2010-04-29 49 views
94

Voglio creare app che controllino qual è il luogo più vicino da dove si trova l'utente. Posso facilmente ottenere la posizione dell'utente e ho una lista di posti con latitudine e longitudine.Ottieni la distanza tra due punti geografici

Quale sarebbe il modo migliore per conoscere la posizione più vicina dell'elenco rispetto alla posizione corrente.

Non ho trovato nulla nelle API di Google.

Sono preoccupato, ho bisogno di ricorrere al mio calcolo e devo fare matematica per calcolarlo.

Cosa ne pensate?

Saluti e grazie per aver letto o risposto.

risposta

108
Location loc1 = new Location(""); 
loc1.setLatitude(lat1); 
loc1.setLongitude(lon1); 

Location loc2 = new Location(""); 
loc2.setLatitude(lat2); 
loc2.setLongitude(lon2); 

float distanceInMeters = loc1.distanceTo(loc2); 

Riferimento: http://developer.android.com/reference/android/location/Location.html#distanceTo(android.location.Location)

+1

Probabilmente più lento dell'utilizzo di Location.DistanceBetween() poiché utilizza gli oggetti Location ma funziona molto bene per i miei scopi. – ZoltanF

+0

@praveen thanks man its works .. –

+0

Quale classe devo importare per la posizione 'import android.location.Location;' o che –

117

http://developer.android.com/reference/android/location/Location.html

Guardare in distanceTo o distanceBetween. È possibile creare un oggetto Location da una latitudine e longitudine:

Location location = new Location(""); 
location.setLatitude(lat); 
location.setLongitude(lon); 
+32

distanceBetween è un metodo statico che prende 2 set di punti lunghi lat, quindi non si fa nemmeno bisogno di istanziare un oggetto Location =) –

+4

Sono sicuro che intendeva quello per il metodo 'distanceTo'. – laph

+0

Questo è ottimo e super utile, ma qual è il provider di stringhe per il constrructor? –

10

Ci sono un paio di metodi è possibile utilizzare, ma per stabilire qual è il migliore che abbiamo prima bisogno di sapere se si è a conoscenza di altitudine dell'utente, così come l'altitudine degli altri punti?

A seconda del livello di precisione che sono dopo, si poteva guardare in sia la Haversine o formule Vincenty ...

Queste pagine di dettaglio le formule, e, per i meno portati alla matematica forniscono anche una spiegazione di come per implementarli in script!

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

Vincenty Formula: http://www.movable-type.co.uk/scripts/latlong-vincenty.html

Se avete problemi con uno qualsiasi dei significati nelle formule, proprio commento e farò del mio meglio per rispondere :)

29

Una soluzione approssimata (basata su una proiezione equirettangolare), molto più veloce (richiede solo 1 trig e 1 radice quadrata).

Questa approssimazione è pertinente se i punti non sono troppo distanti. Sarà sovrastimare sempre rispetto alla vera distanza haversine. Ad esempio, aggiungerà non più dello 0.05382% alla distanza reale se la latitudine o la longitudine delta tra i due punti non supera i 4 gradi decimali.

La formula standard (Haversine) è l'esatto uno (cioè, funziona per qualsiasi coppia di longitudine/latitudine sulla terra) ma è molto più lento come deve 7 trigonometriche e 2 radici quadrate. Se la coppia di punti non è troppo distanziata e la precisione assoluta non è fondamentale, è possibile utilizzare questa versione approssimativa (Equirettangolare), che è molto più veloce in quanto utilizza solo una radice trigonometrica e una radice quadrata.

// Approximate Equirectangular -- works if (lat1,lon1) ~ (lat2,lon2) 
int R = 6371; // km 
double x = (lon2 - lon1) * Math.cos((lat1 + lat2)/2); 
double y = (lat2 - lat1); 
double distance = Math.sqrt(x * x + y * y) * R; 

È possibile ottimizzare questo ulteriore mediante:

  1. Rimozione della radice quadrata se si confronta semplicemente la distanza ad un altro (in questo caso confrontare entrambi distanza al quadrato);
  2. Factoring-out the cosine se si calcola la distanza da un punto master a molti altri (in tal caso si esegue la proiezione equirettangolare centrata sul punto master, quindi è possibile calcolare il coseno una volta per tutti i confronti).

Per maggiori informazioni visita: http://www.movable-type.co.uk/scripts/latlong.html

C'è un'implementazione di riferimento bella della formula Haversine in diverse lingue all'indirizzo: http://www.codecodex.com/wiki/Calculate_Distance_Between_Two_Points_on_a_Globe

+0

great man thanx. Ma se ho bisogno di ottenere un set di posizioni attorno a una posizione in un perimetro, dovrei usare un ciclo while per controllare ogni posizione rispetto a quella cercata e mantenere solo quelle che si trovano nel perimetro? – themis

+0

Si può, ma questo è un approccio a forza bruta in 'O (n)'. Per una soluzione 'O (1)', utilizzare un indice spaziale 2D per tagliare le potenziali corrispondenze prima di calcolare la soluzione esatta. Stiamo lasciando lo scopo di questa domanda :) –

+0

questo è un wrapup molto bello di buone ottimizzazioni possibili .. thx! Esattamente quello che stavo cercando –

3

Ci sono due modi per ottenere la distanza tra LatLng.

public static void distanceBetween (double startLatitude, double startLongitude, double endLatitude, double endLongitude, float[] results) 

See this

e la seconda

public float distanceTo (Location dest) come risposta da Praveen.

0

basta utilizzare il seguente metodo, passare esso lat e lunga e ottenere la distanza in metri:

private static double distance_in_meter(final double lat1, final double lon1, final double lat2, final double lon2) { 
    double R = 6371000f; // Radius of the earth in m 
    double dLat = (lat1 - lat2) * Math.PI/180f; 
    double dLon = (lon1 - lon2) * Math.PI/180f; 
    double a = Math.sin(dLat/2) * Math.sin(dLat/2) + 
      Math.cos(latlong1.latitude * Math.PI/180f) * Math.cos(latlong2.latitude * Math.PI/180f) * 
        Math.sin(dLon/2) * Math.sin(dLon/2); 
    double c = 2f * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
    double d = R * c; 
    return d; 
} 
+1

latlong1 e latlong2 non sono definiti – Boy

+0

cos'è latlong1 e latlong2? –

0
private float getDistance(double lat1, double lon1, double lat2, double lon2) { 
     float[] distance = new float[2]; 
     Location.distanceBetween(lat1, lon1, lat2, lon2, distance); 
     return distance[0]; 
    } 
Problemi correlati