Pergunta

Recebo algumas coordenadas de GPS do Google Maps e preciso encontrar a distância entre eles usando o objetivo C.Implementei a fórmula, mas obtenho resultados muito grandes.

Testei os valores do Google Maps, repassando-os ao Google Earth e a um serviço de geocodificação na internet e tudo confere.Agora estou começando a suspeitar que a lei dos cossenos exige que eu faça algum tipo de conversão com as coordenadas antes de transmiti-las.

Fiz uma implementação semelhante da fórmula Haversine, mas também me deu grandes resultados.Mudei então para o cosseno, pois era mais fácil de depurar e não preciso de muita precisão.

Espero que alguém possa esclarecer um pouco sobre isso ou usar o código :)

- (CGFloat) calculateDistanceBetweenPoints:(CGPoint) origin andDestination:(CGPoint) destination {

//To convert kilometers to miles, divide by 1.609
// x = latitude 
// y = longitude

/* example:
 Dubai      : 25.248665, 55.352917 
 Amsterdam  : 52.309071, 4.763385
 Approx dist: 5,182.62 KM
 Calc. dist : 8,253.33
 */

CGFloat toRad           =   (M_PI / 180);
CGFloat R               =   6371.0f; //earth's mean radius in Km

CGFloat sinePart        =   sinf( origin.x * toRad ) * sinf( destination.x * toRad );
CGFloat cosinePart      =   cosf( origin.x * toRad ) * cosf( destination.x * toRad );
CGFloat deltaCosinePart =   cosf( ( destination.y - origin.y ) * toRad );

CGFloat delta           =   acosf( sinePart + cosinePart * deltaCosinePart) * R;

return delta;
}

Acima calculado a partir de links referenciados aqui:pergunta sobre fluxo de pilha

Foi útil?

Solução

O código pode estar bem, quando eu o executo em seus dados de exemplo (menos alguns lugares decimais), ele retorna 5168.3584

Outras dicas

Você já pensou em usar o método fornecido em CLLocation:

- (CLLocationDistance)getDistanceFrom:(const CLLocation *)location?

Há uma série de perguntas que podem ajudar, incluindo:

Dadas as duas posições, você cria um triângulo esférico com cantos A em Amsterdã, B em Dubai e C no Pólo Norte, com lados a = 90° - ϕAms, b = 90° - ϕDuplicar, e ângulo C = Δλ = λDuplicar - λAms.A resposta obrigatória é o lado c.

Usando algum material da minha resposta ao SO 389211.

(Esta é uma resposta radicalmente revisada - minha tentativa anterior usou o triângulo esférico errado e, portanto, obteve a resposta errada.)


Arte ASCII no seu pior:

                   + C (North Pole)
                  /|
                b/ |
                /  |
(Amsterdam) A  +   | a
                \  |
                c\ |
                  \|
                   + B (Dubai)

A lei básica dos cossenos para triângulos esféricos é:

cos c = cos a . cos b + sin a . sin b . cos C

Observando que cos (90º - x) = sen x e sin (90º - x) = cos x, podemos escrever:

cos c = sen ϕAms .pecado ϕDuplicar + cos ϕAms .porqueϕDuplicar .porque Δλ

O ângulo c em radianos é então convertido em uma distância multiplicando-se pelo raio da Terra.


Aplicando isso aos seus dados:

Dubai: ϕDuplicar = 25.248665°N, λDuplicar = 55.352917°E
Amsterdam: ϕAms = 52.309071°N, λAms = 4.763385°E

Δλ = 50.589532°

Trabalhando com 6 casas decimais para a trigonometria:

cos c = 0.426548 × 0.791320 + 0.904465 × 0.611402 × 0.634872
      = 0.337536            + 0.351079
      = 0.688615

De onde:

c = 46.479426°
  =  0.811219 radians

Multiplicando isso por 6.371 km como o raio nominal da Terra resulta

c = 5168 km

Portanto, para R = 6.371 km, a distância é 0,811219 × 6.371 = 5.168 km (para 4 s.f.).

Verdadeiro Conhecimento diz que deveria ser cerca de 5.155 km.Os dados posicionais usados ​​são comparáveis ​​aos valores que você especificou, e a Wikipedia confirma o raio que você forneceu.Isto é razoavelmente próximo - refazer o cálculo com coordenadas idênticas e mais dígitos no cálculo produziria uma resposta melhor, mas próxima desta.


Pessoal, sinto muito :( e estou com o rosto vermelho.Eu faço alguns outros cálculos nessas coordenadas.Eu calculei a posição (x, y) para que eles posicionem a cidade corretamente em um mapa personalizado que desenhei.Essas coordenadas são calculadas como tal:

- (CGPoint) translateToPixelsFromLatitude:(CGFloat) latitude andLongitude:(CGFloat) longitude {

CGPoint position    = CGPointMake(0, 0);
CGFloat mapWidth    = 300.0f;
CGFloat mapHeight   = 200.0f;

CGFloat offsetX     = 5.0f;
CGFloat offsetY     = 35.0f;

position.x = (((180 + longitude) / 360) * mapWidth) + offsetX;
position.y = (mapHeight - (((90 + latitude) / 180) * mapHeight)) + offsetY;

return position;

}

Por alguns, não deveria codificar no meio da noite e depois ir até o SO para obter ajuda de pessoas ocupadas, por acaso passo as coordenadas transformadas para o método.

Descobri isso quando percebi que ao geocodificar cidades diferentes obtive resultados muito semelhantes e então li a postagem de hic3456 e de repente fez sentido.

Eu registro e testo as coordenadas e a distância de uma classe separada para que tudo seja registrado antes que os dados errados sejam passados ​​para o método.

Agora eu realmente espero que alguém além de mim se beneficie com isso.

Desculpe novamente e obrigado a cada um de vocês.

Bem, se eu entendo a pergunta corretamente, você não está contabilizando a curvatura da terra. A Lei Cosseno trabalha em um avião, não em uma esfera. Por exemplo: O Pólo Norte e o Pólo Sul estão localizados a ~ 20.000 km de distância se você voar, mas apenas ~ 6000 km se você cavar um túnel;)

Atenciosamente, Ari

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