109 votes

Calcul de la distance entre deux points, en utilisant la latitude et la longitude?

Voici mon essai, c'est juste un extrait de mon code :

final double RADIUS = 6371.01;
double temp = Math.cos(Math.toRadians(latA))
            * Math.cos(Math.toRadians(latB))
            * Math.cos(Math.toRadians((latB) - (latA)))
            + Math.sin(Math.toRadians(latA))
            * Math.sin(Math.toRadians(latB));
    return temp * RADIUS * Math.PI / 180;

J'utilise cette formule pour obtenir la latitude et la longitude :

x = Deg + (Min + Sec / 60) / 60)

245voto

David George Points 2328

Le code Java donné par Dommer donne des résultats légèrement incorrects mais les petites erreurs s'accumulent si vous traitez par exemple une piste GPS. Voici une implémentation de la méthode Haversine en Java qui prend également en compte les différences de hauteur entre deux points.

/**
 * Calcul de la distance entre deux points en latitude et longitude en tenant
 * compte de la différence de hauteur. Si vous ne vous intéressez pas à la
 * différence de hauteur, passez 0,0. Utilise la méthode Haversine comme base.
 * 
 * lat1, lon1 Point de départ lat2, lon2 Point d'arrivée el1 Altitude de départ en mètres
 * el2 Altitude d'arrivée en mètres
 * @returns Distance en mètres
 */
public static double distance(double lat1, double lat2, double lon1,
        double lon2, double el1, double el2) {

    final int R = 6371; // Rayon de la terre

    double latDistance = Math.toRadians(lat2 - lat1);
    double lonDistance = Math.toRadians(lon2 - lon1);
    double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
            + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
            * Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    double distance = R * c * 1000; // conversion en mètres

    double height = el1 - el2;

    distance = Math.pow(distance, 2) + Math.pow(height, 2);

    return Math.sqrt(distance);
}

7 votes

Pourquoi ne pas utiliser Math.toRadians() à la place de deg2rad()? Ce serait vraiment auto-contenu.

2 votes

@Bala - Désolé, c'est dans le commentaire sur le code sur mon ordinateur mais manquant ici. Distance en mètres.

4 votes

@ÁronNemmondommegavezetéknevem J'ai mis à jour la méthode pour utiliser votre très bonne suggestion.

87voto

dommer Points 11550

Voici une fonction Java qui calcule la distance entre deux points lat/long, postée ci-dessous, au cas où elle disparaîtrait à nouveau.

    private double distance(double lat1, double lon1, double lat2, double lon2, char unit) {
      double theta = lon1 - lon2;
      double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta));
      dist = Math.acos(dist);
      dist = rad2deg(dist);
      dist = dist * 60 * 1.1515;
      if (unit == 'K') {
        dist = dist * 1.609344;
      } else if (unit == 'N') {
        dist = dist * 0.8684;
        }
      return (dist);
    }

    /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
    /*::  Cette fonction convertit les degrés décimaux en radians      :*/
    /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
    private double deg2rad(double deg) {
      return (deg * Math.PI / 180.0);
    }

    /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
    /*::  Cette fonction convertit les radians en degrés décimaux       :*/
    /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
    private double rad2deg(double rad) {
      return (rad * 180.0 / Math.PI);
    }

    System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, 'M') + " Miles\n");
    System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, 'K') + " Kilomètres\n");
    System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, 'N') + " Milles Nautiques\n");

1 votes

Google Map montre 200 Kms pour 12.915700, 77.632046, 11.665154, 78.145657 alors que le code ci-dessus montre 149.82 Kms. Quelque chose ne va pas encore.

3 votes

@Samy la fonction ci-dessus vous donne la distance en ligne droite.

1 votes

Mon royaume pour que les développeurs étiquettent leurs variables avec les Unités. double dist => double distInMiles (ou similaire) (Je ne critique pas la personne qui a posté cette réponse, je vote en faveur.......mais plutôt l'implémenteur original du code)

21voto

granadaCoder Points 6390

Les futurs lecteurs qui tombent sur cet article SOF.

De toute évidence, la question a été posée en 2010 et nous sommes maintenant en 2019. Mais elle apparaît en tête des résultats d'une recherche internet. La question originale ne exclut pas l'utilisation d'une bibliothèque tierce (quand j'ai écrit cette réponse).

public double calculateDistanceInMeters(double lat1, double long1, double lat2,
                                     double long2) {

    double dist = org.apache.lucene.util.SloppyMath.haversinMeters(lat1, long1, lat2, long2);
    return dist;
}

et

  org.apache.lucene
  lucene-spatial
  8.2.0

https://mvnrepository.com/artifact/org.apache.lucene/lucene-spatial/8.2.0

Veuillez lire la documentation sur "SloppyMath" avant de vous plonger!

https://lucene.apache.org/core/8_2_0/core/org/apache/lucene/util/SloppyMath.html

0 votes

Êtes-vous sûr que c'est correct? ce fichier jar ne contient pas de ".util", je viens de le vérifier.

0 votes

C'est pourquoi je publie toujours la version avec une réponse. Assurez-vous d'obtenir la version 8.2.0. 13 votes positifs suggèrent également qu'une réponse est précise.

2 votes

Je pense que c'est une mauvaise pratique d'ajouter une dépendance à quelque chose si vous pouvez le remplacer par 28 lignes dans votre code, sauf si vous utilisez plus de cette dépendance

15voto

zahmde Points 151

Note: cette solution ne fonctionne que pour de courtes distances.

J'ai essayé d'utiliser la formule postée par dommer pour une application et j'ai trouvé qu'elle fonctionnait bien pour de longues distances mais dans mes données, j'utilisais uniquement de très courtes distances et le post de dommer s'en sortait très mal. J'avais besoin de vitesse, et les calculs géographiques plus complexes fonctionnaient bien mais étaient trop lents. Donc, dans le cas où vous avez besoin de vitesse et que toutes les calculs que vous réalisez sont courts (peut-être < 100m ou ainsi). J'ai trouvé cette petite approximation très efficace. Elle suppose que le monde est plat, donc ne l'utilisez pas pour de longues distances, elle fonctionne en approximant la distance d'une seule latitude et longitude à la latitude donnée et en renvoyant la distance de Pythagore en mètres.

public class FlatEarthDist {
    //retourne la distance en mètres
    public static double distance(double lat1, double lng1, 
                                  double lat2, double lng2){
     double a = (lat1-lat2)*FlatEarthDist.distPerLat(lat1);
     double b = (lng1-lng2)*FlatEarthDist.distPerLng(lat1);
     return Math.sqrt(a*a+b*b);
    }

    private static double distPerLng(double lat){
      return 0.0003121092*Math.pow(lat, 4)
             +0.0101182384*Math.pow(lat, 3)
                 -17.2385140059*lat*lat
             +5.5485277537*lat+111301.967182595;
    }

    private static double distPerLat(double lat){
            return -0.000000487305676*Math.pow(lat, 4)
                -0.0033668574*Math.pow(lat, 3)
                +0.4601181791*lat*lat
                -1.4558127346*lat+110579.25662316;
    }
}

0 votes

Est-ce que quelqu'un pourrait ajouter des détails si c'est plus efficace pour les courtes distances que la réponse acceptée ici: stackoverflow.com/a/16794680/1537394 ?

5voto

Chris Taylor Points 25865

Voici une page avec des exemples de javascript pour divers calculs sphériques. Le premier en haut de la page devrait vous donner ce dont vous avez besoin.

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

Voici le code Javascript

var R = 6371; // km
var dLat = (lat2-lat1).toRad();
var dLon = (lon2-lon1).toRad(); 
var a = Math.sin(dLat/2) * Math.sin(dLat/2) + 
        Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) *
        Math.sin(dLon/2) * Math.sin(dLon/2); 
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
var d = R * c;

Où 'd' contiendra la distance.

0 votes

Peut "a" être négatif ?

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