Pergunta

Se eu tenho uma leitura de latitude ou longitude no formato NMEA padrão, existe uma maneira / fórmula fácil para converter essa leitura em metros, que eu posso implementar em Java (J9)?

EDIT: Ok parece que o que eu quero fazer não é possível facilmente, no entanto, o que eu realmente quero fazer é:

Digamos que eu tenho um ponto de vista e um longo ponto e um lat e um usuário há uma maneira fácil de compará -los para decidir quando dizer ao usuário que estão dentro de um razoavelmente perto da distância do caminho? Eu percebo que razoável é o assunto, mas isso é facilmente possível ou ainda excessivamente matemática?

Foi útil?

Solução

Aqui está uma função JavaScript:

function measure(lat1, lon1, lat2, lon2){  // generally used geo measurement function
    var R = 6378.137; // Radius of earth in KM
    var dLat = lat2 * Math.PI / 180 - lat1 * Math.PI / 180;
    var dLon = lon2 * Math.PI / 180 - lon1 * Math.PI / 180;
    var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
    Math.sin(dLon/2) * Math.sin(dLon/2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    var d = R * c;
    return d * 1000; // meters
}

Explicação: https://en.wikipedia.org/wiki/haversine_formula

A fórmula de Haversine determina a distância de grande círculo entre dois pontos em uma esfera, dadas suas longitudes e latitudes.

Outras dicas

Dado que você está procurando uma fórmula simples, essa é provavelmente a maneira mais simples de fazê -lo, assumindo que a Terra seja uma esfera de perímetro 40075 km.

Comprimento em metros de 1 ° de latitude = sempre 111,32 km

Comprimento em metros de 1 ° de longitude = 40075 km * cos (latitude) / 360

Para aproximar curtas distâncias entre duas coordenadas, usei fórmulas de http://en.wikipedia.org/wiki/lat-lon:

m_per_deg_lat = 111132.954 - 559.822 * cos( 2 * latMid ) + 1.175 * cos( 4 * latMid);
m_per_deg_lon = 111132.954 * cos ( latMid );

.

No código abaixo, deixei os números brutos para mostrar sua relação com a fórmula da Wikipedia.

double latMid, m_per_deg_lat, m_per_deg_lon, deltaLat, deltaLon,dist_m;

latMid = (Lat1+Lat2 )/2.0;  // or just use Lat1 for slightly less accurate estimate


m_per_deg_lat = 111132.954 - 559.822 * cos( 2.0 * latMid ) + 1.175 * cos( 4.0 * latMid);
m_per_deg_lon = (3.14159265359/180 ) * 6367449 * cos ( latMid );

deltaLat = fabs(Lat1 - Lat2);
deltaLon = fabs(Lon1 - Lon2);

dist_m = sqrt (  pow( deltaLat * m_per_deg_lat,2) + pow( deltaLon * m_per_deg_lon , 2) );

A entrada da Wikipedia afirma que os cálculos de distância estão dentro de 0,6m por 100 km longitudinalmente e 1 cm por 100 km latitudinalmente, mas não o verifiquei como perto dessa precisão é bom para o meu uso.

Latitudes e longitudes especificam pontos, não distâncias, então sua pergunta é um pouco sem sentido. Se você está perguntando sobre a menor distância entre dois pontos (Lat, Lon), veja Este artigo da Wikipedia em distâncias de grande círculo.

A Terra é uma superfície irritantemente irregular, então não há uma fórmula simples para fazer isso exatamente. Você precisa viver com um modelo aproximado da Terra e projetar suas coordenadas nele. O modelo que normalmente vejo usado para isso é WGS 84. É isso que os dispositivos GPS geralmente usam para resolver exatamente o mesmo problema.

NOAA tem algum software que você pode baixar para ajudar com isso em seu site.

Existem muitas ferramentas que facilitarão isso. Ver Resposta de Monjardin Para mais detalhes sobre o que está envolvido.

No entanto, isso não é necessariamente difícil. Parece que você está usando Java, então eu recomendaria olhar para algo como Gdal. Ele fornece invólucros java para suas rotinas e têm todas as ferramentas necessárias para converter de Lat/Lon (coordenadas geográficas) em UTM (sistema de coordenadas projetadas) ou alguma outra projeção de mapa razoável.

O UTM é bom, porque são medidores, tão fáceis de trabalhar. No entanto, você precisará obter o apropriado Zona utm para fazer um bom trabalho. Existem alguns códigos simples disponíveis via Google para encontrar uma zona apropriada para um par Lat/Long.

Aqui está a versão R de Função BH-', apenas no caso de:

measure <- function(lon1,lat1,lon2,lat2) {
    R <- 6378.137                                # radius of earth in Km
    dLat <- (lat2-lat1)*pi/180
    dLon <- (lon2-lon1)*pi/180
    a <- sin((dLat/2))^2 + cos(lat1*pi/180)*cos(lat2*pi/180)*(sin(dLon/2))^2
    c <- 2 * atan2(sqrt(a), sqrt(1-a))
    d <- R * c
    return (d * 1000)                            # distance in meters
}

Uma milha náutica (1852 metros) é definida como uma ArcMinute de longitude no equador. No entanto, você precisa definir um projeção de mapa (Veja também Utm) em que você está trabalhando para a conversão para realmente fazer sentido.

Existem algumas maneiras de calcular isso. Todos eles usam aproximações de trigonometria esférica, onde o raio é o da terra.

tentar http://www.movable-type.co.uk/scripts/latlong.html Para um pouco de métodos e codificação em diferentes idiomas.

Com base na distância média para Degress na Terra.

1 ° = 111 km;

Convertendo isso para radianos e dividindo -se por medidores, tome um número mágico para o rad, em metros: 0,0000089987192435999958;

então:

const RAD = 0.000008998719243599958;
Math.sqrt(Math.pow(lat1 - lat2, 2) + Math.pow(long1 - long2, 2)) / RAD;
    'below is from
'http://www.zipcodeworld.com/samples/distance.vbnet.html
Public Function distance(ByVal lat1 As Double, ByVal lon1 As Double, _
                         ByVal lat2 As Double, ByVal lon2 As Double, _
                         Optional ByVal unit As Char = "M"c) As Double
    Dim theta As Double = lon1 - lon2
    Dim dist As Double = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) + _
                            Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * _
                            Math.Cos(deg2rad(theta))
    dist = Math.Acos(dist)
    dist = rad2deg(dist)
    dist = dist * 60 * 1.1515
    If unit = "K" Then
        dist = dist * 1.609344
    ElseIf unit = "N" Then
        dist = dist * 0.8684
    End If
    Return dist
