Como faço para calcular o azimute (ângulo para o norte) entre duas coordenadas WGS84

StackOverflow https://stackoverflow.com/questions/642555

  •  22-07-2019
  •  | 
  •  

Pergunta

Eu tenho duas coordenadas WGS84, latitude e longitude em graus. Estes pontos são bastante próximas umas das outras, por exemplo apenas um metro de distância.

Existe uma maneira fácil de calcular o azimute da linha entre esses pontos, isto é, o ângulo para o norte?

A abordagem ingênua seria assumir um sistema de coordenadas cartesianas (porque estes pontos são tão próximas umas das outras) e usar apenas

sin (a) = abs (L2-L1) / sqrt (sqr (L2-L1) + sqr (B2-B1))

a = azimute L1, L2 = longitude B1, B2 = latitude

O erro será maior como as coordenadas afastar-se do equador porque há a distância entre dois graus longitudinais torna-se cada vez mais pequeno do que aquele entre dois graus de latitude (que permanece constante).

Eu encontrei algumas fórmulas muito complexas, que eu realmente não querem implementar, porque eles parecem ser um exagero para pontos que são que, juntos, perto e eu não preciso de muito alta precisão (duas casas decimais são suficientes, é provavelmente bem ou desde que há outros fatores que reduzem a precisão de qualquer maneira, como a que o GPS retornos).

Talvez eu pudesse determinar um factor de correcção longitudinal aproximado dependendo da latitude e da utilização somthing como este:

sin (a) = abs (L2 * f-L1 * f) / sqrt (sqr (L2 * f-L1 * f) + sqr (B2-B1))

onde f é o fator de correção

Alguma dica?

(Eu não quero usar qualquer bibliotecas para isso, especialmente não aqueles que requerem licenças de tempo de execução. Qualquer MPLed Delphi Source seria ótimo.)

Foi útil?

Solução

As fórmulas que você se refere no texto são para calcular a distância ortodrómica entre 2 pontos. Aqui está como eu calcular o ângulo entre os pontos:

uses Math, ...;
...

const
  cNO_ANGLE=-999;

...

function getAngleBetweenPoints(X1,Y1,X2,Y2:double):double;
var
  dx,dy:double;
begin
  dx := X2 - X1;
  dy := Y2 - Y1;

  if (dx > 0) then  result := (Pi*0.5) - ArcTan(dy/dx)   else
  if (dx < 0) then  result := (Pi*1.5) - ArcTan(dy/dx)   else
  if (dy > 0) then  result := 0                          else
  if (dy < 0) then  result := Pi                         else
                    result := cNO_ANGLE; // the 2 points are equal

  result := RadToDeg(result);
end;
  • Lembre-se de lidar com a situação em que 2 pontos são iguais (verificação se o resultado for igual cNO_ANGLE, ou modificar a função para lançar uma exceção);

  • Esta função assume que você está em uma superfície plana. Com as pequenas distâncias que você mencionou isso é tudo bem, mas se você estiver indo para ser calcular o título entre as cidades de todo o mundo que você pode querer olhar para algo que toma a forma da terra na contagem;

  • É melhor para fornecer essa função com coordenadas que já estão mapeados para uma superfície plana. Você poderia alimentar WGS84 Latitude diretamente em Y (e lon em X) para obter uma aproximação grosseira embora.

Outras dicas

Aqui está a solução C #. Testado para 0, 45, 90, 135, 180, 225, 270 e 315 ângulos.

Editar eu substituí minha solução feia anterior, pelo C # tradução de solução de Wouter:

public double GetAzimuth(LatLng destination)
{
    var longitudinalDifference = destination.Lng - this.Lng;
    var latitudinalDifference = destination.Lat - this.Lat;
    var azimuth = (Math.PI * .5d) - Math.Atan(latitudinalDifference / longitudinalDifference);
    if (longitudinalDifference > 0) return azimuth;
    else if (longitudinalDifference < 0) return azimuth + Math.PI;
    else if (latitudinalDifference < 0) return Math.PI;
    return 0d;
}

public double GetDegreesAzimuth(LatLng destination)
{
    return RadiansToDegreesConversionFactor * GetAzimuth(destination);
}

Eu encontrei este link

http://williams.best.vwh.net/avform.htm

dada na resposta à

Lat / Lon + Distância + ponto -> Lat / Lon

Este parece promissor, especialmente à aproximação Terra plana dada perto do fim.

Isso funcionaria apenas para pequenas diferenças. Caso contrário, você não pode simplesmente "latitudinalDifference / longitudinalDifference".

Eu recomendaria a implementação de um fator de correção baseado na longitude. I implementada uma rotina de simular uma vez para retornar todos os registros georreferenciados dentro x milhas de um ponto específico e correu para questões simular. Infelizmente eu não tenho o código mais, e não consigo lembrar como cheguei ao número de correção, mas você está no caminho certo.

Alguém já testou isso? Ela não retorna as respostas corretas

Esta função assume que você está em uma superfície plana. Com as pequenas distâncias que você mencionou isso é tudo bem, mas se você estiver indo para ser calcular o título entre as cidades de todo o mundo que você pode querer olhar para algo que toma a forma da terra na contagem;

A sua terra plana tem pouco a ver com isso. O erro, como lhe chamam, é porque você está calculando um azimute inicial de um ponto. A menos que você está indo direto a um poste, você relação ao pólo vai mudar com a distância. Independentemente disso, o programa acima não retorna resultados corretos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top