Domanda

Se ho una lettura di latitudine o longitudine in formato NMEA standard, esiste un modo / formula semplice per convertire quella lettura in metri, che posso quindi implementare in Java (J9)?

Modifica: Ok sembra che ciò che voglio fare non sia possibile facilmente , tuttavia ciò che voglio davvero fare è:

Supponiamo che io abbia un lat e un long di way point e un lat e un long di un utente c'è un modo semplice per confrontarli per decidere quando dire all'utente che si trovano entro un ragionevolmente close distanza del punto di passaggio? Mi rendo conto che la materia è ragionevole, ma è facilmente fattibile o ancora eccessivamente matematica?

È stato utile?

Soluzione

Ecco una funzione 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
}

Spiegazione: https://en.wikipedia.org/wiki/Haversine_formula

  

La formula haversine determina la distanza del grande cerchio tra due punti su una sfera date le loro lunghezze e latitudini.

Altri suggerimenti

Dato che stai cercando una formula semplice, questo è probabilmente il modo più semplice per farlo, supponendo che la Terra sia una sfera di perimetro 40075 km.

Lunghezza in metri di 1 & # 176; di latitudine = sempre 111,32 km

Lunghezza in metri di 1 & # 176; di longitudine = 40075 km * cos (latitudine) / 360

Per approssimare brevi distanze tra due coordinate ho usato formule da   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 );

.

Nel codice qui sotto ho lasciato i numeri grezzi per mostrare la loro relazione con la formula di 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) );

La voce di Wikipedia afferma che i calc di distanza sono entro 0,6 m per 100 km in senso longitudinale e 1 cm per 100 km in senso longitudinale, ma non l'ho verificato in quanto vicino all'accuratezza va bene per il mio uso.

Latitudini e longitudini specificano punti, non distanze, quindi la tua domanda è alquanto insensata. Se stai chiedendo la distanza più breve tra due punti (lat, lon), consulta questo articolo di Wikipedia sulle distanze del grande cerchio.

La terra è una superficie fastidiosamente irregolare, quindi non esiste una formula semplice per farlo esattamente. Devi vivere con un modello approssimativo della terra e proiettare le tue coordinate su di esso. Il modello che in genere vedo utilizzato per questo è WGS 84 . Questo è ciò che i dispositivi GPS di solito usano per risolvere esattamente lo stesso problema.

NOAA ha alcuni software che puoi scaricare per aiutarti con questo sul loro sito web .

Ci sono molti strumenti che renderanno questo facile. Vedi la risposta di Monjardin per maggiori dettagli su ciò che è coinvolti.

Tuttavia, farlo non è necessariamente difficile. Sembra che tu stia usando Java, quindi ti consiglio di esaminare qualcosa come GDAL . Fornisce wrapper Java per le loro routine e dispongono di tutti gli strumenti necessari per convertire da Lat / Lon (coordinate geografiche) a UTM (sistema di coordinate proiettate) o qualche altra ragionevole proiezione della mappa.

UTM è bello, perché è metri, così facile da lavorare. Tuttavia, dovrai ottenere la UTM zone appropriata affinché possa fare un buon lavoro . Ci sono alcuni semplici codici disponibili tramite Google per trovare una zona appropriata per una coppia lat / long.

Ecco la versione R della funzione b-h- , per ogni evenienza:

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
}

Un miglio nautico (1852 metri) è definito come un arcminute di longitudine all'equatore . Tuttavia, devi definire una proiezione della mappa (vedi anche UTM ) in cui stai lavorando affinché la conversione abbia davvero senso.

Esistono diversi modi per calcolare questo. Tutti usano approssimazioni della trigonometria sferica in cui il raggio è quello della terra.

prova http://www.movable-type.co.uk/ scripts / latlong.html per un po 'di metodi e codice in diverse lingue.

Basato sulla distanza media per i degressi nella Terra.

1 & # 176; = 111km;

Convertendo questo per radianti e dividendolo per metri, prendi un numero magico per il RAD, in metri: 0.000008998719243599958;

quindi:

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

Per convertire latitudine e longitudine nella rappresentazione xey è necessario decidere quale tipo di proiezione cartografica utilizzare. Quanto a me, Ellittical Mercator sembra molto bene. Qui puoi trovare un'implementazione (anche in Java).

Se è sufficientemente vicino, puoi evitare di trattarli come coordinate su un piano piatto. Funziona ad esempio a livello di strada o di città se non è richiesta la massima precisione e tutto ciò di cui hai bisogno è un'ipotesi approssimativa sulla distanza coinvolta da confrontare con un limite arbitrario.

Se desideri una soluzione semplice, utilizza la formula Haversine come indicato dagli altri commenti . Se si dispone di un'applicazione sensibile alla precisione, tenere presente che la formula Haversine non garantisce una precisione migliore dello 0,5%, poiché si presume che la terra sia un cerchio. Per considerare che la Terra è uno sferoide oblato, considera l'utilizzo di le formule di Vincenty . Inoltre, non sono sicuro di quale raggio dovremmo usare con la formula Haversine: {Equatore: 6.378.137 km, Polare: 6.356.752 km, Volumetrico: 6.371,0088 km}.

È necessario convertire le coordinate in radianti per eseguire la geometria sferica. Una volta convertito, puoi calcolare una distanza tra i due punti. La distanza può quindi essere convertita in qualsiasi misura desiderata.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top