Запрос расстояния SQL без тригонометрии

У меня есть база данных SQLite, которая не поддерживает триггерные функции. Я хотел бы отсортировать набор пар широты и долготы в моей таблице по расстоянию по сравнению со второй парой широты и долготы. Я знаком со стандартной формулой гаверсинуса для сортировки пар широты и долготы по расстоянию.

В этом случае меня не особо заботит точность, мои точки разделены большими расстояниями, поэтому я не против округлить расстояния, рассматривая кривые как прямые.

На мой вопрос, есть ли общепринятая формула для такого рода запросов? Помните, никаких триггерных функций!


person Ben Holland    schedule 01.07.2011    source источник
comment
Не могли бы вы получить расстояния широты и долготы отдельно (абсолютные значения), а затем применить pythag (там нет триггера), чтобы получить число, представляющее длину расстояния между точками. Не обращайте на меня внимания, если это чушь - не очень разбираюсь в гео, но меня поразило, что все можно рассматривать как треугольники.   -  person Jon Egerton    schedule 01.07.2011


Ответы (4)


Если ваши точки находятся на разумном расстоянии друг от друга (т. Е. Не через половину земного шара и не через линию даты), вы можете внести поправку на разницу между широтой и долготой (поскольку градус долготы короче, за исключением экватора. ), а затем просто вычислите расстояние, как если бы Земля была плоской.

Поскольку вы просто хотите отсортировать значения, вам даже не нужно использовать квадратный корень, вы можете просто добавить квадраты разностей.

Пример, где @lat и @lng - ваше текущее положение, а 2 - поправка разницы:

select *
from Points
order by (lat - @lat) * (lat - @lat) + ((lng - @lng) * 2) * ((lng - @lng) * 2)

Вы можете рассчитать поправку на разницу для определенной широты как 1 / cos(lat).


Сес Тиммерман придумал эту формулу, которая также работает через линию дат:

