Pergunta

Esta é uma continuação a esta questão .

Eu pareço ser preso neste. Basicamente, eu preciso ser capaz de converter para trás e para referindo-se coordenadas tanto no sistema de graus padrão ou medindo a distância ao norte do pólo sul ao longo da linha internacional de data e, em seguida, uma distância a leste a partir desse ponto na data linha. Para fazer isso (assim como alguns mais geral a distância de medição de material), eu tenho um método para determinar a distância entre dois pontos latitude / longitude, e um outro método que leva um lat / lon ponto, um título e uma distância, e retorna a latitude / longitude ponto no final do referido curso.

Aqui estão os dois métodos estáticos que eu definidos:

/* Takes two lon/lat pairs and returns the distance between them in kilometers.
*/
public static double distance (double lat1, double lon1, double lat2, double lon2) {
    double theta = toRadians(lon1-lon2);
    lat1 = toRadians(lat1);
    lon1 = toRadians(lon1);
    lat2 = toRadians(lat2);
    lon2 = toRadians(lon2);

    double dist = sin(lat1)*sin(lat2) + cos(lat1)*cos(lat2)*cos(theta);
    dist = toDegrees(acos(dist)) * 60 * 1.1515 * 1.609344 * 1000;

    return dist;
}

/* endOfCourse takes a lat/lon pair, a heading (in degrees clockwise from north), and a distance (in kilometers), and returns
 * the lat/lon pair that would be reached by traveling that distance in that direction from the given point.
 */
public static double[] endOfCourse (double lat1, double lon1, double tc, double dist) {
    double pi = Math.PI;
    lat1 = toRadians(lat1);
    lon1 = toRadians(lon1);
    tc = toRadians(tc);
    double dist_radians = toRadians(dist / (60 * 1.1515 * 1.609344 * 1000));
    double lat = asin(sin(lat1) * cos(dist_radians) + cos(lat1) * sin(dist_radians) * cos(tc));
    double dlon = atan2(sin(tc) * sin(dist_radians) * cos(lat1), cos(dist_radians) - sin(lat1) * sin(lat));
    double lon = ((lon1-dlon + pi) % (2*pi)) - pi;
    double[] endPoint = new double[2];
    endPoint[0] = lat; endPoint[1] = lon;
    return endPoint;
}

E aqui está a função que estou usando para testá-lo:

public static void main(String args[]) throws java.io.IOException, java.io.FileNotFoundException {
    double distNorth = distance(0.0, 0.0, 72.0, 0.0);
    double distEast = distance(72.0, 0.0, 72.0, 31.5);
    double lat1 = endOfCourse(0.0, 0.0, 0.0, distNorth)[0];
    double lon1 = endOfCourse(lat1, 0.0, 90.0, distEast)[1];
    System.out.println("end at: " + lat1 + " / " + lon1);
    return;
}

O "fim em" valores devem ser aproximadamente. 72,0 / 31,5. Mas ao invés disso eu estou recebendo cerca de 1,25 / 0.021.

Eu suponho que deve estar faltando algo estúpido, esquecendo-se de unidades de converter em algum lugar, ou algo assim ... Qualquer ajuda seria muito apreciada!

UPDATE 1:

Eu tive (corretamente), escrito a função distância para retornar metros, mas escreveu quilômetros nos comentários por engano ... que, naturalmente, me confundiu quando eu voltei a ele hoje. De qualquer forma, agora que é fixo, e eu tenho corrigido o erro de factoring no método endOfCourse, e eu também percebi que eu tinha esquecido de converter de volta para graus de radianos em que o método também. De qualquer forma:., Enquanto parece que eu estou começando agora o número latitude correta (71,99 ...), o número de longitude está fora de forma (eu recebo 3,54 em vez de 11,5)

UPDATE 2: I teve um erro na escrita do teste, como mencionado abaixo. É agora fixo no código. O número longitude ainda é, no entanto, errado: Eu estou começando agora -11,34 em vez de 11,5. Eu acho que deve haver algo de errado com estas linhas:

