Algorytm do kompensowania szerokości / długości geograficznej o pewną liczbę metrów

108

Szukam algorytmu, który po podaniu pary szerokości i długości geograficznej oraz translacji wektora w metrach we współrzędnych kartezjańskich (x, y) dałby mi nową współrzędną. Coś jak odwrotna Haversine. Mógłbym również pracować z transformacją odległości i kursu, ale prawdopodobnie byłoby to wolniejsze i nie tak dokładne. Idealnie, algorytm powinien być szybki, ponieważ pracuję na systemie wbudowanym. Dokładność nie jest krytyczna, w odległości 10 metrów byłoby dobrze.

Thomas O
źródło
Więc dobrze byłoby modelować Ziemię jako kulę?
podmroku
1
Tak, byłoby dobrze, ponieważ oczekuję przesunięć <1 km.
Thomas O

Odpowiedzi:

107

Jeśli twoje przemieszczenia nie są zbyt duże (mniej niż kilka kilometrów) i nie masz racji na biegunach, skorzystaj z szybkiej i brudnej prognozy, że 111 111 metrów (111,111 km) w kierunku y wynosi 1 stopień (szerokości geograficznej) i 111.111 * cos (szerokość geograficzna) metrów w kierunku x wynosi 1 stopień (długości geograficznej).

Whuber
źródło
3
@ Thomas: Tak naprawdę możesz być bardzo blisko biegunów. Sprawdziłem na podstawie obliczeń UTM, stosując równe przesunięcia xiy wynoszące 1400 m (więc całkowite przesunięcie wynosi 2 km). Wyniki są dobre do 8,6 metra lub lepiej. Najgorsza szerokość geograficzna (dla tego kierunku i wielkości przemieszczenia) wynosi 81 stopni: przybliżenie staje się dokładniejsze, gdy poruszasz się na północ, a jego błąd utrzymuje się poniżej 10 metrów, dopóki nie przekroczysz 89,6 stopnia!
whuber
60
Nawiasem mówiąc, te magiczne liczby 111 111 są łatwe do zapamiętania dzięki znajomości historii: Francuzi pierwotnie zdefiniowali licznik, tak aby 10 ^ 7 metrów oznaczało odległość wzdłuż południka paryskiego od równika do bieguna północnego. Zatem 10 ^ 7/90 = 111 1111,1 metra to jeden stopień szerokości geograficznej w granicach możliwości francuskich geodetów dwa wieki temu.
whuber
3
Więc jeśli we wzorze chcę przesunąć o + 100 m w kierunku y od powiedzmy 10,0 N, 10,0 E, czy po prostu dodam 100/111111? Czy poruszając się w kierunku x + 100 m, byłoby to 100 ÷ (11111 × (cos 10))? Tylko upewniam się, że mam rację.
Thomas O
5
@ Thomas Tak, zgadza się. Zwróć uwagę, jak druga formuła rozszerza pozorne przesunięcie x (dzięki dzieleniu przez liczbę mniejszą niż 1) tak, jak powinna, ponieważ stopień długości geograficznej zmniejsza się, gdy zbliżasz się do biegunów od równika. Jedynym potencjalnym problemem jest upewnienie się, że ty i twoja platforma oprogramowania zgadzacie się co to znaczy „cos”: lepiej interpretować cos (10) jako cosinus 10 stopni , a nie 10 radianów! (Jeśli nie, 10 stopni = 10 * pi / 180 radianów ilustruje prostą konwersję.) W tym momencie kod oferowany przez @haakon_d powinien mieć dla Ciebie pełny sens.
whuber
7
Ktoś próbował edytować tę odpowiedź, zastępując „metry” przez „km”. Prawdopodobnie czytali przecinek „” w europejskim znaczeniu dziesiętnym. Postępuję zgodnie z konwencją amerykańską (która, jak sądzę, jest również konwencją publikacji międzynarodowych), dotyczącą używania przecinka do rozdzielania ciągów cyfr długich na grupy po trzy i kropkę dziesiętną „”. zamiast przecinka. (To użycie jest wyraźnie pokazane w poprzednich komentarzach.) Aby uniknąć dwuznaczności, zredagowałem odpowiedź, aby wyraźnie pokazać, co oznaczają przecinek i kropka.
whuber
56

Jak mówi Liedman w swojej odpowiedzi, formuły lotnicze Williamsa są nieocenionym źródłem, a aby zachować dokładność do 10 metrów w przypadku przemieszczeń do 1 km, prawdopodobnie będziesz musiał użyć bardziej złożonego z nich.

Ale jeśli chcesz zaakceptować błędy powyżej 10 m dla punktów przesuniętych o więcej niż około 200 m, możesz użyć uproszczonego obliczenia płaskiej ziemi. Myślę, że błędy nadal będą mniejsze niż 50 m dla przesunięć do 1 km.

 //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 

To powinno zwrócić:

 latO = 51,00089832
 lonO = 0,001427437
haakon_d
źródło
7
Chciałbym tylko zaznaczyć, że jest to odpowiedź identyczna z odpowiedzią, którą udzieliłem, z tą różnicą, że zastąpiłem moją wartość 111 111 metrów na stopień przez 111 319,5. Twoja wartość jest nieco lepsza na dużych szerokościach geograficznych, ale nieco gorsza na niższych szerokościach geograficznych (od 0 do około 40 stopni). Każda z tych wartości spełnia podane wymagania dotyczące dokładności.
whuber
1
+1 za podanie kodu. Pamiętaj, że jest on dokładniejszy, niż podejrzewasz (błąd wynosi zwykle mniej niż 5 m na 2000 m).
whuber
1
Zastanawiałem się, czy powinienem dodać uwagę w mojej odpowiedzi, że jest to identyczne rozwiązanie dla ciebie, z wyjątkiem wartości R, ale pominąłem ją ze względu na zwięzłość. Jeśli chodzi o precyzję, masz rację, o ile nie dodasz żadnych błędów obrotowych do systemu. Wykorzystując przesunięcia mierzone w lokalnym rzutowanym układzie współrzędnych, błędy rotacji mogą rosnąć dość duże.
haakon_d
1
To doskonały punkt: domyślnie założyliśmy, że przesunięcie x jest co najmniej zbliżone do prawdziwego wschodu i zachodu, a przesunięcie y jest bliskie północ-południe. Jeśli nie, należy je przeliczyć na równoważne przesunięcia EW i NS (nie tylko „wschody” i „północy”) przed obliczeniem ich ekwiwalentów lat-lon.
whuber
Parametr d odległości równań formuły lotniczej jest w radianach, np. (Odległość / promień ziemi).
user1089933,
23

Uważam, że Aviation Formulary, tutaj jest świetny dla tego rodzaju formuł i algorytmów. W przypadku swojego problemu sprawdź „podaną długość / długość promieniową i odległość”: tutaj

Należy pamiętać, że ten algorytm może być zbyt skomplikowany, aby można było z niego korzystać, jeśli chcesz utrzymać niski poziom funkcji trygonometrii itp.

Liedman
źródło
Dzięki za to - wygląda idealnie. Chociaż nie mogę ustalić, czy odległość jest w metrach, czy w innym pomiarze.
Thomas O
2

Pierwszym punktem może być rzutowanie na punkt. Możesz zrobić coś takiego jak ten pseudo-kod:

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

gdzie (x, y) jest pożądanym przesunięciem.

Nie musisz używać utm, dowolnego płaskiego układu współrzędnych, który ma sens w twojej okolicy.

Z jakim oprogramowaniem pracujesz?

MartinHvidberg
źródło