[PHP/SQL] Géolocalisation et distance entre des villes
Posté le 24. sept, 2008 par Tony Samson dans Développement Web
J’ai besoin pour un développement spécifique mais aussi pour Agenda Culturel de pouvoir lister dans un script PHP les villes à proximité d’une ville donnée. Concrètement, cela signifie afficher les villes situées à l’intérieur d’un périmètre d’une distance de X kilomètres de la ville de référence.
J’ai longuement cherché sur le web, et je n’ai trouvé que peu d’infos à ce sujet. Je vous livre ici le résultat de mes recherches et de mes multiples tests, de l’intégration des coordonnées de latitude/longitude à l’aide des API de géolocalisation google map et yahoo map jusqu’à la requête sql finale qui inclue la formule de calcul de distance à partir des coordonnées géolocalisées.

Une base de donnée fiable des villes associées à leurs coordonnées de latitude/longitude
En premier lieu, il s’agit d’avoir une base de données de villes. Il en existe de nombreuses sur le net, celle-ci intègre même les coordonnées de latitude et de longitude.
Dans mon cas, je possédais déjà une base de données de villes françaises mais sans ces coordonnées. La meilleure méthode pour y intégrer la latitude et la longitude de chaque ville est d’utiliser l’API de Yahoo ou de google.
Ces deux API permettent de récupérer un flux XML correspondant à la recherche (ex : Amiens, France) contenant la latitude et la longitude.
Par exemple, voici le résultat de la recherche de la ville d’Amiens avec l’API de Yahoo :
<ResultSet xsi:schemaLocation="urn:yahoo:maps http://api.local.yahoo.com/MapsService/V1/GeocodeResponse.xsd">
<Result precision="zip">
<Latitude>49.896309</Latitude>
<Longitude>2.279720</Longitude>
<City>80000 Amiens</City>
<State>France</State>
<Country>FR</Country>
</Result>
</ResultSet>
Il n’y a donc plus qu’à faire une boucle sql sur la table des villes en parsant le flux de yahoo ou google correspondant (en indiquant la ville, le code postal et le pays) et intégrer à l’enregistrement de la ville la latitude et la longitude. Un vrai jeu d’enfant avec simplexml en php5 ! Cependant, même si ces API sont puissantes, il se peut que parfois la ville ne soit pas trouvée, que la ville retournée ne soit pas la bonne ou que plusieurs résultats soient retournés. Pour plus d’informations, et pour choisir entre les API de Yahoo et de Google, je vous invite à lire cet article sur la géolocalisation via yahoo et google map très bien fait et qui m’a bien aidé.
Vous avez à présent une table contenant les villes associées à leurs coordonnées géographique de latitude et de longitude.
Il ne reste plus qu’à exploiter cela dans une requête SQL et afficher le tout en PHP.
J’ai d’abord tenté une conversion des données latitude/longitude en points de coordonnées lambert 2 étendue (norme française) grâce à la fonction geos2lambert() disponible sur google code mais son exploitation s’est révélé compliquée et imprécise (ou alors c’est moi qui suis vraiment nul en maths !).
Je suis donc reparti sur les données de latitude/longitude. Grâce à une formule mathématique complexe trouvée sur le net je suis arrivé au résultat suivant.
Je reçois en variable GET les coordonnées de ma ville de référence :
$latitude=$_GET[lat];
$longitude=$_GET[lon];
La fameuse formule utilisant les colonnes lat et lon de ma table sql et les données de latitude et longitude de ma ville de référence :
$formule="(6366*acos(cos(radians($latitude))*cos(radians(`lat`))*cos(radians(`lon`) -radians($longitude))+sin(radians($latitude))*sin(radians(`lat`))))";
Et la requête SQL prête à être exécutée :
$sql="SELECT ville,$formule AS dist FROM ville WHERE $formule<='$_GET[distance]' ORDER by dist ASC";
- le SELECT $formule AS dist permet de classer les villes de la plus proche à la plus éloignée avec ORDER by dist ASC
- le WHERE $formule<=’$_GET[distance]‘ permet de définir un rayon en km ($_GET[distance]) à partir de la ville de référence
Je vous laisse coder l’éxécution de la requête sql et l’affichage des données en php, ce n’est pas vraiment le plus dur !
Vous pouvez voir le résultat sur cette page. La ville de référence est ici Amiens avec un périmètre de 15 km.
En guise de conclusion…
Il faut savoir que ce calcul et le résultat ne sont pas précis pour plusieurs raisons :
- Le calcul ne tient pas compte de l’altitude, qui, dans certains endroits peut influer sur les distances
- La formule a été simplifiée au maximum par souci de simplicité et d’efficacité.
- La distance est « à vol d’oiseau » et non pas une distance routière
- La localisation latitude/longitude d’une ville repose sur un point (généralement la mairie de la ville en question), donc la distance ne commence pas à la sortie de la ville mais du centre de la ville. Ainsi, par exemple, pour Paris cela ne sert à rien de vouloir localiser les villes à 5km…
Cependant, malgré l’imprécision cela fonctionne, car l’intérêt premier est d’afficher les villes proches et non de concurrencer google map ! Il convient juste de ne pas forcément afficher les distances en km qui sont souvent fausses (à quelques kilomètres près).
L’utilisation de cette technique qui est finalement assez simple à mettre en place peut être très utile sur du web local afin d’élargir les recherches sur une ville aux villes à proximité (dans le cas où aucune réponse n’est disponible pour la ville concernée par exemple) ou proposer d’autres villes ou contenus (ou publicités géolocalisées !) à l’internautes en rapport avec sa requête.
Si vous avez des questions sur la mise en place d’une recherche de proximité ou si cet article vous a aidé, n’hésitez pas, les commentaires sont fait pour ça !
Antoine
11. mar, 2009
merci pour cet article
philgood
24. mar, 2009
Très interessant, très bien rédigé
merci pour ce partage
topheur
08. avr, 2009
Trop bon.
Merci beaucoup pour cette article.
Question : tu dis dans ton article que tu utilises un calcul simpifié. Sais tu ou trouver la version non simplifié ?
Titcoatch
19. mai, 2009
Merci c’était parfait pour ce que je voulais faire et ça marche du tonnerre.
Ptigob
21. juil, 2009
Cool c’est la formule qu’il me fallait merci msieur
Return
28. juil, 2009
Bonjour,
Article très bien réalisé. Merci pour le partage.
Une petite remarque : le lien ne marche plus
Tony Samson
30. juil, 2009
Voilà le lien de démo est corrigé.
@topheur : pour ce qui est de la formule plus complexe je ne saurais dire où je l’avais trouvé… désolé.
Tony Samson
31. juil, 2009
Formule plus complexe en tenant compte que la terre est ronde (donc plus précis) :
http://fr.wikipedia.org/wiki/Distance_du_grand_cercle
Portekoi
27. août, 2009
Merci à toi pour cet article fort intéressant
fabien tanguy
13. sept, 2009
la formule exacte a un nom celle d’haversine.
merci pour cet article très clair et très enrichissant
PizzaToy
30. oct, 2009
Bonjour,
un grand merci pour la formule et le code, c’est vrai ça marche du tonnerre !
L’intérêt d’une telle application est multiple. On s’approche du logique de géomarketing en délimitant une zone de chalandise. On peut y adapter un curseur pour faire varier le rayon de notre recherche. Un des points intéressant est que, par exemple, une ville se trouvant limitrophe de plusieurs départements renverra un balayage complet de sa zone en une seule recherche; alors qu’un simple moteur par départemnt obligera de relancer la procédure.
Pour ma part j’ai ajouté un Autocompleter et une carte inréractive, tout ça avec 3 bases de données : une pour les départements et les préfectures, une autre pour les villes et positions (35000 points), et les adresses des pizzerias affiliées ou pas au concept http://www.pizzatoy.com.
Encore merci
Jerem
19. jan, 2010
Salut Mec, bon article ! Du vrai tuto, comme on les aime
Continue +++
Sun Location
10. mar, 2010
Super cet article, bien simpa en tout cas !
merci
drhouse
22. avr, 2010
Article sympa
Merci bcp
Adrien
24. avr, 2010
Merci pour ton tuto bien sympa
Par contre, juste pour info, dans mon cas la formule ne fonctionnais pas après plusieurs tentatives, du coup j’ai trouvé ceci, qui semble fonctionner pour moi :
http://code.google.com/intl/fr/apis/maps/articles/geospatial.html#geospatial
A savoir que c’est en miles, donc x1.6 et quelques ^^
Merci encore
NAS
14. mai, 2010
Yes ! intéressant tout ça ! Si en plus tu nous donnais un petit fichier SQL avec la table des villes de france
ce serait le top 
mais déjà merci