Frage

Dies kann oder nicht klar sein kann, lassen Sie mir einen Kommentar, wenn ich weg von der Unterseite ist, oder Sie weitere Informationen benötigen. Vielleicht gibt es aus einer Lösung bereits für das, was ich in PHP will.

Ich bin für eine Funktion, die einen Abstand von einem Länge oder Breite Wert addieren oder subtrahieren.

Grund: Ich habe eine Datenbank mit allen Latitudes und Longitudes darin und will eine Abfrage bilden alle Städte innerhalb X Kilometer zu extrahieren (oder Meilen). Meine Frage wie folgt aussehen würde ...

Select * From Cities Where (Longitude > X1 and Longitude < X2) And (Latitude > Y1 and Latitude < Y2)

 Where X1 = Longitude - (distance)
 Where X2 = Longitude + (distance)

 Where Y1 = Latitude - (distance)
 Where Y2 = Latitude + (distance)

Ich arbeite in PHP mit einer MySQL-Datenbank.

Offen für alle Anregungen auch! :)

War es hilfreich?

Lösung

Dies ist eine MySQL-Abfrage, die genau das tun, was Sie wollen. Denken Sie daran, Dinge wie diese Annäherungen sind im Allgemeinen, wie die Erde nicht perfekt sphärisch ist auch nicht berücksichtigt dies Berge, Hügel, Täler, etc .. Wir verwenden diesen Code auf AcademicHomes.com mit PHP und MySQL, gibt es Aufzeichnungen innerhalb $ radius Meilen von $ Breitengrad, Längengrad $.

