110 votes

Obtenir la distance entre deux points géographiques

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

Quel serait le meilleur moyen de connaître le lieu le plus proche de la liste par rapport à la position actuelle de l'utilisateur ?

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

173voto

praveen Points 131
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)

2 votes

Probablement plus lent que Location.DistanceBetween() puisqu'il utilise des objets de localisation, mais il fonctionne très bien pour mes besoins.

0 votes

Quelle classe je dois importer pour l'emplacement import android.location.Location; ou qui

0 votes

@PranavMS oui Android.location.Location ;

122voto

haseman Points 6071

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

Regardez dans distanceTo 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);

37 votes

DistanceBetween est une méthode statique qui prend 2 ensembles de points de longitude, donc vous n'avez même pas besoin d'instancier un objet Location =)

4 votes

Je suis sûr qu'il voulait dire ça pour distanceTo méthode.

0 votes

C'est génial et super utile, mais à quoi sert le fournisseur de String dans le constrructeur ?

34voto

Laurent Points 1589

Une solution approximative (basée sur une projection équirectangulaire), beaucoup plus rapide (il ne nécessite qu'une racine trigonométrique et une racine carrée).

Cette approximation est pertinente si vos points ne sont pas trop éloignés les uns des autres. Elle toujours surestimer par rapport à la distance haversine réelle. Par exemple, il ajoutera pas plus de 0,05382 %. à la distance réelle si le delta de latitude ou de longitude entre vos deux points ne dépasse pas 4 degrés décimaux .

La formule standard (Haversine) est la suivante exact (c'est-à-dire qu'il fonctionne pour tout couple de longitude/latitude sur la terre) mais est beaucoup plus lent car elle nécessite 7 trigonométries et 2 racines carrées. Si vos deux points ne sont pas trop éloignés l'un de l'autre, et que la précision absolue n'est pas primordiale, vous pouvez utiliser cette version approximative (Equirectangulaire), qui est beaucoup plus rapide car elle n'utilise qu'une trigonométrie 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 encore davantage soit par :

  1. Suppression de la racine carrée si vous comparez simplement la distance à une autre (dans ce cas, comparez les deux distances au carré) ;
  2. Factorisation du cosinus si vous calculez la distance d'un point maître à plusieurs autres (dans ce cas, vous faites la projection équirectangulaire centrée sur le point maître, de sorte que vous pouvez 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 belle implémentation de référence de la formule de Haversine en plusieurs langues à l'adresse suivante : http://www.codecodex.com/wiki/Calculate_Distance_Between_Two_Points_on_a_Globe

0 votes

Un grand homme, merci. Mais si j'ai besoin d'obtenir un ensemble d'emplacements autour d'un emplacement dans un périmètre, dois-je utiliser une boucle while pour vérifier chaque emplacement par rapport à celui recherché et ne garder que ceux qui sont dans le périmètre ?

0 votes

Vous pouvez, mais c'est une approche par la force brute en O(n) . Pour un O(1) utiliser un index spatial 2D pour éliminer les correspondances potentielles avant de calculer la solution exacte. Nous sortons du cadre de cette question :)

0 votes

C'est un très bon résumé des optimisations possibles merci ! C'est exactement ce que je cherchais

12voto

Dwaine Bailey Points 300

Il existe plusieurs méthodes que vous pouvez utiliser, mais pour déterminer laquelle est la meilleure, nous devons d'abord savoir si vous connaissez l'altitude de l'utilisateur, ainsi que l'altitude des autres points ?

En fonction du niveau de précision que vous recherchez, vous pouvez utiliser les formules Haversine ou Vincenty...

Ces pages détaillent les formules et, pour les moins matheux, fournissent également une explication sur la façon de les implémenter en script !

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

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

Si vous avez des problèmes avec l'une des significations des formules, il suffit de commenter et je ferai de mon mieux pour y répondre :)

4voto

Nepster Points 893

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

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

Voir ceci

et le second

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X