Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Формулы для расчета географической близости

Автор вопроса: Alix AxelОтветов: 2

Мне нужно реализовать поиск близости Geo в моем приложении, но я очень запутался в правильной формуле для использования. После некоторых поисков в Интернете и в StackOverflow я обнаружил, что решения следующие:

  1. Используйте формулу гаверсина
  2. Используйте Формулу расстояния большого круга
  3. Используйте систему пространственного поиска в базе данных

Вариант №3 действительно не вариант для меня банкомат. Я немного сбит с толку, поскольку всегда думал, что Формула расстояния по Большому кругу и формула Хаверсина были синонимами, но, видимо, я ошибался?

Приведенный выше снимок экрана был взят из великолепного географического (близкого) поиска с помощью MySQL paper и использует следующие функции:

ASIN, SQRT, POWER, SIN, PI, COS

Я также видел варианты от той же формулы (Сферический закон косинусов), например этот:

(3956 * ACOS(COS(RADIANS(o_lat)) * COS(RADIANS(d_lat)) * COS(RADIANS(d_lon) - RADIANS(o_lon)) + SIN(RADIANS(o_lat)) * SIN(RADIANS(d_lat))))

Это использует следующие функции:

ACOS, COS, RADIANS, SIN

Я не математик, но одинаковы ли эти формулы? Я встречал еще несколько вариантов и формул (например, Сферический закон косинусов и формулы Винсенти точнее всего) и это меня еще больше сбивает с толку ...

Мне нужно выбрать хорошую формулу общего назначения для реализации в PHP / MySQL. Может ли кто-нибудь объяснить мне различия между формулами, которые я упомянул выше?

  • Какой из них вычисляется быстрее всего?
  • Какой из них обеспечивает наиболее точные результаты?
  • Какой из них лучший с точки зрения скорости / точности результатов?

Я ценю ваше понимание этих вопросов.


Основываясь на ответе theonlytheory, я протестировал следующие формулы расстояния большого круга:

  • Формула Винсенти
  • Формула гаверсина
  • Сферический закон косинусов

Формула Винсенти очень медленная, но довольно точная (до 0,5 мм).

Формула Хаверсина намного быстрее, чем формула Винсенти, я смог выполнить 1 миллион вычислений примерно за 6 секунд, что вполне приемлемо для моих нужд.

Формула сферического закона косинусов оказалась почти в два раза быстрее, чем формула Хаверсинуса, а разница в точности заключается в пренебрежении для большинства случаев использования.


Вот несколько тестовых мест:

  • Штаб-квартира Google (37.422045, -122.084347)
  • Сан-Франциско, Калифорния (37.77493, -122.419416)
  • Эйфелева башня, Франция (48.8582, 2.294407)
  • Оперный театр, Сидней (-33.856553, 151.214696)

Штаб-квартира Google - Сан-Франциско, Калифорния:

  • Формула Винсенти: 49 087.066 meters
  • Формула Хаверсина: 49 103.006 meters
  • Сферический закон косинусов: 49 103.006 meters

Штаб-квартира Google - Эйфелева башня, Франция:

  • Формула Винсенти: 8 989 724.399 meters
  • Формула Хаверсина: 8 967 042.917 meters
  • Сферический закон косинусов: 8 967 042.917 meters

Штаб-квартира Google - Оперный театр, Сидней:

  • Формула Винсенти: 11 939 773.640 meters
  • Формула Хаверсина: 11 952 717.240 meters
  • Сферический закон косинусов: 11 952 717.240 meters