double dlon = atan2(sin(tc) * sin(dist_radians) * cos(lat1), cos(dist_radians) - sin(lat1) * sin(lat));
double lon = ((lon1-dlon + pi) % (2*pi)) - pi;
Foi útil?

Solução

Você tem um caso grave dos números mágicos no código. A expressão:

 (60 * 1.1515 * 1.609344 * 1000)

aparece duas vezes, mas não há muita explicação. Com alguma ajuda: 1.609344 é o número de quilômetros em uma milha; 60 é o número de minutos em um grau; 1000 é o número de metros de um km; e 1,1515 é o número de milhas terrestres em uma milha náutica (graças, DanM). Uma milha náutica é o comprimento de um minuto de latitude no equador.

Eu suponho que você está usando um modelo de terra esférica, em vez de uma terra esférica? A álgebra não é suficiente complexo para ser esferoidal.

A primeira fórmula - conversão entre dois pares de latitude e longitude - é impar. Você precisa tanto delta-lat (??) e delta-lon (?f) para classificar a resposta. Além disso, a distância entre os pares:

(60° N, 30° W), (60° N, 60° W)
(60° N, 60° W), (60° N, 90° W)

deve ser o mesmo -. Mas eu tenho certeza que seu código produz respostas diferentes

Então, eu acho que você precisa voltar para os seus materiais de referência trigonometria esférica e ver o que você está fazendo errado. (Eu levaria um tempo para encontrar o meu livro sobre o assunto -. Ele precisaria ser desembalado a partir de qualquer caixa é in)

[ ... o tempo passa ... descompactação feito ... ]

Dado um triângulo esférico com ângulos A , B , C nos vértices e lados a , < em> b , c oposto esses vértices (isto é, lado a é de b C , etc), o co-seno fórmula é:

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

A aplicação desta para o problema, podemos chamar os dois pontos dados B e C , e criamos um triângulo esférico direita com um ângulo direito em A .

arte ASCII no seu pior:

                  + C
                 /|
                / |
            a  /  | b
              /   |
             /    |
            /     |
         B +------+ A
              c

O lado c é igual à diferença de longitude; o lado b é igual à diferença de latitude; o ângulo A é de 90 °, de modo cos A = 0. Portanto, eu acredito que uma equação para a é:

cos a = cos Δλ . cos Δφ + sin Δλ . sin Δφ . cos 90°

a = arccos (cos Δλ . cos Δφ)

O ângulo a em radianos é então convertido em uma distância multiplicando pelo raio da Terra. Alternativamente, dado a em graus (e fracções de grau), então existem 60 milhas náuticas para um grau, por conseguinte, 60 * 1,1515 milhas de estatuto, e 60 * 1,1515 * 1,609344 km para um grau. A menos que você quiser a distância em metros, não vejo uma necessidade para o fator de 1000.

Paul Tomblin aponta para Aviation Formulary v1.44 como fonte da equação -. e, na verdade, ele está lá, juntamente com uma versão mais numericamente estável para quando a diferença de posição é pequena

Indo para trigonometria básica, também sabemos que:

cos (A - B) = cos A . cos B + sin A . sin B

A aplicação que duas vezes na equação dei pode muito bem acabar na fórmula no Formulário de Aviação.

(Minha referência: "Astronomia: Princípios e Práticas, quarta edição" por AE Roy e D Clarke (2003);. minha cópia é a primeira edição de 1977, Adam Hilger, ISBN 0-85274-346-7)


Nota Check out (Google) 'define: "milha náutica"'; parece que uma milha náutica é agora 1.852 m (1,852 km) por definição. . O multiplicador de 1,1515 corresponde à antiga definição da milha náutica como aproximadamente 6.080 pés Usando bc com uma escala de 10, eu recebo:

(1852/(3*0.3048))/1760
1.1507794480

Qual fator funciona para você depende do que a sua base é.


