Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Matthieu Napoli

blog technique

Géolocalisation et approximations (ou comment simplifier le calcul avec des latitudes et longitudes en PHP)

Bonjour à tous,
Aujourd'hui, un petit article sur la manipulation de coordonnées géographiques dans vos applications, notamment ici dans un site web en PHP.

Cet article fait suite au peu de documentation que j'ai constaté en recherchant le web.

1ère méthode : Calculs précis

Le "calcul précis" présenté ici est déjà une approximation, mais c'est la solution qu'on rencontre le plus souvent dans les forums :

define('RAYON_TERRE', 6378137);

/**
* Retourne la distance précise à vol d'oiseau entre 2 coordonnées
* @param double latitude du point 1
* @param double longitude du point 1
* @param double latitude du point 2
* @param double longitude du point 2
* @return double Distance entre les points 1 et 2
*/

function get_distance_precis($lat1, $long1, $lat2, $long2)
{
  $rlo1 = deg2rad($long1);
  $rla1 = deg2rad($lat1);
  $rlo2 = deg2rad($long2);
  $rla2 = deg2rad($lat2);

  $dlo = ($rlo2 - $rlo1) / 2;
  $dla = ($rla2 - $rla1) / 2;
  $a = (sin($dla) * sin($dla)) + cos($rla1) * cos($rla2) * (sin($dlo) * sin($dlo));
  $d = 2 * atan2(sqrt($a), sqrt(1 - $a));

  return (RAYON_TERRE * $d);
}

Bilan :

  • Calcul compliqué et lent
  • Propre à PHP, s'implémente difficilement dans une requête SQL (pour faire un SELECT en prenant en compte la distance par exemple)

2ème méthode : Approximation

On remarquera que le calcul suivant renvoie un résultat linéaire :

echo get_distance_precis(0.0, 0.0, 0.001, 0);
echo get_distance_precis(0.0, 0.0, 0.01, 0);
echo get_distance_precis(0.0, 0.0, 0.1, 0);
echo get_distance_precis(0.0, 0.0, 1., 0.);

111.31949079327
1113.1949079327
11131.949079327
111319.49079327

On peut donc utiliser le facteur proportionnel get_distance_precis(0.0, 0.0, 1., 0.) ce qui donne la fonction suivante :

define('CONVERSION_LATLONG_METRES', 111319.49079327);

/**
* Retourne la distance approximative à vol d'oiseau entre 2 coordonnées
* @param double latitude du point 1
* @param double longitude du point 1
* @param double latitude du point 2
* @param double longitude du point 2
* @return double Distance entre les points 1 et 2
*/

function get_distance_approx($lat1, $long1, $lat2, $long2)
{
  $delta_lat = $lat2 - $lat1;
  $delta_long = $long2 - $long1;
  $dist_lat = $delta_lat * CONVERSION_LATLONG_METRES;
  $dist_long = $delta_long * CONVERSION_LATLONG_METRES;
  $distance = sqrt($dist_lat * $dist_lat + $dist_long * $dist_long);
  return $distance;
}

Vérification des résultats :

echo get_distance_precis(0.0, 0.0, 0.001, 0);
echo get_distance_precis(0.0, 0.0, 0.01, 0);
echo get_distance_precis(0.0, 0.0, 0.1, 0);
echo get_distance_precis(0.0, 0.0, 1., 0.);
echo get_distance_approx(0.0, 0.0, 0.001, 0);
echo get_distance_approx(0.0, 0.0, 0.01, 0);
echo get_distance_approx(0.0, 0.0, 0.1, 0);
echo get_distance_approx(0.0, 0.0, 1., 0.);

111.31949079327
1113.1949079327
11131.949079327
111319.49079327

111.31949079327
1113.1949079327
11131.949079327
111319.49079327

Bilan :

  • Calcul simple et rapide
  • Peut s'implémenter facilement dans une requête SQL en utilisant le facteur de conversion.

Bonus : Faire l'inverse, décaler une latitude/longitude avec une distance

Au lieu de calculer la distance entre 2 points, on peut vouloir décaler une coordonnées (pour par exemple faire un carré autour d'un point).
Pour cela voici la fonction suivante :

define('CONVERSION_LATLONG_METRES', 111319.49079327);

/**
* Décale la latitude ou la longitude de la distance spécifiée
* @return angle de décalage
*/

function get_angle_decalage_geo($distance)
{
  return $distance / CONVERSION_LATLONG_METRES;
}

Cette fonction renvoie le décalage à appliquer à une latitude ou une longitude pour obtenir un point situé à la distance précisée.

Vérification des résultats :

echo get_angle_decalage_geo(100);
echo get_distance_approx(0.0, 0.0, get_angle_decalage_geo(100), 0.);

0.00089831528411955
100

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :
Posted: lundi 13 juillet 2009 11:01 par MadMatt
Classé sous : , ,

Commentaires

LeFauve42 a dit :

Solution tres elegante, mais es-tu sur que cela fonctionne dans tous les cas ?

Je remarque que tu ne testes pas les decalages de longitude.

Si tu te deplace de 90 degres de longitude sur l'equateur (lattitude de 0 degres), tu fais (environ) 10000km, mais si tu te deplaces de 90 degres de longitude a partir du pole nord (lattitude de 90 degres), tu ne bouges pas :o)

As-tu regarde l'extension OpenGIS de MySQL ? Je ne suis pas sur que ca reponde entierement a ton probleme, mais ca doit le simplifier un peu(http://dev.mysql.com/doc/refman/5.4/en/gis-introduction.html)

Eric

# juillet 20, 2009 10:42

MadMatt a dit :

Non cela ne fonctionne pas dans tous les cas car le but est d'approximer le calcul, notamment pour des distances de l'ordre du km, en France (du moins pas pour les extrêmes comme le pole Nord ^^).

J'utilise ça pour des calculs de distance de moins de 500m, donc ça marche très bien ;)

En tout cas je ne connaissais pas OpenGIS, merci pour l'info, ça a l'air vraiment intéressant.

# juillet 20, 2009 11:01

LeFauve42 a dit :

OK :o)

Si tu utilises cette formule uniquement pour la France, tu aurais interet a utiliser deux constantes au lieu de CONVERSION_LATLONG_METRES :

- Une pour les lat (celle que tu as est pas mal)

- Une pour les long, que tu pourrais calculer pour une lat de 46.5 degres (a la louche, le milieu de la France (si on ne compte pas la Corse)).

Ton calcul ne serait pas plus lent, mais ton approximation serait bien meilleure :o)

Eric

# juillet 20, 2009 13:52
Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- [ SharePoint Summit 2014 ] L’utilisation de SharePoint 2013 pour la mise en place d’un site Internet Grand Public par Le blog de Patrick [MVP SharePoint] le il y a 12 heures et 38 minutes

- [ SharePoint Summit Montréal 2014 ] Mes présentations sont en ligne par Le blog de Patrick [MVP SharePoint] le il y a 15 heures et 13 minutes

- [ SharePoint Summit Montréal 2014 ] L'intelligence d'affaire dans O365 : enfin facile et économique grâce aux dernières évolution de la Power BI par Le blog de Patrick [MVP SharePoint] le il y a 16 heures et 22 minutes

- [ SharePoint Summit Montréal 2014 ] Kit de démarrage rapide pour de la collaboration en mode Intranet avec SharePoint par Le blog de Patrick [MVP SharePoint] le 04-14-2014, 18:40

- [ SharePoint Summit Montréal 2014 ] Une conférence francophone majeure autour de SharePoint par Le blog de Patrick [MVP SharePoint] le 04-14-2014, 15:52

- [status.modern.ie] Tout savoir sur les futures versions d'Internet Explorer par Philippe Didiergeorges Aka Philess le 04-08-2014, 11:07

- Problèmes de compatibilité avec Visual Studio 2013 ? par Blog de Jérémy Jeanson le 04-07-2014, 22:04

- [ #Yammer ] Comment basculer l’interface en français ? par Le blog de Patrick [MVP SharePoint] le 04-06-2014, 15:29

- [WF] Programmer n’est pas jouer par Blog de Jérémy Jeanson le 04-03-2014, 06:24

- MBA : Quelle formation après un MBA ? par Blog Technique de Romelard Fabrice le 03-26-2014, 12:37