Algoritmo para compensar uma latitude / longitude em alguns metros

108

Estou procurando um algoritmo que, quando for dado um par de latitude e longitude e uma tradução de vetor em metros nas coordenadas cartesianas (x, y), me daria uma nova coordenada. Mais ou menos como um Haversine reverso. Eu também poderia trabalhar com uma transformação de distância e de rumo, mas isso provavelmente seria mais lento e não tão preciso. Idealmente, o algoritmo deve ser rápido, pois estou trabalhando em um sistema incorporado. A precisão não é crítica, pois 10 metros seria bom.

Thomas O
fonte
Então você ficaria bem modelando a Terra como uma esfera?
Underdark
1
Sim, isso seria bom, pois estou esperando compensações <1km.
Thomas O

Respostas:

107

Se seus deslocamentos não forem muito grandes (menos de alguns quilômetros) e você não estiver certo nos polos, use a estimativa rápida e suja de que 111.111 metros (111.111 km) na direção y são 1 grau (de latitude) e 111,111 * cos (latitude) metros na direção x é 1 grau (de longitude).

whuber
fonte
3
@ Thomas: Na verdade, você pode estar muito perto dos postes. Eu verifiquei contra um cálculo UTM usando deslocamentos iguais de x e y de 1400 m (então o deslocamento total é de 2 km). Os resultados são bons para 8,6 metros ou melhor. A pior latitude (para essa direção e quantidade de deslocamento) é de 81 graus: a aproximação fica mais precisa à medida que você se move para o norte e seu erro permanece abaixo de 10 metros até você ultrapassar os 89,6 graus!
whuber
60
A propósito, é fácil lembrar esses números mágicos de 111.111, conhecendo um pouco da história: os franceses originalmente definiram o medidor de modo que 10 ^ 7 metros seriam a distância ao longo do meridiano de Paris do equador ao pólo norte. Assim, 10 ^ 7/90 = 111.111,1 metros equivale a um grau de latitude dentro das capacidades dos pesquisadores franceses dois séculos atrás.
whuber
3
Então, com a fórmula, se eu quisesse mover + 100m na ​​direção y, digamos, 10.0 N, 10.0 E, acrescentaria apenas 100/111111? Se movendo na direção x + 100m, seria 100 ÷ (111,111 × (cos 10))? Apenas certificando-me de que entendi direito.
Thomas O
5
@ Thomas Sim, está certo. Observe como a segunda fórmula expande o deslocamento x aparente (em virtude de dividir por um número menor que 1) como deveria, porque um grau de longitude fica menor à medida que você se move em direção aos pólos do equador. O único problema é garantir que você e sua plataforma de software concordem com o que "cos" significa: é melhor interpretar cos (10) como o cosseno de 10 graus , e não 10 radianos! (Caso contrário, 10 graus = 10 * pi / 180 radianos ilustra a conversão simples.) Nesse ponto, o código oferecido por @haakon_d deve fazer todo o sentido para você.
whuber
7
Alguém tentou editar esta resposta para substituir "metros" por "km". Eles provavelmente estavam lendo a vírgula "," no sentido europeu de um ponto decimal. Sigo a convenção americana (que também acredito que é a publicação internacional) de usar uma vírgula para separar cadeias de dígitos longos em grupos de três e um ponto decimal "." em vez da vírgula. (Esse uso é mostrado claramente nos comentários anteriores.) Para evitar qualquer ambiguidade, editei a resposta para mostrar claramente o que a vírgula e o ponto significam.
whuber
56

Como Liedman diz em sua resposta, as fórmulas de aviação da Williams são uma fonte inestimável, e para manter a precisão em 10 metros para deslocamentos de até 1 km, você provavelmente precisará usar os mais complexos.

Mas se você estiver disposto a aceitar erros acima de 10m para pontos compensados ​​acima de aproximadamente 200m, use um cálculo simplificado de terra plana. Eu acho que os erros ainda serão menores que 50m para compensações de até 1km.

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

Isso deve retornar:

 latO = 51,00089832
 lonO = 0,001427437
haakon_d
fonte
7
Eu só quero ressaltar que isso é idêntico à resposta que eu forneci, exceto que você substituiu meu valor de 111.111 metros por grau por 111.319,5. Seu valor é um pouco melhor em altas latitudes, mas um pouco pior nas latitudes mais baixas (de 0 a cerca de 40 graus). Qualquer valor atende aos requisitos de precisão declarados.
whuber
1
+1 para fornecer código. Observe que é mais preciso do que você suspeita (o erro geralmente é inferior a 5 m acima de 2000 m).
whuber
1
Gostaria de saber se devo adicionar um comentário na minha resposta de que esta é uma solução idêntica à sua, exceto pelo valor de R, mas deixei de fora devido à brevidade. Quando se trata de precisão, você está certo, desde que não adicione nenhum erro de rotação ao sistema. Usando compensações medidas em um sistema de coordenadas local projetado, os erros de rotação podem aumentar bastante.
haakon_d
1
Esse é um ponto excelente: assumimos implicitamente que o deslocamento x é pelo menos próximo do verdadeiro leste-oeste e o deslocamento y é próximo ao norte-sul. Caso contrário, eles devem ser convertidos em deslocamentos equivalentes EW e NS (não apenas "leste" e "norte") antes de calcular seus equivalentes lat-lon.
whuber
O parâmetro d distance das equações do Formulário de Aviação está em radianos, por exemplo (distância / raio da terra).
user1089933
23

Acho que o Formulário de Aviação, aqui é ótimo para esses tipos de fórmulas e algoritmos. Para o seu problema, consulte o "lat / long dado radial e distância": aqui

Observe que esse algoritmo pode ser um pouco complexo demais para seu uso, se você quiser manter baixo o uso das funções trigonométricas, etc.

Liedman
fonte
Obrigado por isso - parece ideal. Embora eu não consiga descobrir se a distância está em metros ou em alguma outra medida.
Thomas O
2

Pode fazer sentido projetar o argumento primeiro. Você poderia criar algo parecido com este pseudo-código:

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

onde (x, y) é o deslocamento desejado.

Você não precisa usar utm, qualquer sistema de coordenadas planas que faça sentido em sua área.

Com qual software você está trabalhando?

MartinHvidberg
fonte