End Function
Public Function Haversine(ByVal lat1 As Double, ByVal lon1 As Double, _
                         ByVal lat2 As Double, ByVal lon2 As Double, _
                         Optional ByVal unit As Char = "M"c) As Double
    Dim R As Double = 6371 'earth radius in km
    Dim dLat As Double
    Dim dLon As Double
    Dim a As Double
    Dim c As Double
    Dim d As Double
    dLat = deg2rad(lat2 - lat1)
    dLon = deg2rad((lon2 - lon1))
    a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(deg2rad(lat1)) * _
            Math.Cos(deg2rad(lat2)) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2)
    c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a))
    d = R * c
    Select Case unit.ToString.ToUpper
        Case "M"c
            d = d * 0.62137119
        Case "N"c
            d = d * 0.5399568
    End Select
    Return d
End Function
Private Function deg2rad(ByVal deg As Double) As Double
    Return (deg * Math.PI / 180.0)
End Function
Private Function rad2deg(ByVal rad As Double) As Double
    Return rad / Math.PI * 180.0
End Function

Para converter latitude e longitude na representação x e y, você precisa decidir que tipo de projeção de mapa usar. Quanto a mim, o elíptico Mercator parece muito bem. Aqui Você pode encontrar uma implementação (em Java também).

Se estiver suficientemente próximo, você pode se safar de tratá -los como coordenadas em um plano plano. Isso funciona no nível, no nível da rua ou da cidade, se a precisão perfeita não for necessária e tudo o que você precisa é de um palpite na distância envolvida para comparar com um limite arbitrário.

Se você deseja uma solução simples, use o Fórmula Haversine conforme descrito pelos outros comentários. Se você tiver uma aplicação sensível à precisão, lembre -se de que a fórmula do Haversine não garante uma precisão melhor do que 0,5%, pois assume que a Terra é um círculo. Considerar que a Terra é um esferóide oblato, considere usar Fórmulas de Vincenty. Além disso, não tenho certeza de qual raio devemos usar com a fórmula do Haversine: {Equador: 6.378.137 km, Polar: 6.356.752 km, volumétrico: 6.371.0088 km}.

You need to convert the coordinates to radians to do the spherical geometry. Once converted, then you can calculate a distance between the two points. The distance then can be converted to any measure you want.

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