2010-04-29 20 views
94

Quiero hacer una aplicación que compruebe cuál es el lugar más cercano desde donde se encuentra el usuario. Puedo obtener fácilmente la ubicación del usuario y tengo una lista de lugares con latitud y longitud.Obtener la distancia entre dos puntos geográficos

Cuál sería la mejor manera de conocer el lugar más cercano de la lista con respecto a la posición actual.

No he podido encontrar nada en las API de Google.

Me preocupa tener que recurrir a mi cálculo y tengo que hacer cálculos matemáticos para calcularlo.

¿Qué piensan?

Saludos y gracias por leer o responder.

Respuesta

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); 

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

+1

Probablemente más lento que usar Location.DistanceBetween() ya que está usando objetos Location pero funciona muy bien para mis propósitos. – ZoltanF

+0

@praveen gracias al hombre sus trabajos ... –

+0

¿Qué clase tengo que importar para la ubicación 'import android.location.Location;' o qué –

117

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

Mira en distanceTo o distanceBetween. Puede crear un objeto de la ubicación de una latitud y longitud:

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

distanceBetween es un método estático que toma 2 conjuntos de puntos largos lat, por lo que ni siquiera necesito crear una instancia de un objeto Location =) –

+4

Estoy seguro de que quiso decir eso para el método 'distanceTo'. – laph

+0

Esto es genial y muy útil, pero ¿para qué sirve el proveedor de String en el constructor? –

10

Hay un par de métodos que puede utilizar, pero para determinar cuál es el mejor, primero tenemos que saber si usted es consciente de la altitud del usuario, así como la altitud de los otros puntos?

Dependiendo del nivel de precisión que está después, usted podría mirar en cualquiera de las fórmulas o Haversine vincenty ...

Estas páginas de detalle las fórmulas, y, para los menos inclinación matemática también proporcionan una explicación de cómo para implementarlos en script!

Haversine Fórmula: http://www.movable-type.co.uk/scripts/latlong.html

Vincenty Fórmula: http://www.movable-type.co.uk/scripts/latlong-vincenty.html

Si tiene algún problema con cualquiera de los significados de las fórmulas, basta con comentar y haré todo lo posible para responder a ellos :)

29

Una solución aproximada (basada en una proyección equirrectangular), mucho más rápido (requiere solo 1 trig y 1 raíz cuadrada).

Esta aproximación es relevante si sus puntos no están demasiado separados. Se siempre sobreestimar en comparación con la distancia real de haversine. Por ejemplo, agregará no más de 0.05382% a la distancia real si la latitud o longitud delta entre sus dos puntos no excede 4 grados decimales.

La fórmula estándar (Haversine) es la exacta uno (es decir, funciona para cualquier par de longitud/latitud en la tierra), pero es mucho más lento , ya que necesita 7 trigonométricas y 2 raíces cuadradas. Si su par de puntos no están demasiado separados, y la precisión absoluta no es primordial, puede usar esta versión aproximada (Equirectangular), que es mucho más rápida ya que usa solo una raíz trigonométrica y una raíz cuadrada.

// 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; 

Puede optimizar este aún más mediante:

  1. Extracción de la raíz cuadrada si simplemente comparar la distancia a otro (en este caso comparamos ambas distancia al cuadrado);
  2. Factorizar el coseno si calcula la distancia de un punto maestro a muchos otros (en ese caso, usted hace la proyección equirrectangular centrada en el punto maestro, por lo que puede calcular el coseno una vez para todas las comparaciones).

Para más información ver: http://www.movable-type.co.uk/scripts/latlong.html

hay un bonito implementación de referencia de la fórmula Haversine en varios idiomas en: http://www.codecodex.com/wiki/Calculate_Distance_Between_Two_Points_on_a_Globe

+0

great man thanx. Pero si necesito obtener un conjunto de ubicaciones alrededor de una ubicación en un perímetro, ¿debo usar un ciclo while para verificar cada ubicación con respecto a la buscada y mantener solo las que están en el perímetro? – themis

+0

Puedes, pero eso es un enfoque de fuerza bruta en 'O (n)'. Para una solución 'O (1)', use un índice espacial 2D para recortar las posibles coincidencias antes de calcular la solución exacta. Estamos dejando el alcance de esta pregunta :) –

+0

este es un muy buen resumen de buenas optimizaciones posibles ... ¡gracias! Excactly lo que estaba buscando –

3

Hay dos maneras para obtener distancia entre LatLng.

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

See this

y segundo

public float distanceTo (Location dest) como contestada por Praveen.

0

sólo tiene que utilizar el siguiente método, pase lo lat y largo y obtener la distancia en metros:

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 y latlong2 no están definidos – Boy

+0

¿qué es latlong1 & 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]; 
    } 
Cuestiones relacionadas