У меня есть таблица MySQL с пространственными точками, и вам нужно рассчитать расстояния. Я нашел много материала для этого, используя формулу Хаверсина, однако все они предполагают большое расстояние между точками. В моем случае я забочусь только о коротких дистанциях (< 1 миля), поэтому мне не нужно исправлять кривизну земли. Моя интуиция использует формулу Хаверсина, которая будет неточной на таких небольших расстояниях. Какие-либо предложения?Расчет коротких расстояний между точками lat/long
ответ
Ваша интуиция неверна. Рассмотрим формулу гаверсинуса и определение гаверсинуса, согласно Википедии (φ является широта и ψ долгота):
Существует еще что имеет значение: для малых значений θ, sin θ приблизительно равно equa л до θ; более релевантно, это приблизительно linear in θ. Поэтому haversin θ будет приблизительно (θ/2) ². Это приближение улучшается по мере приближения к нулю.
Если широта и долгота близки друг к другу, то φ ₂ - φ ₁ и ψ ₂ - ψ ₁, что то, что функция гаверсинуса применяется к здесь, будет близка к нулю это означает, что формула приблизительно
(д/2r) ² = ((φ ₂ - φ ₁)/2) ² + Cos (ф ₁) сов (φ ₂) ((ψ ₂ - ψ ₁)/2) ²
Теперь заметим, что эта формула имеет ту же форму, как евклидово расстояние в двух измерениях с некоторыми произвольными коэффициентами масштабирования (напомним, что (кх) ² = к ² х ² поэтому мы можем двигаться константы в и из квадратов):
к ₁ d ² = к ₂ Δ φ ² + к ₃ Δ ψ ²
Наконец, я утверждаю без доказательства, что эти произвольные коэффициенты масштабирования оказываются те же самые которые преобразуют изменения широты/долготы в линейное расстояние.
Следовательно, формула haversine не неточна для небольших расстояний; он точно такой же, как обычный расчет евклидова расстояния, в пределе малых расстояний.
Создайте очки, используя значение точки типов данных геометрии в MyISAM таблицы
Создать Пространственный индекс на этих точках
Используйте MBRContains(), чтобы найти значение:
SELECT *
FROM table
WHERE MBRContains(LineFromText(CONCAT(
'('
, @lon + 10/(111.1/cos(RADIANS(@lon)))
, ' '
, @lat + 10/111.1
, ','
, @lon - 10/(111.1/cos(RADIANS(@lat)))
, ' '
, @lat - 10/111.1
, ')')
,mypoint)
, или, в MySQL 5.1 и выше:
SELECT *
FROM table
WHERE MBRContains
(
LineString
(
Point
(
@lon + 10/(111.1/COS(RADIANS(@lat))),
@lat + 10/111.1
)
Point
(
@lon - 10/(111.1/COS(RADIANS(@lat))),
@lat - 10/111.1
)
),
mypoint
)
Это выберет все точки, расположенные примерно в пределах поля (@lat +/- 10 км, @lon +/- 10 км).
Это фактически не коробка, а сферический прямоугольник: широта и долгота связанный сегмент сферы. Это может отличаться от простого прямоугольника на Земле Франца-Иосифа, но довольно близко к нему на большинстве населенных мест.
Применить дополнительную фильтрацию, чтобы выбрать все внутри круга (не квадрат)
Возможно применять дополнительную тонкую фильтрацию для учета большого расстояния окружности (на большие расстояния)
Вы, вероятно, избегайте рассмотрения записей как плоского треугольника и просто используйте синус-закон. Однако Haversine НЕ будет неточным для небольших или больших расстояний ... это БОЛЬШЕ точной, чем предполагать, что Земля плоская. Хаверсин - частный случай сферического аналога закона синуса. –