pow(lat-lat2, 2) + pow(2 * min(abs(lon-lon2), 360 - abs(lon-lon2)), 2)
person Guffa    schedule 01.07.2011
comment
@downvoter: Почему голосование против? Если вы не объясните, что вы считаете неправильным, это не улучшит ответ. - person Guffa; 01.07.2011
comment
Я также не понимаю, почему этот ответ был отвергнут. Пожалуйста, объясни. - person Ben Holland; 03.07.2011
comment
pow(lat - @lat, 2) + pow(2 * (lon - @lon), 2) короче и отличается от языковой переменной, но какой окончательный запрос корректирует широту? Есть ли в этом возможные проблемы Россия-Аляска? - person Cees Timmerman; 29.03.2012
comment
@CeesTimmerman: Это 2 *, который корректирует широту. Например, на Аляске значение поправки будет между 1,6 и 3,2, в зависимости от широты. - person Guffa; 29.03.2012
comment
Ясно спасибо. Вероятно, голос против этого алгоритма все еще идет неверным путем во время путешествия между Россией и Аляской: pow (60-60, 2) + pow (2 * (150-150), 2) = 360000.0 - person Cees Timmerman; 30.03.2012
comment
Пока вы не пересекаете полюса, pow(lat - lat2, 2) + pow(2 * min(abs(lon - lon2), abs((180 - abs(lon)) + (180 - abs(lon2)))), 2) должно сойтись. (14400.0 из Стерлингов в Россию.) - person Cees Timmerman; 01.04.2012
comment
@CeesTimmerman: Хорошее дополнение. Я разъяснил ограничения исходного алгоритма. - person Guffa; 01.04.2012
comment
Спасибо. Немного улучшил: pow(lat-lat2, 2) + pow(2 * min(abs(lon-lon2), 360 - abs(lon-lon2)), 2) - person Cees Timmerman; 01.04.2012
comment
@sajanyamaha, спасибо. Большинству серверов требуется этот сложный обходной путь, что делает его square(lat-lat2) + square(2 * case when abs(lon-lon2) < 360 - abs(lon-lon2) then abs(lon-lon2) else 360 - abs(lon-lon2) end). - person Cees Timmerman; 25.01.2013
comment
Если я могу спросить, зачем нужна коррекция разницы? - person Fuseteam; 25.04.2016
comment
@Fuseteam: В противном случае расстояние с востока на запад было бы преувеличено по сравнению с расстоянием с севера на юг. - person Guffa; 26.04.2016
comment
@guffa по сравнению с тем, что это связано с тем, что Земля не является идеальной сферой? Интересный - person Fuseteam; 26.04.2016
comment
@Fuseteam: Нет, это потому, что Земля представляет собой шар. Значения долготы становятся ближе друг к другу, когда вы приближаетесь к полюсам. - person Guffa; 26.04.2016
comment
@guffa о, понятно, спасибо за помощь, я думаю, теперь я понимаю - person Fuseteam; 26.04.2016
comment
теперь я думаю об этом, не было бы проще просто определить функцию, такую, что Limitation(L,L2){if(abs(L-L2) < 360 - abs(L-L2)) abs(L-L2); else 360 - abs(L-L2);}, а затем передать долготу, широту можно передать аналогичной функции только 90 вместо 180, таким образом, ограничения этой формулы могут быть решены .. ........ я думаю, кстати, есть ли у этой формулы возможные проблемы на экваторе? - person Fuseteam; 24.08.2016
comment
@Fuseteam: Нет, на экваторе проблем нет, поскольку значения просто меняются с положительных на отрицательные. Однако могут возникнуть проблемы, если вы находитесь очень близко к полюсу, поскольку ближайшее расстояние будет считаться кривой вокруг полюса, а не линией, пересекающей полюс. (В небольшой степени это применимо везде, но везде на суше (кроме Антарктиды) разница достаточно мала.) - person Guffa; 27.08.2016
comment
Но что же тогда вызывает проблемы на международной линии свиданий? - person Fuseteam; 27.08.2016
comment
@Fuseteam: Это когда долгота колеблется от +180 до -180. - person Guffa; 28.08.2016
comment
так что это только при скачках между 180 и -180, но не между положительным и отрицательным в целом, я вижу, и поскольку он где-нибудь на суше, разница достаточно мала, ограничение полюсов не требует решения, я вижу. - person Fuseteam; 28.08.2016

Если вам нужны правильные пространственные данные в вашей модели, используйте SpatiaLite, версию SQLite с пространственной поддержкой:

http://www.gaia-gis.it/spatialite/

Это как PostGIS для PostgreSQL. Все ваши функции SQLite будут работать безупречно и без изменений, и вы также получите пространственные функции.

person Spacedman    schedule 01.07.2011
comment
Спасибо, это интересно, но я не уверен, что хочу сейчас менять коннекторы базы данных. Проголосуйте за классную ссылку! - person Ben Holland; 01.07.2011
comment
Но это правильный способ сделать это. Вы должны укусить пулю сейчас и перейти к чему-то действительно пространственному - это того стоит. - person TheSteve0; 20.07.2011

Вы всегда можете усечь синус в ряд Тейлора и использовать тот факт, что sin ^ 2 ( x) + cos ^ 2 (x) = 1, чтобы получить приближение косинуса. Единственная сложная часть - это использование теоремы Тейлора для оценки количества терминов, которые вам понадобятся для с заданной точностью.

person Community    schedule 01.07.2011
comment
Хотел бы я понять, о чем вы говорите. - person Cees Timmerman; 29.03.2012
comment
Приятные образы! радианы (градусы% 180) и 7 членов выглядят хорошо, не так ли? - person Cees Timmerman; 01.04.2012
comment
Я исправил это в Python, но по-прежнему 0,5 для 180 и -180. - person Cees Timmerman; 01.04.2012

Замена "*" на "/" у меня работает:

выберите * в порядке точек по (lat - @lat) * (lat - @lat) + ((lng - @lng) / 2) * ((lng - @lng) / 2)

person Andreoid    schedule 02.05.2013