Wie würde ich bei einer Datenbank mit Orten mit Längen- und Breitengraden wie 40.8120390, -73.4889650 alle Orte in einer bestimmten Entfernung von einem bestimmten Ort finden?
Es scheint nicht sehr effizient zu sein, alle Standorte aus der Datenbank auszuwählen und sie dann einzeln durchzugehen, um die Entfernung vom Startort zu ermitteln und festzustellen, ob sie innerhalb der angegebenen Entfernung liegen. Gibt es eine gute Möglichkeit, die ursprünglich ausgewählten Standorte aus der Datenbank einzugrenzen? Wenn ich eine eingegrenzte Anzahl von Orten habe (oder nicht?), Gehe ich sie immer noch einzeln durch, um die Entfernung zu überprüfen, oder gibt es einen besseren Weg?
Die Sprache, in der ich das mache, spielt keine Rolle. Vielen Dank!
Antworten:
Vergleichen Sie zunächst den Abstand zwischen den Breiten. Jeder Breitengrad ist ungefähr 111 Kilometer voneinander entfernt. Die Reichweite variiert (aufgrund der leicht ellipsoiden Form der Erde) von 110,567 km (68,703 Meilen) am Äquator bis 111,699 km (69,407 Meilen) an den Polen. Der Abstand zwischen zwei Orten ist gleich oder größer als der Abstand zwischen ihren Breiten.
Beachten Sie, dass dies für Längengrade nicht gilt - die Länge jedes Längengrads hängt vom Breitengrad ab. Wenn Ihre Daten jedoch an ein bestimmtes Gebiet gebunden sind (z. B. ein einzelnes Land), können Sie auch für die Längen eine minimale und maximale Grenze berechnen.
Fahren Sie mit einer schnellen Entfernungsberechnung mit geringer Genauigkeit fort, bei der sphärische Erde vorausgesetzt wird:
Der Großkreisabstand d zwischen zwei Punkten mit den Koordinaten {lat1, lon1} und {lat2, lon2} ist gegeben durch:
Eine mathematisch äquivalente Formel, die für kurze Entfernungen weniger Rundungsfehlern unterliegt, lautet:
d ist der Abstand im Bogenmaß
(6371 km ist der durchschnittliche Radius der Erde )
Die Berechnungsanforderungen für diese Methode sind minimal. Das Ergebnis ist jedoch für kleine Entfernungen sehr genau.
Wenn es sich dann mehr oder weniger in einer bestimmten Entfernung befindet, verwenden Sie eine genauere Methode.
GeographicLib ist die genaueste Implementierung, die ich kenne, obwohl auch die inverse Vincenty-Formel verwendet werden kann.
Wenn Sie ein RDBMS verwenden, legen Sie den Breitengrad als Primärschlüssel und den Längengrad als Sekundärschlüssel fest. Fragen Sie nach einem Breitengradbereich oder nach einem Breiten- / Längengradbereich ab, wie oben beschrieben, und berechnen Sie dann die genauen Entfernungen für die Ergebnismenge.
Beachten Sie, dass moderne Versionen aller wichtigen RDBMS geografische Datentypen und Abfragen nativ unterstützen.
quelle
Basierend auf dem Breiten- und Längengrad des aktuellen Benutzers und der Entfernung, die Sie suchen möchten, wird die SQL-Abfrage unten angegeben.
@latitude und @longitude sind der Breiten- und Längengrad des Punktes. Breite und Länge sind die Spalten der Entfernungstabelle. Der Wert von pi ist 22/7
quelle
PostgreSQL GIS-Erweiterungen können hilfreich sein - da sie möglicherweise bereits einen Großteil der Funktionen implementieren, die Sie implementieren möchten.
quelle
Tank´s Yogihosting
Ich habe eine Gruppe von Tabellen aus Open Streep Maps in meiner Datenbank und habe sie erfolgreich getestet.
Entfernung funktioniert gut in Metern.
quelle
Diese Fragen können hilfreich sein:
quelle
Wie von biziclop erwähnt, ist wahrscheinlich eine Art metrischer Raumbaum die beste Option. Ich habe Erfahrung mit kd-Bäumen und Quad-Bäumen, um diese Art von Bereichsabfragen durchzuführen, und sie sind erstaunlich schnell. Sie sind auch nicht so schwer zu schreiben. Ich würde vorschlagen, eine dieser Strukturen zu untersuchen, da Sie damit auch andere interessante Fragen beantworten können, z. B. "Was ist der nächstgelegene Punkt in meinem Datensatz zu diesem anderen Punkt?".
quelle
Was Sie brauchen, ist räumliche Suche. Sie können die Solr Spatial-Suche verwenden . Es wurde auch ein lat / long-Datentyp eingebaut. Überprüfen Sie dies hier .
quelle
Sie können Längen- und Breitengrade in das UTM-Format konvertieren. Hierbei handelt es sich um ein metrisches Format, mit dessen Hilfe Sie Entfernungen berechnen können. Dann können Sie leicht entscheiden, ob der Punkt an einer bestimmten Stelle liegt.
quelle
Da Sie sagen, dass jede Sprache akzeptabel ist, ist PostGIS die natürliche Wahl:
SELECT * FROM places WHERE ST_DistanceSpheroid(geom, $location, $spheroid) < $max_metres;
Wenn Sie WGS Datum verwenden möchten, sollten Sie setzen
$spheroid
auf'SPHEROID["WGS 84",6378137,298.257223563]'
Angenommen, Sie haben
places
nach dergeom
Spalte indiziert , sollte dies einigermaßen effizient sein.quelle
Dank der von @yogihosting bereitgestellten Lösung konnte ich ähnliche Ergebnisse aus schemenlosen Spalten von MySQL mit den unten gezeigten Codes erzielen:
Bitte beachten Sie, dass das obige Code-Snippet die Doctrine DB-Verbindung und PHP verwendet
quelle
Sie können diese Gleichung überprüfen, ich denke, es wird helfen
quelle