OK - Je me lance avec ceci depuis environ 3 mois et éteint et depuis que j'ai épuisé toutes les formules de proximité de la Geo que j'ai rencontrées et que je ne suis pas plus proche d'obtenir les bons résultats que j'ai figuré Il est temps de demander de l'aide.
L'objectif fort> p> Je configure une implémentation assez basique d'un localisateur de magasins. L'utilisateur entre dans leur code postal et sélectionne dans une liste prédéfinie de rayi de recherche. L'API GMAPS génère des coordonnées Lat / Long pour cette adresse et les transmet à un script PHP. Dans ce script, les coordonnées utilisateur sont interrogées sur une table de base de données MySQL (structure ci-dessous) p> Les résultats de cette requête (ID POST) sont entrés dans une requête WordPress qui génère la XML contenant les données du marqueur de carte. (La requête WordPress utilise post__in et posts_per_page -1 pour afficher des informations pour tous les identifiaires générés par la requête p> en un mot, chaque mise en œuvre de La formule Haversine que j'ai rencontrée semble entraîner des marqueurs manquants - plus particulièrement tous les marqueurs qui sont très proches des utilisateurs saisis des coordonnées (ne savent pas précisément, mais je pense que c'est à environ 500 m). C'est un gros problème comme si le l'utilisateur entre dans leur code postal et qu'il y a un magasin très proche de son emplacement, il ne s'affichera pas. P> J'ai essayé environ 8 permutations différentes de la forumla que j'ai creusé de divers tutoriels avec le mêmes résultats. Vous trouverez ci-dessous la formule que j'utilise actuellement sur le site, qui fournit à tous les marqueurs, à l'exception des personnes très proches des utilisateurs saisis Position: P> $center_lat = $_GET["lat"];
$center_lng = $_GET["lng"];
$radius = $_GET["radius"];
$sql = "
SELECT post_id, lat, lng,
truncate((degrees(acos( sin(radians(lat))
* sin(radians(".$center_lat."))
+ cos(radians(lat))
* cos(radians(".$center_lat."))
* cos(radians(".$center_lng." - lng) ) ) )
* 69.09*1.6),1) as distance
FROM wp_geodatastore HAVING distance <= ".$radius." ORDER BY distance desc
"; // End $sqlcircleradius
$result = mysql_query($sql);
$row = mysql_fetch_array( $result );
while($row = mysql_fetch_array( $result )) {
// Print out the contents of each row
$post_ids[] = $row['post_id'];
}
5 Réponses :
Voici une solution que j'ai utilisée avec succès pendant un certain temps dans mes propres calculs de proximité géographique:
Merci d'avoir posté le code @fleep. Malheureusement, tandis que cela fonctionnait en général, je suis toujours terminé avec le même problème de marqueur manquant. Appréciez la tentative cependant!
EDIT strong>
Cet emplacement finder est assez souvent que j'ai écrit un article sur elle. http://www.plumislandmedia.net/mysql/haversine-mysql-nearest-loc/ p> original post strong> p> le début de Let en traitant avec la formule Haversine une fois pour toutes, en le mettant dans une fonction stockée afin que nous puissions oublier ses détails noueux. NOTE: Cette solution complète est en miles. P> $sql_stmt = sprintf ("
SELECT post_id, lat, lng
FROM
(
SELECT post_id, lat, lng,
(3959 * ACOS(COS(RADIANS(lat))
* COS(RADIANS(%$1s))
* COS(RADIANS(lng) - RADIANS(%$2s))
+ SIN(RADIANS(lat))
* SIN(RADIANS(%$1s))
))
AS distance
FROM wp_geodatastore
WHERE lat >= %$1s -(%$3s/69)
AND lat <= %$1s +(%$3s/69)
AND lng >= %$2s -(%$3s/69)
AND lng <= %$2s +(%$3s/69)
)a
WHERE distance <= %$3s
ORDER BY distance
",$center_lat,$center_lng, $radius);
Merci pour la réponse très détaillée Ollie. Avoir du mal à la mettre en œuvre pour le tester. Désolé d'être une douleur mais je ne connais vraiment pas les procédures stockées MySQL (je peux travailler sur une base de données MySQL avec phpmyadmin, mais c'est à peu près où mes connaissances mysql sèchent). C'était un coup d'œil autour de certains tutoriels sur la création de fonctions stockées en utilisant cette interface graphique mais n'ont rien trouvé pour me guider. Est-il essentiel que la formule de Haversine soit dans ce format ou pouvait-elle être incluse avec le reste de la requête PHP?
Merci pour Edit Ollie - apprécie vous la convertir à PHP et à toute l'aide jusqu'à présent. Malheureusement, il ne semble pas du tout produire des valeurs d'identification. Doublé vérifié le code pour vous assurer que je n'ai rien fait stupide - ne pouviez rien voir. Également essayé votre suggestion de changer le spécificateur de type dans le sprintf mais aucun changement. N'était pas sûr si le minuscule "A" dans votre code était intentionnel ou une faute de frappe, mais de toute la manière dont il n'a produit aucun résultat.
J'ai récompensé la prime à cette réponse parce que c'était la réponse la plus complète et la plus expliquée (malgré cela ne l'utilise pas à la fin - voir ma propre réponse ci-dessous sur laquelle je roule pour l'instant). Cela a déclaré que cette question a généré de très bonnes réponses et je suis sûr que les équations énumérées ci-dessous fonctionneraient probablement pour les projets d'autres peuples avec une configuration différente à la mienne, de sorte qu'ils valent bien la peine de regarder.
Vous pouvez essayer ma classe à http://www.phpclasses.org/package/6202-php-generat-points-of-an-hilbert-curve.html . Il utilise la formule Harvesine et une courbe Hilbert pour calculer un quadkek. Vous pouvez ensuite rechercher le quadkek de gauche à droite. Chaque position de la clé est un point sur la courbe du monstre. Une meilleure explication de la courbe peut être trouvée à l'index spatial de Nick Quadtree Hilbert Curve Blog. C'est comme en utilisant l'extension de l'indice spatial de MySQL mais vous avez plus de contrôle. Vous pouvez utiliser une courbe Z ou une courbe Moore ou vous pouvez changer le look. p>
Ceci est code d'un système de production de travail,
6371.04 * acos(cos(pi()/2-radians(90-wgs84_lat)) * cos(pi()/2-radians(90-$lat)) * cos(radians(wgs84_long)-radians($lon)) + sin(pi()/2-radians(90-wgs84_lat)) * sin(pi()/2-radians(90-$lat))) as distance
Penser un peu latéralement, je suis proposé une solution de «sorte» au problème des marqueurs manquants. Les deux équations que j'ai postées donnaient à l'origine ont donné les résultats corrects, mais chacun a raté les marqueurs proches de la cible ou sur les bords du rayon de recherche p>
Ce n'est pas très élégant, mais j'ai pensé à faire fonctionner les deux équations et à produire 2 tableaux que j'ai ensuite combiné (enlever tous les doublons) me donnerait tous les marqueurs que je recherche. Cela fonctionne (évidemment une performance touchée mais ce n'est pas une application de trafic élevée), je vais donc travailler avec cela pour le moment, mais je suis toujours après une solution plus pratique si quelqu'un en a une! P>
Y a-t-il une raison pour laquelle vous n'utilisez pas les capacités géospitalières construites de MySQL? dev.mysql.com/ Doc / Refman / 5.0 / FR / ...
J'ai du mal à comprendre des choses dans votre code. Pourquoi
ayant code> au lieu de
où code>? Ce qui se passe avec le
int code> trucs dans
(flotteur) $ center_lat - ((int) $ rayon / 69); code> et le
tronquent code> dans votre autre requête? Gardez ce fait à l'esprit lorsque vous appliquez les formules: une minute de longitude à l'équateur est définie comme un mile nautique. Un diplôme entier est de 60 milles nautiques. Enfin, essayez de vous débarrasser de
entre code> et utiliser "où a> = lat1 et a <= lat2` à la place. Il devrait donner la même complexité de la requête et épelle l'inclusivité / l'exclusivité de la plage que vous recherchez.
@Kenneth - Je n'utilise pas les requêtes géospatiales pour quelques raisons. Premièrement, j'utilise le Plugin Geo Data Store pour créer et maintenir mon Tableau des données de marqueur. Ce plugin génère la structure de la table que j'ai montrée ci-dessus. Deuxièmement, la grande majorité des tutoriels que j'ai rencontrés pour créer des cartes de type de localisation de magasin semblent recommander une structure de table semblable à celle indiquée. Peut-être que ce ne sont pas les meilleures raisons, mais je suis venu aussi loin avec la configuration actuelle et je suis sûr que ce que j'essaie de faire devrait être possible.
@Olliejones appréciez les conseils. Le
ayant code> (au lieu de
où code> semble recadrer sur presque toutes les formules que j'ai rencontrées (y compris l'une des Didacticiel Google Maps . Le
int code> ne doit probablement pas être là - i devait tellement frustré que j'ai commencé à partir dans des choses qui auraient probablement pu être dépouillées de formules que j'ai trouvées (ne semblait pas avoir de différence pour les résultats de toute façon. J'ai essayé votre
entre code> / < Code> Où Code> Suggestion mais j'ai bien peur qu'il a brisé la requête - voir le prochain commentaire pour ce que j'ai essayé:
où lat> = ". $ $ lat1." Et lat <= ". $ $ Lat2." Et lng> = ". $ $ Gng1." Et lat <= ". $ Gng2." Code>
Vous voudrez peut-être examiner les réponses à cette question Stackoverflow.com/questions/574691/...
@Olliejones Si vous filtrez sur un alias de colonne, en particulier d'une valeur calculée (comme la distance dans ce cas), vous devez utiliser au lieu de votre lieu de travail. C'est parce que le point au point où la clause d'où est évaluée, la valeur de la colonne Alias peut être encore connue. La clause WHERE sélectionne les enregistrements à utiliser, puis des alias de colonne sont calculés sur la base de ces enregistrements, puis enfin b>, la clause filtre les valeurs d'alias de colonne.
@ LJ902 Avez-vous essayé d'exécuter les deux requêtes (rayon carré et rayon de cercle) séparément pour un emplacement donné et vérifiant les résultats pour la raison pour laquelle les enregistrements «manquants» sont manquants? Je supposerais qu'ils apparaissent dans la requête de rayon carré mais sont exclus dans la requête de Rayon Circle. Quelle distance est cette requête calculant pour ces magasins?
@MliusBrown - n'avait pas pensé à exécuter les deux requêtes de manière autonome (bien que des versions antérieures de la formule étaient fondamentalement la partie de la requête de rayon de cercle et ils ont manqué les marqueurs voisins). J'ai essayé le calcul du rayon carré par lui-même et j'ai de nouveau produit les résultats manquants. Donc, je ne suis fondamentalement pas le plus sage de ce qui cause la question.
Je rencontre le même problème.
@SID - Voir ma solution "Sorte de" dans les réponses ci-dessous. J'ai tout travaillé comme ça devrait être maintenant si je suis sûr que ce n'est pas la façon la plus efficace de faire des choses. Il y a d'autres vraiment bonnes réponses ci-dessous aussi que je devrais probablement fonctionner, mais cela pourrait être un problème avec le reste de ma configuration qui les empêche d'être aussi précis que possible