Алгоритм смещения широты / долготы на некоторое количество метров

108

Я ищу алгоритм, который при задании пары широты и долготы и перевода вектора в метрах в декартовых координатах (x, y) дал бы мне новую координату. Вроде как обратный Haversine. Я мог бы также работать с преобразованием расстояния и курса, но это, вероятно, будет медленнее и не так точно. В идеале алгоритм должен быть быстрым, так как я работаю над встроенной системой. Точность не критична, в пределах 10 метров было бы хорошо.

Томас О
источник
Таким образом, вы будете в порядке моделировать Землю как сферу?
Подземье
1
Да, это было бы хорошо, так как я ожидаю смещения <1 км.
Томас О

Ответы:

107

Если ваши смещения не слишком велики (менее нескольких километров), и вы не правы на полюсах, воспользуйтесь быстрой и грязной оценкой, что 111 111 метров (111 111 км) в направлении у составляют 1 градус (широты) и 111 111 * cos (широта) метров в направлении x составляет 1 градус (долготы).

Whuber
источник
3
@ Томас: На самом деле, вы можете быть очень близко к полюсам. Я проверил по расчету UTM, используя равные смещения по x и y 1400 м (таким образом, общее смещение составляет 2 км). Результаты хороши до 8,6 метров или лучше. Наихудшая широта (для этого направления и величины смещения) составляет 81 градус: аппроксимация на самом деле становится более точной, когда вы двигаетесь на север, и ее ошибка остается ниже 10 метров, пока вы не превысите 89,6 градуса!
whuber
60
Между прочим, эти магические числа 111111 легко запомнить, зная некоторую историю: французы первоначально определили метр так, чтобы 10 ^ 7 метров было расстоянием вдоль парижского меридиана от экватора до северного полюса. Таким образом, 10 ^ 7/90 = 111 111,1 метра равняется одному градусу широты в пределах возможностей французских геодезистов два столетия назад.
whuber
3
Итак, с формулой, если бы я хотел переместиться на + 100 м в направлении y, скажем, от 10,0 N до 10,0 E, я бы просто добавил 100/111111? Если двигаться в направлении х + 100 м, будет ли это 100 ÷ (111 111 × (cos 10))? Просто убедившись, что я правильно понял.
Томас О
5
@ Томас Да, все верно. Обратите внимание, как вторая формула расширяет видимое смещение по оси x (путем деления на число меньше 1), как и должно быть, потому что степень долготы уменьшается по мере движения к полюсам от экватора. Единственная потенциальная проблема - убедиться, что вы и ваша программная платформа согласны с тем, что означает «cos»: лучше интерпретировать cos (10) как косинус 10 градусов , а не 10 радиан! (Если нет, то 10 градусов = 10 * пи / 180 радиан иллюстрируют простое преобразование.) На этом этапе код, предлагаемый @haakon_d, должен иметь для вас полный смысл.
whuber
7
Кто-то пытался отредактировать этот ответ, чтобы заменить «метры» на «км». Они, вероятно, читали запятую "," в европейском смысле десятичной точки. Я следую американскому соглашению (которое, по моему мнению, является соглашением международных публикаций) использования запятой для разделения длинноразрядных строк на группы из трех и десятичной точки "." вместо запятой. (Это использование ясно показано в предыдущих комментариях.) Чтобы избежать двусмысленности, я отредактировал ответ, чтобы ясно показать, что означают запятая и точка.
whuber
56

Как говорит Лидман в своем ответе, авиационные формулы Уильямса являются бесценным источником, и чтобы сохранить точность в пределах 10 метров для перемещений до 1 км, вам, вероятно, придется использовать более сложные из них.

Но если вы готовы принять ошибки свыше 10 м для точек со смещением более 200 м, вы можете использовать упрощенный расчет плоской земли. Я думаю, что ошибки все равно будут менее 50 м для смещений до 1 км.

 //Position, decimal degrees
 lat = 51.0
 lon = 0.0

 //Earth’s radius, sphere
 R=6378137

 //offsets in meters
 dn = 100
 de = 100

 //Coordinate offsets in radians
 dLat = dn/R
 dLon = de/(R*Cos(Pi*lat/180))

 //OffsetPosition, decimal degrees
 latO = lat + dLat * 180/Pi
 lonO = lon + dLon * 180/Pi 

Это должно вернуть:

 latO = 51,00089832
 lonO = 0,001427437
haakon_d
источник
7
Я просто хочу отметить, что это совпадает с ответом, который я дал, за исключением того, что вы заменили мое значение 111 111 метров на градус на 111 319,5. Ваше значение немного лучше в высоких широтах, но немного хуже в более низких широтах (от 0 до примерно 40 градусов). Любое значение соответствует заявленным требованиям точности.
whuber
1
+1 за предоставление кода. Обратите внимание, что это более точно, чем вы подозреваете (ошибка обычно меньше 5 м над 2000 м).
whuber
1
Я задавался вопросом, должен ли я добавить замечание в своем ответе, что это идентичное вашему решению, за исключением значения R, но из-за краткости не учел его. Когда дело доходит до точности, вы правы до тех пор, пока не добавите в систему никаких ошибок вращения. При использовании смещений, измеренных в локальной проекционной системе координат, погрешности вращения могут возрасти.
haakon_d
1
Это превосходный момент: мы неявно предположили, что смещение по оси x, по крайней мере, близко к истинному востоку и западу, а смещение по оси y близко к северу и югу. Если нет, то они должны быть преобразованы в эквивалентные смещения EW и NS (не только «восточные» и «северные»), прежде чем вычислять их латоновые эквиваленты.
whuber
Параметр расстояния d в формулах Авиационного формуляра выражен в радианах, например (расстояние / радиус земли).
user1089933
23

Я считаю, что Aviation Formulary, здесь отлично подходит для этих типов формул и алгоритмов. Для вашей проблемы, проверьте "широта / длинна с учетом радиуса и расстояния": здесь

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

Liedman
источник
Спасибо за это - выглядит идеально. Хотя я не могу понять, если расстояние в метрах или какое-то другое измерение.
Томас О
2

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

falt_coordinate = latlon_to_utm(original_koordinate)
new_flat_coordinate = flat_coordinate + (x,y)
result_coordinate = utm_to_latlon(new_flat_coordinate)

где (x, y) - желаемое смещение.

Вам не нужно использовать utm, любую плоскую систему координат, которая имеет смысл в вашей области.

С каким программным обеспечением вы работаете?

Мартин
источник