j'ai une ville comme point de départ avec ses données géographique, pare exemple Mortzwiller avec Latitude = 47.737756 et Longitude=7.034963999999945
ensuite grâce à ma basse de données de toutes les villes de France, j'ai envi de retrouver les communes située à 10Km de ma ville de dépar.
j'ai trouvé une équation mathématique sur google qui dit :
1° de latitude = 111.11 km
1° de longitude = 111.11 km * cos(latitude)
j'ai essayé d'appliqué un produit en croix pour résoudre mon probléme:
1° de latitude = 111.11 km
1° de longitude = 111.11 km * cos(1)= 60 km
donc pour mon probléme 10Km au alentour de ma ville je fais celà:
1° de latitude = 111.11 km
X° de latitude = 10 km
X° de latitude = 0.0900009
1° de longitude = 111.11 km * cos(1)= 60 km
X° de longitude =10 km
X° de longitude= 0.16666666666
puis :
Latitude de ma ville = 47.737756
X1 = 47.737756 + 0.0900009
X2 = 47.737756 - 0.0900009
Longitude de ma ville =7.034963999999945
Y1= 7.034963999999945 + 0.16666666666
Y2 = 7.034963999999945 - 0.16666666666
enfin je fait une recherche sur ma base de données: rechercher toutes les ville pour X2 < Latitude < X1 et Y1 < Longitude < Y2
malheureusement les résultats que me retourne ma base de donnes, c'est des commune qui sont plus loin des 10km, j'ai des communes qui sont situé à 25 ou meme 30 km de ma ville de départ
que faire ? j'ai mal utilisé l’équation mathématique ? c'est La distance à vol d'oiseau ? je n'arrive pas à trouver une solution !
Mais 1° de longitude = 111km, c'est vrai uniquement au niveau de l'équateur. Quand on est vers la France, 1° de longitude, ça ne représente plus que 80 km environ. il faudrait donc corriger avec cette nouvelle valeur.
Tu as un autre problème. C'est qu'en faisant X2<Latitude<X1 et Y1<Longitude<Y2, tu dessines en fait un carré (ou un rectangle) autour de ton point central, alors qu'il faudrait dessiner un rond.
Quand on est tout simplement sur une feuille de papier, plane, c'est avec une formule du type (x-x0)²+(y-y0)² < R² qu'on trouve les points qui sont dans un cercle.
Voilà ce qui ne va pas.
Maintenant, pour trouver la bonne formule, tu tapes 'calcul distance sur terre' dans la barre de recherche de ce site, et tu vas avoir des dizaines de sujets ouverts sur la question (rien que sur ce site, je ne parle pas d'autres sites)
Bonjour tbc92, Merci d'avoir pris le temps de me répondre
pour la longitude j'ai bien dit que c'est 1° de longitude = 111.11 km * cos(1)= 60 km, donc je ne sais pas si c'est juste ?!
effectivement je fais une recherche sur un carré (ou un rectangle) autour de mon point central, alors qu'il faudrait dessiner un rond, merci d'avoir fait la remarque je vais changer mon équation
je vais prendre le temps de lire les anciens post sur ce sujet pour trouver la solution adéquate à mon problème.
La formule avec le cosinus est juste (si on assimile la Terre à une sphère) et permet justement de corriger le souci dont tbc92 parlait. Mais tu as utilisé cos(1) (je viens de vérifier, ça donne bien 60 km en utilisant cos(1 radian) : attention de ne pas confondre 1 et l ! Et attention que si tu utilises des angles en degrés, il faut calculer les cosinus en degrés, par en radians.
Sinon, il faut savoir aussi que ces deux formules sont approximatives, mais ce sont de très bonnes approximations à courte distance, genre quelques kilomètres. Ça correspond à ton exemple, mais il ne faudrait pas les utiliser pour des recherches à quelques milliers de kilomètres. Bref, si tu es sûr de ne l'utiliser que sur quelques kilomètres, ce sont bien les formules à utiliser. (Mais comme l'a dit tbc92, le bon critère est : (x-x0)²+(y-y0)² < R².))
1- pour les radian vous avez raison, si pour 1° de latitude = 111.11 km dans ce cas 1° de Longitude = ????? 2- oui je vais faire des recherche sur maximum 5km en vole de oiseau 3- je n'arrive pas à utilisé (x-x0)²+(y-y0)² < R² dans mon cas !
voici ce que j’obtiens cette équation X2 < Latitude < X1 et Y1 < Longitude < Y2 pour 5km vole de oiseau de la ville de Mulhouse
$query2 = "SELECT * FROM `villes_france_free` WHERE `ville_longitude_deg` BETWEEN '$XLongitude1' AND '$XLongitude2' AND `ville_latitude_deg`BETWEEN '$XLatitude1' AND '$XLatitude2'";
la distance du trajet c'est la distance réelle que l'API Google map me retourne
1- pour les radian vous avez raison, si pour 1° de latitude = 111.11 km dans ce cas 1° de Longitude = ?????
Eh ben, c'est la formule que tu as citée au tout début ! 1° de longitude, ça fait 111,11 km multiplié par le cosinus de la latitude.
Exemple : à Paris, la latitude vaut à peu près 48°. Donc 1° de longitude fait 111,11 x cos(48°) = 111,11 x 0,669 = 74 km.
À part ça, je ne comprends pas la fin de ton message. Les distances obtenues, ce sont celles que tu as calculées et tu dois vérifier si elles sont correctes ? Mais tu dis qu'elles viennent de Google. Donc pourquoi tu les affiches ?
si LO1 et LA1 sont les longitudes et latitudes de la ville centrale, et si D est la distance max acceptée , et si toutes les longitudes/latitudes sont en degrés :
SELECT * FROM villes_france_free WHERE (ville_longitude_deg-LO1)*111*cos(LA1) * (ville_longitude_deg-LO1)*111*cos (LA1) + (ville_latitude_deg-LA1)*111 * (ville_latitude_deg-LA1)*111 < D*D
SELECT * FROM `villes_france_free` WHERE `ville_longitude_deg` BETWEEN '7.2466' AND '7.4133' AND `ville_latitude_deg`BETWEEN '47.70499' AND '47.79500'
je sélectionne toutes les villes qui ont longitude entre '7.2466' et '7.4133' et latitude entre '47.70499' et '47.79500'
robun a écrit:
À part ça, je ne comprends pas la fin de ton message. Les distances obtenues, ce sont celles que tu as calculées et tu dois vérifier si elles sont correctes ? Mais tu dis qu'elles viennent de Google. Donc pourquoi tu les affiches ?
une fois que je trouve les villes à 5km de vole de oiseau je vais calculer la distance réelle entre la ville trouvé et ma ville de départ avec Google API pour garder par exemple que les ville qui sont à 8km ou 10km de trajet
tbc92 a écrit:
SELECT * FROM villes_france_free WHERE (ville_longitude_deg-LO1)*111*cos(LA1) * (ville_longitude_deg-LO1)*111*cos (LA1) + (ville_latitude_deg-LA1)*111 * (ville_latitude_deg-LA1)*111 < D*D
avec cette raquette je dois appliquer des calculs sur chaque ville de ma BDD, ça deviendra lourd ! moi l’objectif c'est trouvé un résultat avec une seule requête
maintenant je me demande si ma méthode de calcul est juste ou fausse ? comment amélioré les calculs ?
1° de longitude = 111.11 km * cos(1)= 60 km ==> je ne sais pas si cela est juste
Mais évidemment que c'est faux ! J'en ai parlé plus haut, et j'ai montré comment calculer ça. C'est faux parce que tu calcules le cosinus de un (1) et non de l (l), la latitude. Et j'ai donné un exemple (quand la latitude vaut 48°) de comment on doit le calculer.
La requete que j'ai donné permet de bâtir un cercle, au lieu de bâtir un rectangle, c'est ce que tu veux faire.
Si tu l'as testée, peux- tu déjà verifier si elle donne un résultat exact.
Ensuite, il se peut que cette requête soit trop lente, et il se peut qu'en aidant le système, en lui donnant le rectangle circonscrit, ça aide le système à aller vite.
Dans ce cas là on va dire : trouve moi dans un premier temps les villes qui sont dans un certain carré ( tu dis que ça va vite, ok), puis parmi ces villes, trouve moi les villes qui sont aussi dans le cercle voulu.
Du coup, ce n'est plus une question de maths, mais une question d'optimisation de temps de traitement. Et la bonne réponse va ressembler à ça :
select * from
( SELECT * FROM villes_france_free
WHERE ville_latitude between LA_MINI and LA_MAXI and ville_longitude between LO_MINI and LO_MAXI)
where (ville_longitude_deg-LO1)*111*cos(LA1) * (ville_longitude_deg-LO1)*111*cos (LA1)
Avec LA_MINI et LA_MAXI et LO_MINI et LO_MAXI déterminés à peu près comme tu faisais jusque là.
J'ai juste un doute, je suis parti du fait que tous les angles étaient en degrés, et je ne sais pas si dans ton système d'exploitation, la fonction cos() attend des degrés ou des radians.
Mais, on a fait 99% du boulot, tu peux faire les 1% restants.
1° de longitude = 111.11 km * cos(1)= 60 km ==> je ne sais pas si cela est juste
Mais évidemment que c'est faux ! J'en ai parlé plus haut, et j'ai montré comment calculer ça. C'est faux parce que tu calcules le cosinus de un (1) et non de l (l), la latitude. Et j'ai donné un exemple (quand la latitude vaut 48°) de comment on doit le calculer.
- Edité par robun 19 janvier 2018 à 15:21:49
Bonjour j'ai pris un peu le temps pour revoir de A à Z ce que nous avons dit sur ce post, vous avez raison j'ai corrigé mon équation 1° de longitude = 111.11 km * cos(1)= 60 km ==> elle fausse bien sur
maintenant sur mon site je fais comme ceci :
$cosinusLong=cos(deg2rad($villeDepartLatitude)); //je fais un cos de Latitude de ma ville de depart en radian, je converti mes degré en radian avec deg2rad
$UnLongitude=111.11*$cosinusLong; // puis je multiplie * 111.11km
$XLongitude=5/$UnLongitude; / puis je calcul ma longitude pour 5km vol d'oiseau
maintenant j'ai des meilleurs résultats
maintenant il me reste la question de faire un cycle ou un rectangle(carré), je dois travailler cette patrie ce qu'est mieux pour mon site !
vous remercie tout les deux pour vous réponses qui m'on vraiment aidé pour trouvé une solution adéquate à mon probléme
sujet résolut
je vais aussi partager mon code php si au plus tard quelqu’un passe par là et qu'il a le même probléme
$ville=$_POST["ville"];
if (empty($ville)){echo'rien';}
else {
// remplacer les espaces les "-" des ville par des + pour le bon fonctionnement de API google
$VilleDepartApi = str_replace(CHR(32),"+",$ville); // ici si ma ville est Le Mans ==> Le+Mans
$VilleDepartApi = str_replace("-","+",$VilleDepartApi); // ici si ma ville est Saint-Etien ==> Saint+Etien
$France='+France';
if (preg_match("#France#i",$VilleDepartApi))
{} else {
$VilleDepartApi=$VilleDepartApi.$France;
}
// j'utilise API google map geocode/json pour exteraire les donnees geographiques de mes adresses
$url = 'https://maps.googleapis.com/maps/api/geocode/json?address='.$VilleDepartApi.'&key=' . $apiKey'';
$handle = curl_init($url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($handle);
$responseDecoded = json_decode($response, true);
$responseCode = curl_getinfo($handle, CURLINFO_HTTP_CODE); //Here we fetch the HTTP response code
curl_close($handle);
$villeDepartLatitude= $responseDecoded['results'][0]['geometry']['location']["lat"];
$villeDepartLongitude= $responseDecoded['results'][0]['geometry']['location']["lng"];
$XLatitude=0.0.4500045;
$cosinusLong=cos(deg2rad($villeDepartLatitude));
$UnLongitude=111.11*$cosinusLong;
$XLongitude=5/$UnLongitude;
$XLatitude1= $villeDepartLatitude-$XLatitude;
$XLatitude2= $villeDepartLatitude+$XLatitude;
$XLongitude1=$villeDepartLongitude-$XLongitude;
$XLongitude2=$villeDepartLongitude+$XLongitude;
$query2 = "SELECT * FROM `villes_france_free` WHERE `ville_longitude_deg` BETWEEN '$XLongitude1' AND '$XLongitude2' AND `ville_latitude_deg`BETWEEN '$XLatitude1' AND '$XLatitude2'";
$result2 = mysql_query($query2,$connexion) or die(mysql_error());
$total2 = mysql_num_rows($result2);
if($total2 > 0) {
while($row2 = mysql_fetch_array($result2)){
$villenom=$row2['ville_nom'];
$villeCp=$row2['ville_code_postal'];
$VilleArriveeApi = str_replace(CHR(32),"+",$villenom); // ici si ma ville est Le Haut Soultzbach ==> Le+Haut+Soulzbach
$VilleArriveeApi = str_replace("-","+",$VilleArriveeApi); // ici si ma ville est Saint-Lô ==> Saint+Lô
if (preg_match("#France#i",$VilleArriveeApi))
{} else {
$VilleArriveeApi=$VilleArriveeApi.$France;
}
$url = 'https://maps.googleapis.com/maps/api/distancematrix/json?origins='.$VilleDepartApi.'&destinations='.$VilleArriveeApi.'+'.$villeCp.'&key=' . $apiKey; // l'url pour calculer la distance et le temps entre deux ville
// je recupere les infos en json avec ce code ...
$handle = curl_init($url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($handle);
$responseDecoded = json_decode($response, true);
$responseCode = curl_getinfo($handle, CURLINFO_HTTP_CODE); //Here we fetch the HTTP response code
curl_close($handle);
echo 'la ville '.$villenom.' la distance du trajet est: '. $responseDecoded['rows'][0]["elements"][0]["distance"]["text"].'</br>'; // j'extrais la distance entre mes deux villes en metre et je l'affiche
}
}
}
il faut juste une clé de google map API et c'est gratuit
@jpmacveigh Bonsoir, répondre aux questions c'est bien, le faire dans les règles du forum c'est mieux. C'est votre deuxième déterrage je vous envoie un MP.
Avant de poster un message, vérifiez la date du sujet dans lequel vous comptiez intervenir.
Si le dernier message sur le sujet date de plus de deux mois, mieux vaut ne pas répondre. En effet, le déterrage d'un sujet nuit au bon fonctionnement du forum, et l'informatique pouvant grandement changer en quelques mois il n'est donc que rarement pertinent de déterrer un vieux sujet.
Au lieu de déterrer un sujet il est préférable :
soit de contacter directement le membre voulu par messagerie privée en cliquant sur son pseudonyme pour accéder à sa page profil, puis sur le lien "Ecrire un message"
soit de créer un nouveau sujet décrivant votre propre contexte
ne pas répondre à un déterrage et le signaler à la modération
jpmv