2009-08-15 10 views
1

Ich habe eine Datenbank mit geokodierten Einträgen. Ich muss feststellen, welche zwei Einträge von einer Teilmenge der gesamten Einträge am weitesten entfernt sind. Zum Beispiel wähle ich eine Liste von 10 Einträgen, dann aus dieser Liste, welche zwei Orte die größte Entfernung innerhalb dieser Liste darstellen.Längster Abstand zwischen Längen/Breiten in einer Liste

Ich kann nicht meinen Kopf um, wie man sich nähert. Ich habe sogar überlegt, Radianten zu verwenden, aber nichts scheint die Anforderung zu erfüllen.

FYI, gehen LAMP-Stack hier ...

Antwort

2

Die folgende Abfrage berechnet den Abstand zwischen all Ihren Punkten und gibt die beiden mit dem größten Abstand zurück:

SELECT coor1.longitude as lon1, 
     coor1.latitude as lat1, 
     coor2.longitude as lon2, 
     coor2.latitude as lat2, 
     (ACOS(
     COS(RADIANS(coor1.latitude)) * 
     COS(RADIANS(coor1.longitude)) * 
     COS(RADIANS(coor2.latitude)) * 
     COS(RADIANS(coor2.longitude)) + 
     COS(RADIANS(coor1.latitude)) * 
     SIN(RADIANS(coor1.longitude)) * 
     COS(RADIANS(coor2.latitude)) * 
     SIN(RADIANS(coor2.longitude)) + 
     SIN(RADIANS(coor1.latitude)) * 
     SIN(RADIANS(coor2.latitude)) 
     ) * 6378      --- Use 3963.1 for miles 
     ) 
AS DistanceKM 
FROM coordinates coor1, 
    coordinates coor2 
WHERE NOT (coor1.longitude = coor2.longitude AND coor1.latitude = coor2.latitude) 
ORDER BY DistanceKM DESC 
LIMIT 1;         --- Only the biggest 

Jetzt empfehle ich, diese Berechnungen vor Hand durchzuführen und das Ergebnis in einer separaten Tabelle zu speichern.

+0

Dies wird die Antwort jedes Mal neu berechnen.Das kann oder kann nicht schlecht sein, abhängig von der Größe des Datensatzes und der Häufigkeit, mit der die Antwort angefordert wird. Außerdem ist es bei großen Systemen nicht sinnvoll, eine CPU-intensive Berechnung für die Datenbank vorzunehmen (häufig ist es besser, sie auf dem Anwendungsserver zu haben). Für kleine und mittlere Websites ist dies eine sehr gute Option. –

+0

Wie ich bereits sagte, empfehle ich, diese Berechnungen vor der Hand durchzuführen und das Ergebnis in einer separaten Tabelle zu speichern. Ich habe diese Abfrage zu Informationszwecken veröffentlicht. –

+0

das sieht vielversprechend aus, vielen dank. Der Anwendungsfall ist, dass Leute Ad-hoc-Listen von Einträgen erstellen können, denen ich dann eine Art Punktwert zuweisen muss (die Liste), basierend darauf, wie groß der Abstand ist. – Don

1

Brute-Force-Ansatz:

  1. Finden Sie die Mitte der Liste der zehn durch die Breiten- und Längenwerte gemittelt werden.

  2. Für jede (Breite, Länge) Paar in Ihrer Datenbank, verwenden Sie die großen Kreis Formel Abstand von der Mitte aus Schritt (1)

  3. Wählen größten zwei Entfernungen zu berechnen.

Offensichtliche Optimierung: brechen die Welt in N „Quadrate“ (beispielsweise 10 Grad Länge, 10 Grad nördlicher Breite) und vorge berechnen die Großkreisentfernung zwischen den Mittelpunkten jeder Paarung. Speichern Sie dies in der Datenbank. Jetzt können Sie schnell nach den am weitesten entfernten "Quadraten" suchen und nur die (Breiten-, Längen-) Paare innerhalb dieser Kacheln überprüfen.

+1

@Derobert: Diese Optimierung funktioniert nicht. Da ich Text für eine bessere Erklärung formatieren muss, siehe den unteren Teil meiner Antwort. –

+0

@Eric J: Das ist ein sehr guter Punkt. Aber ich denke, du könntest es umgehen, indem du ein paar zusätzliche Quadrate kontrollierst (aber immer noch viel weniger als alle). – derobert

0

Hier ist the algorithm in PHP für den Abstand zwischen zwei Punkten basierend auf Breite und Länge implementiert.

Beachten Sie, dass, wenn die "Teilmenge der Gesamteinträge" groß ist, Sie schnell einige Berechnungen durchführen müssen. Wenn dies der Fall ist, sollten Sie die Entfernungen zwischen Stadtpaaren vorab berechnen.

EDIT: Warum 10-Grad-Optimierung funktioniert nicht:

vier Quadrate nehmen, wie unten

------------------- 
|  |  | 
| A | B | 
|  |  | 
|_______1|________| 
|  |2  | 
| C | D | 
|  |  | 
|_______3|________| 

von nur Messung der Zentren der Quadrate und Vergleichen dieser Abstände gezeigt, erhalten Sie A und D weiter entfernt als A und C. Städte 1 und 3 liegen jedoch deutlich weiter auseinander als 1 und 2.

2

Durch die Optik könnte dies gelöst werden, indem zuerst die convex hull der Punkte (unter Verwendung Graham's scan, zum Beispiel), und dann tun rotating calipers für den Durchmesser auf diese.

+0

Das funktioniert, wenn Punkte in einer Ebene liegen. Wie machst du das für eine Kugel? – niteria

+0

Ich glaube, es funktioniert, solange alle Punkte auf der gleichen Seite eines großen Kreises sind (also auf der gleichen Hälfte der Kugel), obwohl das nur eine Ahnung ist, also halte mich nicht daran fest. –

+0

Es sollte für Halbkugel funktionieren. – niteria