web-dev-qa-db-fra.com

Obtenez la distance entre deux points géographiques

Je veux faire une application qui vérifie l'endroit le plus proche où se trouve un utilisateur. Je peux facilement obtenir l'emplacement de l'utilisateur et j'ai déjà une liste d'endroits avec latitude et longitude.

Quel serait le meilleur moyen de connaître l'emplacement le plus proche de la liste par rapport à l'emplacement actuel de l'utilisateur. 

Je n'ai rien trouvé dans les API de Google. 

104
Chmouel Boudjnah
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);

Référence: http://developer.Android.com/reference/Android/location/Location.html#distanceTo(Android.location.Location)

140
praveen

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

Regardez dans distance ou distanceBetween. Vous pouvez créer un objet Location à partir d'une latitude et d'une longitude:

Location location = new Location("");
location.setLatitude(lat);
location.setLongitude(lon);
121
haseman

Une solution approchée (basée sur une projection équirectangulaire), beaucoup plus rapide (il ne nécessite que 1 trig et 1 racine carrée).

Cette approximation est pertinente si vos points ne sont pas trop éloignés. Il sera toujours surestimé} par rapport à la distance réelle. Par exemple, il ajoutera pas plus de 0,05382% à la distance réelle si la latitude ou la longitude du delta entre vos deux points ne dépasse pas 4 degrés décimaux.

La formule standard (Haversine) est le exact (c'est-à-dire que cela fonctionne pour tout couple de longitude/latitude sur la terre) mais est beaucoup plus lent car il nécessite 7 trigonométriques et 2 carrés. les racines. Si vos points ne sont pas trop éloignés et que la précision absolue n’est pas primordiale, vous pouvez utiliser cette version approximative (Equirectangular), qui est beaucoup plus rapide car elle n’utilise qu’une racine trigonométrique et une racine carrée.

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

Vous pouvez optimiser cela plus loin} soit:

  1. _ {Suppression de la racine carrée} _ si vous comparez simplement la distance à une autre (dans ce cas, comparez les deux distance au carré);
  2. (Factorisation du cosinus) si vous calculez la distance d'un point maître à plusieurs autres (dans ce cas, vous projetez la projection équirectangulaire centrée sur le point maître afin de pouvoir calculer le cosinus une fois pour toutes les comparaisons).

Pour plus d'informations, voir: http://www.movable-type.co.uk/scripts/latlong.html

Il existe une implémentation de référence de Nice de la formule Haversine dans plusieurs langues à l’adresse: http://www.codecodex.com/wiki/Calculate_Distance_Between_Two_Points_on_a_Globe

29
Laurent Grégoire

Vous pouvez utiliser plusieurs méthodes, mais pour déterminer laquelle est la meilleure, nous devons d’abord savoir si vous connaissez l’altitude de l’utilisateur ainsi que celle des autres points.

Selon le niveau de précision recherché, vous pouvez utiliser les formules Haversine ou Vincenty ...

Ces pages détaillent les formules et, pour les moins enclins à la mathématique, expliquent également comment les implémenter dans un script!

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

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

Si vous rencontrez des problèmes de signification dans les formules, n'hésitez pas à commenter et je ferai de mon mieux pour y répondre :)

10
Dwaine Bailey

Il y a deux façons d'obtenir une distance entre LatLng.

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

Regarde ça

et deuxieme

public float distanceTo (Location dest) comme répondu par praveen.

3
Xar E Ahmer
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];
    }
2
Levon Petrosyan

Utilisez simplement la méthode suivante, passez-le lat et long et obtenez la distance en mètre:

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;
}
0
farhad.kargaran

vous pouvez obtenir distance et temps en utilisant Google Map API Google Map API

il suffit de passer JSON téléchargé à cette méthode, vous obtiendrez en temps réel la distance et le temps entre deux latlong 

void parseJSONForDurationAndKMS(String json) throws JSONException {

    Log.d(TAG, "called parseJSONForDurationAndKMS");
    JSONObject jsonObject = new JSONObject(json);
    String distance;
    String duration;
    distance = jsonObject.getJSONArray("routes").getJSONObject(0).getJSONArray("legs").getJSONObject(0).getJSONObject("distance").getString("text");
    duration = jsonObject.getJSONArray("routes").getJSONObject(0).getJSONArray("legs").getJSONObject(0).getJSONObject("duration").getString("text");

    Log.d(TAG, "distance : " + distance);
    Log.d(TAG, "duration : " + duration);

    distanceBWLats.setText("Distance : " + distance + "\n" + "Duration : " + duration);


}
0
saigopi