Olhando para o segundo problema dos primeiros princípios, temos uma configuração um pouco diferente, e precisamos do 'outro' esférica trigonometria equação, a Fórmula Sine:

sin A   sin B   sin C
----- = ----- = -----
sin a   sin b   sin c

A adaptação do diagrama anterior:

                  + C
                 /|
                / |
            a  /  | b
           |  /   |
           |X/    |
           |/     |
         B +------+ A
              c

é-lhe dada ponto de partida B , ângulo X = 90º - B, comprimento (ângulo) a , e ângulo A = 90 °. O que você está depois é b (o delta na latitude) e c (o delta na longitude).

Assim, temos:

sin a   sin b
----- = ----
sin A   sin B

ou

        sin a . sin B
sin b = -------------
            sin A

Ou, uma vez que A = 90 °, sen A = 1, e sin B = sen (90 ° - X) = cos X:

sin b = sin a . cos X

Isso significa que você converter a distância percorrida em um ângulo a , tomar o seno de que, se multiplicam pelo cosseno da direção claro, e levar o arco seno do resultado.

Dada a , b (apenas calculado) e A e B , podemos aplicar a fórmula de co-seno para obter c . Note-se que não podemos simplesmente re-aplicar a fórmula sine para obter c , uma vez que não tem o valor de C e, porque estamos jogando com trigonometria esférica, não há regra conveniente que C = 90 ° - B. (a soma dos ângulos de um triângulo esférico pode ser maior do que 180 °; considerar um triângulo esférico equilátero com todos os ângulos iguais a 90 °, o que é perfeitamente viável)


Outras dicas

Confira http://www.movable-type.co.uk /scripts/latlong.html

Esse site tem um monte de diferentes fórmulas e código Javascript que deve ajudá-lo. Eu traduzi-lo com sucesso em C # e um servidor SQL UDF e eu usá-los em todo o lugar.

Por exemplo, para usar o Javascript para distância calcular:

var R = 6371; // km
var φ1 = lat1.toRadians();
var φ2 = lat2.toRadians();
var Δφ = (lat2-lat1).toRadians();
var Δλ = (lon2-lon1).toRadians();

var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
        Math.cos(φ1) * Math.cos(φ2) *
        Math.sin(Δλ/2) * Math.sin(Δλ/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

var d = R * c; 

Aproveite!

A sua conversão entre km e radianos é errado. Uma milha náutica é de 1 / 60th de um grau, assumindo assim que 1,15 ... é a sua conversão de milhas para milhas náuticas, e 1,6 ... é a sua conversão de km para milhas terrestres,

   nm = km /  (1.1515 * 1.609344);
   deg = nm / 60;
   rad = toRadians(deg);

Em outras palavras, eu acho que você está fora por um fator de 1000.

Quanto à sua pergunta atualização: não deve

double lon1 = endOfCourse(lat1, 0.0, 90.0, distEast)[0];

ser

double lon1 = endOfCourse(lat1, 0.0, 90.0, distEast)[1];

Eu descobri o grande problema com estas fórmulas, além dos erros de implementação mencionados em outras respostas e atualizações.

O grande problema era o seguinte: O método Distância (para calcular a distância entre dois pontos) foi computar distâncias grande-círculo. O que, claro, faz sentido - que é o caminho mais curto entre os dois pontos. No entanto , o ortodromia entre dois pontos que se encontram no mesmo paralelo (linha de latitude) não é o mesmo que a distância entre esses dois pontos ao viajar directamente ao longo da linha de latitude, a menos que você 're no equador.

Assim: as funções estão funcionando corretamente; no entanto, a alternativa sistema de coordenadas propus na pergunta original requer que olhar apenas para o norte distância ao longo do IDL seguido pela distância a leste ao longo do paralelo na latitude resultante. E calcular a distância ao longo de um determinado paralelo é bastante diferente do cálculo da distância ao longo de um grande círculo!

De qualquer forma, você tem isso.

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