Как видите, нет заметной разницы между формулой Хаверсинуса и сферическим законом косинусов, однако оба имеют смещение расстояния до 22 километров по сравнению с формулой Винсенти, потому что он использует эллипсоидальное приближение Земли вместо сферического.

  • У меня была похожая проблема давно, в проекте, который я никогда не начинал ... в своих заметках я нашел эту формулу: AB=sqrt(pow(($Xb-$Xa),2)+pow(($Yb-$Ya),2)));, я никогда не понимал, что именно он делает ... надеюсь, может вам помочь;) Strae 20.01.2010
  • @DaNieL: Проверьте ответ theonlytheory, он объясняет, когда следует использовать указанную вами формулу. знак равно Alix Axel 20.01.2010
  • FWIW: для тех, кого смущает 3956, то есть радиус Земли в милях, однако, согласно Википедии, это должно быть приблизительно 3959 en.wikipedia.org/wiki/Earth_radius, если вы хотите работать с расстояниями в км, которые вместо этого будут 6371. Я не уверен, повлияет ли это на ваш ответ @Alix, но в зависимости от того, какой # вы использовали, ваши единицы могут быть выключены и вместо этого должны быть в милях. Chris Marisic 29.10.2010
  • Если ваш "диапазон поиска" достаточно мал ( Rudie 16.05.2011
  • Кстати: orig.lat - dest.lat не ошибается с координатами [-180, 180]? Что будет, если orig.lat = -170 и dest.lat = 170? Дистанция 340 град? Нет, на самом деле их всего 20. Как решить эту проблему, если вы работаете с реальными координатами Земли (атласом)? Rudie 16.05.2011
  • pow(lat-lat2, 2) + pow(1/cos(radians(lat)) * min(abs(lon-lon2), 360-abs(lon-lon2)), 2) = ›distance_squared Cees Timmerman 05.04.2012

phpgeomathgeospatial

Ответы

Ответ 1 · рейтинг 36 · morpheus

Закон косинусов и формула Хаверсинуса дадут идентичные результаты, если предположить, что машина обладает бесконечной точностью. Формула Хаверсина более устойчива к ошибкам с плавающей запятой. Однако современные машины имеют двойную точность порядка 15 значащих цифр, и закон косинусов может отлично работать для вас. Обе эти формулы предполагают сферическую Землю, тогда как итерационное решение Викенти (наиболее точное) предполагает эллипсоидальную Землю (на самом деле Земля даже не эллипсоид - это геоид). Некоторые ссылки: http://www.movable-type.co.uk/scripts/gis-faq-5.1.html

Становится лучше: обратите внимание, что широта будет использоваться в законе косинусов, так как хаверсин - это геоцентрическая широта, которая отличается от геодезической широты. Для сферы это одно и то же.

Какой из них вычислить быстрее всего?

В порядке от самого быстрого к самому медленному: закон косинусов (5 тригг. Вызовов) -> гаверсинус (включает sqrt) -> Vicenty (необходимо решать итеративно в цикле for)

Какой из них самый точный?

Vicenty.

Какой из них лучше, если учитывать скорость и точность?

Если ваша проблемная область такова, что для расстояний, которые вы пытаетесь рассчитать, Земля может считаться плоской, тогда вы можете разработать (я не буду приводить подробности) формулу вида x = kx * разница в долготе , y = ky * разница в широте. Тогда расстояние = sqrt (dx dx + dy dy). Если ваша проблемная область такова, что ее можно решить с помощью квадрата расстояния, вам не придется использовать sqrt, и эта формула будет максимально быстрой. Дополнительное преимущество заключается в том, что вы можете рассчитать расстояние vector: x - это расстояние в восточном направлении, а y - это расстояние в северном направлении. В противном случае поэкспериментируйте с 3 и выберите то, что лучше всего работает в вашей ситуации.

Ответ 2 · рейтинг 12 · BASTA

Итак, вы хотите:

  • сортировать записи по расстоянию от p0
  • выбрать только записи, расстояние от которых до p0 меньше r

Хитрость в том, что для этого не нужно точно вычислять расстояние по большому кругу! Вы можете использовать любую функцию от пары точек до реального значения , которое строго растет с увеличением расстояния между точками по большому кругу. Таких функций много, и некоторые из них вычисляются намного быстрее, чем различные формулы для определения точного расстояния по большой окружности. Одна из таких функций - евклидово расстояние в 3D. Преобразование широты и долготы в трехмерную точку на сфере не требует обратных тригонометрических функций.

Когда у вас есть x, Y, Z, вы можете понять, что вам на самом деле не нужно расстояние от p0 до вашей точки, потому что вы также можете использовать расстояние от касательной плоскости в p0. Это расстояние также строго растет с увеличением расстояния по большому кругу и вычисляется из X, Y, Z как линейной комбинации - даже квадратный корень не требуется. Вам просто нужно предварительно вычислить коэффициенты и расстояние отсечки, которое соответствует желаемому расстоянию по большой окружности.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы