2009-07-28 13 views
3

Ich möchte ein Feature in meinem neuesten Projekt vorzugsweise mit PHP erstellen. Wenn sich jeder Benutzer anmeldet, wird er seine Postleitzahl eingeben. Dann werde ich das hoffentlich mit Open Street Map in lat/long umwandeln.Beste Methode zum Erarbeiten von Orten in einem Umkreis von

Ich möchte in der Lage sein, andere Benutzer in der Nähe des aktuellen Benutzers zu finden. Ich habe viele Leute gesehen, die die Haversine-Formel verwenden, aber das würde bedeuten, dass der Benutzer die Details jedes anderen Benutzers abgefragt hat, um die Entfernung zu berechnen. Ich könnte dies cachen, aber es wird bald veraltet sein, wenn neue Benutzer sich anmelden.

Welche Auswirkung hätte die Ausführung der folgenden Abfrage auf mein System?

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"; 

Das ist von jemandes Blog gezogen.

Ich habe keine Zahlen für die Anmeldequote oder die Anzahl der Benutzer, da es noch in der Entwicklung ist.

Ich würde mich über Rückmeldungen oder andere Methoden freuen, die ich verwenden könnte, um passende Benutzer innerhalb eines bestimmten Radius zu finden.

+0

ist das wirklich eine PHP-Frage? klingt eher nach einer SQL-Frage. –

+0

Bevorzugte Sprachen sind PHP/MySQL. Ich wusste nicht, ob es irgendwelche Möglichkeiten gibt, dies mit PHP zu erreichen, die sonst übersehen wurden (natürlich abgesehen von den Berechnungen in PHP). –

Antwort

2

Es gibt GIS und Spatial Extensions zu mySql in Version 4.1, siehe here. Aus der Beschreibung finden Sie, dass es für Probleme verwendet wird, wie haben Sie hier:

Ein GIS (Geographisches Informationssystem) speichert und sucht Objekte, die eine oder mehrere räumliche Attribute, wie wie Größe haben und Position, und wird verwendet, um solche Objekte zu verarbeiten. Ein einfaches Beispiel wäre ein System, das Adressen in einer Stadt unter Verwendung geographischer Koordinaten speichert. Wenn diese eher statischen Daten wurden dann mit anderen Informationen, wie zum Beispiel die Position eines Taxi-Fahrerhaus kombiniert, dann könnten diese Daten verwendet werden, um die nächstgelegene Kabine zu einem bestimmten Standort zu finden.

Es fügt mehrere Dinge zu MySql wie:

  • Spacial Schlüssel und dem Typ POINT:

    TABLE-Adresse CREATE ( Adresse CHAR (80) NOT NULL, address_loc POINT NOT NULL, PRIMÄRSCHLÜSSEL (Adresse), SPATIAL SCHLÜSSEL (address_loc) );

  • Konvertierungsroutinen

    INSERT INTO Adreßwerte ('Foobar Strasse 12', GeomFromText ('-Punkt (2671 2500)'));

  • GIS Berechnungsfunktionen

    SELECT c.cabdriver, ROUND (GLength (LineStringFromWKB (Linestring (AsBinary (c.cab_loc), AsBinary (a.Adresse_loc))))) AS Abstand VON Kabine c, Adresse a ORDER BY Entfernung ASC LIMIT 1;

(Beispiele aus obigen Link genommen)

+1

Außer dass Koordinatensysteme auf einer 2D-Basis arbeiten. Ich habe GLength nachgeschlagen und es gibt keinen Hinweis darauf, dass es die sphärische Geometrie berücksichtigt oder etwas anderes als eine pythagoräische Theoremberechnung tut. –

+0

Das sieht gut aus! Ich werde es heute nach der Arbeit noch einmal durchlesen, sieht so aus, als ob ich danach suche! –

0

Zwar ist dies Javascript nicht PHP, aber es wäre trivial zu konvertieren Ich kann mir vorstellen würde.

Er berechnet den Abstand zwischen zwei Punkten unter Berücksichtigung der Erdkrümmung. Es wird eine Weile in einer Logistik-App verwendet, bevor es durch einen Code ersetzt wird, der eine richtige Straßenroute verwendet.

Es könnte für Sie von Nutzen sein ....

<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, und VELatLong Objekte stammen aus der Virtual Earth API (http://msdn.microsoft.com/en-us/library/bb412519.aspx), aber sind im Grunde eine verherrlichte Struktur, so dass Sie sein sollen in der Lage, einen geeigneten Ersatz zu finden

+0

OP fragt nicht über PHP (Tag wahrscheinlich entfernt werden soll), sondern um SQL-Abfragen. –

+0

Eigentlich sagt er, dass er dieses Projekt in PHP implementieren möchte und dass er an allen Methoden interessiert ist, um Benutzer in einem bestimmten Radius zu finden. –

+0

Danke für die Eingabe. Nicht genau das, was ich suchte, aber es gibt mir ein wenig Einblick in die Mathematik erforderlich! –

1

Das Problem kann stark vereinfacht werden, wenn Sie bereit sind, die Definition von "innerhalb eines bestimmten Radius" zu lockern, um nicht spezifisch ein Kreis zu sein. Wenn Sie zu einem "Quadrat" vereinfachen, können Sie alle Position innerhalb des "Radius" mit 2 einfachen "zwischen" Klauseln finden (eine für lat eins für lange). zB:

SELECT * FROM location WHERE 
    lat BETWEEN (my_lat - radius) AND (my_lat + radius) 
    AND long BETWEEN (my_long - radius) AND (my_long + radius); 

Natürlich, das verwendet werden könnte, um eine Teilmenge Ihrer Standorte auszuwählen, bevor eine genauere Methode mit dem tatsächlichen Abstand zu ihnen zu berechnen.

+0

wahr ... obwohl technisch unterscheidet diese gegen Personen in der Nähe der internationalen Datumsgrenze oder der Nord/Südpol :-) –

+0

Es stimmt, weshalb „square“ ist in Anführungszeichen :) –

+0

Dies ist auch super! Ich habe noch nie zuvor mit Lat gearbeitet. Also theoretisch könnte ich meine ursprüngliche Abfrage auf einer Teilmenge von Daten durchführen, die von diesem zurückgegeben werden. Guter Gedanke! –

Verwandte Themen