Meilleure méthode pour l'élaboration des emplacements dans un rayon de point de départ
-
19-09-2019 - |
Question
Je vise à créer une fonction dans mon dernier projet de préférence en utilisant PHP. Lorsque chaque utilisateur signe jusqu'à ils vont entrer leur code postal. Alors, espérons que je convertira cela lat / long en utilisant Open Street Map.
Quoi qu'il en soit, je veux être en mesure de trouver d'autres utilisateurs situés à proximité de l'utilisateur actuel. Je l'ai vu beaucoup de personnes qui utilisent la formule Haversine, mais cela signifierait que l'utilisateur interrogé tous les détails de l'utilisateur de travailler sur la distance. Je pourrais mettre en cache cela, mais bientôt son va devenir obsolète en tant que nouveaux utilisateurs s'inscrire.
Quelle sorte d'effet serait d'exécuter la requête suivante sur mon système?
sql = "SELECT zipcode, ( 3959 * acos( cos( radians( {$coords['latitude']} ) )
* cos( radians( latitude ) ) * cos( radians( longitude )
- radians( {$coords['longitude']} ) )
+ sin( radians( {$coords['latitude']} ) ) * sin( radians( latitude ) ) ) )
AS distance FROM zipcodes HAVING distance <= {$radius} ORDER BY distance";
C'est tiré du blog de quelqu'un.
Je n'ai pas de chiffres pour le taux d'inscription ou le nombre d'utilisateurs car il est encore en développement.
Je vous serais reconnaissant des commentaires ou d'autres méthodes que je pourrais utiliser pour trouver des utilisateurs correspondant dans un rayon spécifique.
La solution
Il y a SIG et extensions spatiales à mySql dans la version 4.1, voir ici . D'après la description que vous trouverez qu'il est utilisé pour les problèmes que vous avez ici:
Un SIG (système d'information géographique) magasins et regarde des objets qui ont un ou plusieurs attributs spatiaux, tels la taille et la position, et est utilisée pour traiter de tels objets. Un exemple simple serait un système qui stocke adresses dans une ville à l'aide géographique des coordonnées. Si cela plutôt statique les données ont été ensuite combiné avec d'autres des informations telles que l'emplacement d'un -Taxi, alors ces données pourraient être utilisées pour trouver la cabine plus proche d'un certain emplacement.
Il ajoute plusieurs choses à MySql comme:
-
clés Spacial et le type de point:
CREATE TABLE adresse ( Adresse CHAR (80) NOT NULL, address_loc POINT NOT NULL, Clé primaire (adresse), SPATIAL KEY (address_loc) );
-
routines de conversion
INSERT INTO valeurs d'adresse ( 'rue Foobar 12', GeomFromText ( 'POINT (2671 2500)') );
-
fonctions de calcul SIG
SELECT c.cabdriver, ROND ( GLength (LineStringFromWKB (LineString (Binary (c.cab_loc), Binary (a.address_loc)))) ) que la distance De la cabine c, une adresse Commande pour Distance ASC LIMIT 1;
(exemples tirés de liaison ci-dessus)
Autres conseils
Le problème peut être grandement simplifiée si vous êtes prêt à desserrer la définition de « dans un certain rayon » de ne pas être spécifiquement un cercle. Si vous simplifiez à un « carré », vous trouverez tous les emplacements dans le « rayon » avec 2 simple « entre » clauses (un pour un lat longtemps). par exemple:
SELECT * FROM location WHERE
lat BETWEEN (my_lat - radius) AND (my_lat + radius)
AND long BETWEEN (my_long - radius) AND (my_long + radius);
Bien sûr, cela pourrait être utilisé pour sélectionner un sous-ensemble de vos sites avant d'utiliser une méthode plus précise pour calculer la distance réelle pour eux.
Il est vrai que cela est Javascript PHP pas, mais il serait trivial de convertir j'imagine.
Il calcule la distance entre deux points, ce qui représente la courbure de la Terre. Est utilisé application dans une logistique un certain temps avant de le remplacer par le code qui le fait en utilisant un itinéraire routier approprié.
peut être utiles pour vous ....
<script type="text/javascript">
function getDistance(lat1,lng1,lat2,lng2)
{
p1 = new VELatLong(lat1,lng1);
p2 = new VELatLong(lat2,lng2);
miles = true;
p1.Latitude= latLonToRadians(p1.Latitude);
p1.Longitude= latLonToRadians(p1.Longitude);
p2.Latitude= latLonToRadians(p2.Latitude);
p2.Longitude= latLonToRadians(p2.Longitude);
var R = 6371; // earth's mean radius in km
var dLat = p2.Latitude- p1.Latitude;
var dLong = p2.Longitude- p1.Longitude;
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(p1.Latitude) * Math.cos(p2.Latitude) * Math.sin(dLong/2) *
Math.sin(dLong/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var disKm = R * c;
var disMiles = disKm * 0.6214;
alert (miles ? disMiles : disKm);
}
// convert lat/long in degrees to radians
function latLonToRadians( point )
{
return point * Math.PI / 180;
}
</script>
Oh, et les objets VELatLong proviennent de l'API Virtual Earth ( http://msdn.microsoft.com/en-us/library/bb412519.aspx ), mais sont essentiellement glorifié struct, vous devriez donc être en mesure de trouver un remplaçant adéquat