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

- Microsoft Regional Director 2.0 ! par Le blog de Patrick [MVP Office 365] le 02-23-2015, 22:10

- TechDays Paris 2015: Malware unchained par Blog Technique de Romelard Fabrice le 02-12-2015, 22:58

- TechDays Paris 2015: La transformation du SI avec le Cloud Microsoft, quel sera le rôle de la DSI demain, comment le Cloud MS accompagne cette transfo... par Blog Technique de Romelard Fabrice le 02-12-2015, 22:51

- TechDays Paris 2015: L’intranet social avec Office 365 et Yammer - quelles possibilités d’intégration ? par Blog Technique de Romelard Fabrice le 02-12-2015, 22:46

- TechDays Paris 2015: Plenière jour 3 - Vers une technologie invisible et une intelligence omniprésente ? par Blog Technique de Romelard Fabrice le 02-12-2015, 10:59

- TechDays Paris 2015: Geek is in da {new} House par Blog Technique de Romelard Fabrice le 02-12-2015, 01:13

- TechDays Paris 2015: Windows Server vNext - Virtualisation et Stockage par Blog Technique de Romelard Fabrice le 02-12-2015, 00:26

- TechDays Paris 2015: Quoi de neuf dans Windows 10 ? par Blog Technique de Romelard Fabrice le 02-11-2015, 23:37

- TechDays Paris 2015: Réussir sa migration vers Office 365 en formant les uilisateurs par Blog Technique de Romelard Fabrice le 02-11-2015, 14:32

- TechDays Paris 2015: Windows 10 et PowerShell 5.0 par Blog Technique de Romelard Fabrice le 02-11-2015, 13:10