2011-10-29 22 views
5

investigué un poco sobre este tema, pero hay muchas opiniones que no ofrecen exactamente una imagen clara. Mi problema es el siguiente: estoy desarrollando una aplicación basada en gps para Android, en la que deseo saber la distancia entre mi ubicación actual especificada por Androids LocationManager y otra ubicación en tiempo real. Probé la fórmula Haversine, una fórmula de Law of Cosines, y luego descubrí que Android SDK me da una función simple Location.distanceTo (Location): no estoy seguro de qué método ejecuta esta función.
Entonces, el punto es, cuál será bueno para mí usar, en situaciones donde la distancia real entre estos lugares la mayoría de las veces no será mayor que aprox. 100-200m? Tal vez debería consultar la fórmula de Vincenty? ¿Es realmente así de lento? ¿Puede alguien por favor explicarme qué debería elegir?Android: mejor método para calcular la distancia entre dos ubicaciones

Respuesta

2

No utilice distanceTo. Utilice el método distanceBetween ya que parece que ya tiene las coordenadas y eso es todo lo que necesita con este método: Location.distanceBetween() Javadoc

+2

¿cuál es la diferencia entre distanceTo y distanceBetween ya me sale poblaciones de LocationManager? –

1

Al buscar en la fuente de Android para distanceTo (Location), puede ver que el resultado se basa en "Inverse formula" de la geodesia:

que se basa en el uso de la (sección 4) "Inverse Formula"

Además, los dos métodos distanceTo y distanceBetween utilizan el mismo método subyacente. Simplemente tienen formas alternativas de entrada/salida.

Para más información, la fuente completa de este cálculo se incluye a continuación, pero le recomiendo que consulte la clase Location en android.location por usted mismo. (P. S. Yo no comprobar la exactitud del cálculo Android. Esto sería un buen ejercicio!)

private static void computeDistanceAndBearing(double lat1, double lon1, 
    double lat2, double lon2, float[] results) { 
    // Based on http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf 
    // using the "Inverse Formula" (section 4) 

    int MAXITERS = 20; 
    // Convert lat/long to radians 
    lat1 *= Math.PI/180.0; 
    lat2 *= Math.PI/180.0; 
    lon1 *= Math.PI/180.0; 
    lon2 *= Math.PI/180.0; 

    double a = 6378137.0; // WGS84 major axis 
    double b = 6356752.3142; // WGS84 semi-major axis 
    double f = (a - b)/a; 
    double aSqMinusBSqOverBSq = (a * a - b * b)/(b * b); 

    double L = lon2 - lon1; 
    double A = 0.0; 
    double U1 = Math.atan((1.0 - f) * Math.tan(lat1)); 
    double U2 = Math.atan((1.0 - f) * Math.tan(lat2)); 

    double cosU1 = Math.cos(U1); 
    double cosU2 = Math.cos(U2); 
    double sinU1 = Math.sin(U1); 
    double sinU2 = Math.sin(U2); 
    double cosU1cosU2 = cosU1 * cosU2; 
    double sinU1sinU2 = sinU1 * sinU2; 

    double sigma = 0.0; 
    double deltaSigma = 0.0; 
    double cosSqAlpha = 0.0; 
    double cos2SM = 0.0; 
    double cosSigma = 0.0; 
    double sinSigma = 0.0; 
    double cosLambda = 0.0; 
    double sinLambda = 0.0; 

    double lambda = L; // initial guess 
    for (int iter = 0; iter < MAXITERS; iter++) { 
     double lambdaOrig = lambda; 
     cosLambda = Math.cos(lambda); 
     sinLambda = Math.sin(lambda); 
     double t1 = cosU2 * sinLambda; 
     double t2 = cosU1 * sinU2 - sinU1 * cosU2 * cosLambda; 
     double sinSqSigma = t1 * t1 + t2 * t2; // (14) 
     sinSigma = Math.sqrt(sinSqSigma); 
     cosSigma = sinU1sinU2 + cosU1cosU2 * cosLambda; // (15) 
     sigma = Math.atan2(sinSigma, cosSigma); // (16) 
     double sinAlpha = (sinSigma == 0) ? 0.0 : 
      cosU1cosU2 * sinLambda/sinSigma; // (17) 
     cosSqAlpha = 1.0 - sinAlpha * sinAlpha; 
     cos2SM = (cosSqAlpha == 0) ? 0.0 : 
      cosSigma - 2.0 * sinU1sinU2/cosSqAlpha; // (18) 

     double uSquared = cosSqAlpha * aSqMinusBSqOverBSq; // defn 
     A = 1 + (uSquared/16384.0) * // (3) 
      (4096.0 + uSquared * 
      (-768 + uSquared * (320.0 - 175.0 * uSquared))); 
     double B = (uSquared/1024.0) * // (4) 
      (256.0 + uSquared * 
      (-128.0 + uSquared * (74.0 - 47.0 * uSquared))); 
     double C = (f/16.0) * 
      cosSqAlpha * 
      (4.0 + f * (4.0 - 3.0 * cosSqAlpha)); // (10) 
     double cos2SMSq = cos2SM * cos2SM; 
     deltaSigma = B * sinSigma * // (6) 
      (cos2SM + (B/4.0) * 
      (cosSigma * (-1.0 + 2.0 * cos2SMSq) - 
       (B/6.0) * cos2SM * 
       (-3.0 + 4.0 * sinSigma * sinSigma) * 
       (-3.0 + 4.0 * cos2SMSq))); 

     lambda = L + 
      (1.0 - C) * f * sinAlpha * 
      (sigma + C * sinSigma * 
      (cos2SM + C * cosSigma * 
       (-1.0 + 2.0 * cos2SM * cos2SM))); // (11) 

     double delta = (lambda - lambdaOrig)/lambda; 
     if (Math.abs(delta) < 1.0e-12) { 
      break; 
     } 
    } 

    float distance = (float) (b * A * (sigma - deltaSigma)); 
    results[0] = distance; 
    if (results.length > 1) { 
     float initialBearing = (float) Math.atan2(cosU2 * sinLambda, 
      cosU1 * sinU2 - sinU1 * cosU2 * cosLambda); 
     initialBearing *= 180.0/Math.PI; 
     results[1] = initialBearing; 
     if (results.length > 2) { 
      float finalBearing = (float) Math.atan2(cosU1 * sinLambda, 
       -sinU1 * cosU2 + cosU1 * sinU2 * cosLambda); 
      finalBearing *= 180.0/Math.PI; 
      results[2] = finalBearing; 
     } 
    } 
} 
Cuestiones relacionadas