2011-10-29 4 views
5

J'ai étudié un peu dans ce sujet, mais il y a beaucoup d'opinions qui ne donnent pas exactement une image claire. Mon problème est le suivant: je développe une application basée sur gps pour Android, dans laquelle je veux connaître la distance entre mon emplacement actuel spécifié par Androids LocationManager, et l'autre emplacement en temps réel. J'ai essayé la formule de Haversine, une formule de la Loi des Cosines, puis j'ai découvert que le SDK Android me donnait une fonction simple. Location.distanceTo (Emplacement) - Je ne suis pas sûr de la méthode utilisée pour cette fonction.
Donc, le point est, ce que je vais être bon pour moi d'utiliser, dans des situations où la distance réelle entre ces endroits la plupart du temps ne sera pas plus grande qu'après. 100-200m? Peut-être que je devrais vérifier la formule de Vincenty? Est-ce vraiment lent? Quelqu'un peut-il m'expliquer s'il vous plaît que devrais-je choisir?Android: meilleure méthode pour calculer la distance entre deux emplacements

Répondre

2

Ne pas utiliser la distanceTo. Utilisez la méthode distanceBetween car il semble que vous avez déjà les coordonnées et c'est tout ce dont vous avez besoin avec cette méthode: Location.distanceBetween() Javadoc

+2

Quelle est la différence entre distanceTo et distanceEntre depuis que je reçois des emplacements de LocationManager? –

1

En regardant dans la source Android pour distanceTo (emplacement), vous pouvez voir que le résultat est basé sur le "inverse" formule » de la géodésie:

qui est basé sur l'utilisation du "Inverse Formula" (section 4)

en outre, les deux méthodes distanceTo et distanceEntre utilisent le même procédé sous-jacent. Ils ont juste des formes alternatives d'entrée/sortie.

Pour être complet, la source complète de ce calcul est incluse ci-dessous, mais je vous encourage à consulter la classe Location dans android.location pour vous-même. (Post-scriptum Je n'ai pas vérifié l'exactitude du calcul Android. Ce serait un bon exercice!)

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; 
     } 
    } 
} 
Questions connexes