$res = mysql_query("SELECT
    * 
FROM
    your_table
WHERE
    (
        (69.1 * (latitude - " . $latitude . ")) * 
        (69.1 * (latitude - " . $latitude . "))
    ) + ( 
        (69.1 * (longitude - " . $longitude . ") * COS(" . $latitude . " / 57.3)) * 
        (69.1 * (longitude - " . $longitude . ") * COS(" . $latitude . " / 57.3))
    ) < " . pow($radius, 2) . " 
ORDER BY 
    (
        (69.1 * (latitude - " . $latitude . ")) * 
        (69.1 * (latitude - " . $latitude . "))
    ) + ( 
        (69.1 * (longitude - " . $longitude . ") * COS(" . $latitude . " / 57.3)) * 
        (69.1 * (longitude - " . $longitude . ") * COS(" . $latitude . " / 57.3))
    ) ASC");

Andere Tipps

EDIT: Wenn Sie irgendwo eine Liste aller Städte in der Welt zusammen mit ihrem lat. und lang. Werte können Sie eine Lookup. In diesem Fall finden Sie in meinen ersten Link unten für die Formel, um die Breite eines Längs Grad an Breite zu berechnen alt text:

alt text

Ehrlich gesagt, sind die Komplikationen für dieses Problem, so dass Sie viel besser sein würde einen Dienst wie Google Maps off Nutzung Ihrer Daten zu erhalten. Insbesondere die Erde ist keine perfekte Kugel, und der Abstand zwischen zwei Grad variiert, wie Sie / weiter vom Äquator näher sind.

Siehe http://en.wikipedia.org/wiki/Geographic_coordinate_system Beispiele was ich meine, und schauen Sie sich der Google maps API .

Je nachdem, wie viele Städte, die Sie sind, einschließlich, können Sie die Liste vorauszuberechnen. Wir tun dies hier für eine interne Anwendung, bei der eine Ungenauigkeit von + 100 Mio. für unser Setup zu viel ist. Es funktioniert durch eine Zwei-Schlüssel-Tabelle von location1, location2, Entfernung mit. Wir können dann sehr schnell wieder Stellen x Abstand von location1 ziehen.

Auch da die calcs offline durchgeführt werden können, ist es nicht das Funktionieren des Systems auswirken. Benutzer auch schnelle Ergebnisse erzielen.

Habe versucht, den oben genannten Code verwenden, und die Antworten aus, indem zu viel waren, wenn der Abstand zwischen den Punkten in der 20-30 Meile Reichweite war, und ich bin mit einem paar Meilen von Fehlern ok. Sprach mit einem Mapping-Kumpel von mir und wir kamen mit diesem nach oben statt. Der Code ist Python, aber man kann es ziemlich leicht übersetzen. Um die ständige Umwandlung in Radiant zu vermeiden, redid ich meine Datenbank, die lat / lng Punkte von Grad in Radiant umzuwandeln. Das schöne daran ist, dass der größte Teil der Mathematik meist einmal durchgeführt wird.

ra = 3963.1906 # radius @ equator in miles, change to km  if you want distance in km
rb = 3949.90275  # radius @ poles in miles, change to km  if you want distance in km
ra2 = ra * ra
rb2 = rb * rb

phi = self.lat

big_ol_constant = (math.pow(ra2*math.cos(phi), 2) + pow(rb2*math.sin(phi), 2))/ (pow(ra*math.cos(phi), 2) + pow(rb*math.sin(phi), 2))

sqlWhere = "%(distance)g > sqrt((power(lat - %(lat)g,2) + power(lng-%(lng)g,2)) * %(big_ol_constant)g)" % {
    'big_ol_constant': big_ol_constant, 'lat': self.lat, 'lng': self.lng, 'distance': distance}

# This is the Django portion of it, where the ORM kicks in.  sqlWhere is what you would put after the WHERE part of your SQL Query.
qs = ZipData.objects.extra(where=[sqlWhere]);

Es scheint sehr genau zu sein, wenn Abstand klein ist, und innerhalb von 10 Meilen oder so wie der Abstand auf 200 Meilen wächst, (natürlich bis dahin, Sie haben Probleme mit „in der Luftlinie“ vs „gepflasterte Straßen“) .

Hier ist das Modell ZipData, dass ich oben erwähnt hat.

class ZipData(models.Model):
    zipcode = ZipCodeField(null=False, blank=False, verbose_name="ZipCode", primary_key=True)
    city = models.CharField(max_length=32, null=False, blank=False)
    state = models.CharField(max_length=2)
    lat = models.FloatField(null=False, blank=False)
    lng = models.FloatField(null=False, blank=False)

Eine zusätzliche Note, ist, dass Sie können viele Geodaten im Zusammenhang mit Postleitzahlen unter GeoNames. org und sie sogar einige Webservice-APIs haben Sie auch verwenden können.

Es gibt viele (schlechte Optionen)

  • den Abstand Berechnen der mathematischen Formel (treat X1-X2 und Y1-Y2) als Vektoren verwendet.

  • Erstellen Sie eine Lookup-Tabelle im Voraus mit allen Kombinationen und halten Sie die Abstände.

  • Betrachten wir ein GIS-spezifische Erweiterung von MySQL. Hier ist einen Artikel ich darüber gefunden .

lessthandot.com hat tatsächlich 3 verschiedene Möglichkeiten, dies zu tun. Sie werden ein wenig durch die Blogs blättern, aber sie sind da. http://blogs.lessthandot.com/

Die Funktion ist unten aus der nerddinner 's (ASP.NET MVC-Beispielanwendung auf Codeplex ) Datenbank (MSSQL).

ALTER FUNCTION [dbo].[DistanceBetween] (@Lat1 as real,
                @Long1 as real, @Lat2 as real, @Long2 as real)
RETURNS real
AS
BEGIN

DECLARE @dLat1InRad as float(53);
SET @dLat1InRad = @Lat1 * (PI()/180.0);
DECLARE @dLong1InRad as float(53);
SET @dLong1InRad = @Long1 * (PI()/180.0);
DECLARE @dLat2InRad as float(53);
SET @dLat2InRad = @Lat2 * (PI()/180.0);
DECLARE @dLong2InRad as float(53);
SET @dLong2InRad = @Long2 * (PI()/180.0);

DECLARE @dLongitude as float(53);
SET @dLongitude = @dLong2InRad - @dLong1InRad;
DECLARE @dLatitude as float(53);
SET @dLatitude = @dLat2InRad - @dLat1InRad;
/* Intermediate result a. */
DECLARE @a as float(53);
SET @a = SQUARE (SIN (@dLatitude / 2.0)) + COS (@dLat1InRad)
                 * COS (@dLat2InRad)
                 * SQUARE(SIN (@dLongitude / 2.0));
/* Intermediate result c (great circle distance in Radians). */
DECLARE @c as real;
SET @c = 2.0 * ATN2 (SQRT (@a), SQRT (1.0 - @a));
DECLARE @kEarthRadius as real;
/* SET kEarthRadius = 3956.0 miles */
SET @kEarthRadius = 6376.5;        /* kms */

DECLARE @dDistance as real;
SET @dDistance = @kEarthRadius * @c;
return (@dDistance);
END

Ich vermute, dass dies hilfreich sein könnte.

Sie können Satz des Pythagoras zu berechnen, die Nähe von zwei Paaren von lat / lon Punkten verwenden.

Wenn Sie zwei Standorten (Alpha und Beta) Sie ihre Entfernung berechnen kann außer mit:

SQRT( POW(Alpha_lat - Beta_lat,2) + POW(Alpha_lon - Beta_lon,2) )

das Setup von der folgenden URL verwenden, gebaut Ive die unten stehende Abfrage. (Bitte beachten Sie Im CodeIgnitor mit der Datenbank abzufragen)

http: / /howto-use-mysql-spatial-ext.blogspot.com/2007/11/using-circular-area-selection.html

function getRadius($point="POINT(-29.8368 30.9096)", $radius=2)
{
    $km = 0.009;
    $center = "GeomFromText('$point')";
    $radius = $radius*$km;
    $bbox = "CONCAT('POLYGON((',
        X($center) - $radius, ' ', Y($center) - $radius, ',',
        X($center) + $radius, ' ', Y($center) - $radius, ',',
        X($center) + $radius, ' ', Y($center) + $radius, ',',
        X($center) - $radius, ' ', Y($center) + $radius, ',',
        X($center) - $radius, ' ', Y($center) - $radius, '
    ))')";

    $query = $this->db->query("
    SELECT id, AsText(latLng) AS latLng, (SQRT(POW( ABS( X(latLng) - X({$center})), 2) + POW( ABS(Y(latLng) - Y({$center})), 2 )))/0.009 AS distance
    FROM crime_listing
    WHERE Intersects( latLng, GeomFromText($bbox) )
    AND SQRT(POW( ABS( X(latLng) - X({$center})), 2) + POW( ABS(Y(latLng) - Y({$center})), 2 )) < $radius
    ORDER BY distance
        ");

    if($query->num_rows()>0){
        return($query->result());
    }else{
        return false;
    }
}

Setzen Sie das Rad nicht neu erfinden. Dies ist eine räumliche Abfrage. Verwenden Sie MySQL Einbau-räumliche Erweiterungen die Breiten-Längen-Koordinaten-Daten in der nativen MySQL Geometriespalte Typ . Dann nutzen Sie die Entfernung Funktion für Punkte abzufragen, die innerhalb einer bestimmten Entfernung voneinander.

Disclaimer:. Dies beruht darauf, die Dokumentation zu lesen, ich habe das selbst nicht versucht,

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top