Ich benutze PostGIS, um die nächsten Nachbarn von Polygonen zu berechnen. Was ich berechnen möchte, ist der Mindestabstand von jedem Polygon zum nächsten Polygon.
Bisher hat mir die Antwort von Mike Toews (die ich mit einer kleinen Änderung zitiere) hier sehr geholfen :
SELECT
a.hgt AS a_hgt,
b.hgt AS b_hgt,
ST_Distance(a.the_geom, b.the_geom) AS distance_between_a_and_b
FROM
public."TestArea" AS a, public."TestArea" AS b
WHERE
a.hgt != b.hgt AND ST_Distance(a.the_geom, b.the_geom) < 400
Dann habe ich das Minimum berechnet:
SELECT a_hgt, MIN(distance_between_a_and_b)
FROM public."lon_TestArea"
GROUP BY a_hgt
Meine Herausforderung besteht jedoch darin, dies für eine große Anzahl von Polygonen (1.000.000) zu berechnen. Da die obige Berechnung jedes Polygon mit jedem anderen Polygon vergleicht, habe ich mich gefragt, wie ich die Berechnung verbessern kann, damit ich keine 10 ^ 12-Berechnungen durchführen muss.
Ein Gedanke, den ich hatte, war, jedes Polygon zu puffern und dann die nächsten Nachbarn aller Werte innerhalb des Puffers für dieses Polygon zu berechnen und das Minimum aufzuzeichnen. Ich bin mir nicht sicher, ob dies der beste Ansatz ist oder ob es eine Funktion in PostGIS gibt, die ich verwenden sollte.
EDIT: Mit einem von Nicklas 'Vorschlägen experimentiere ich mit ST_Dwithin()
:
CREATE TABLE mytable_withinRange AS SELECT
a.hgt AS a_hgt,
b.hgt AS b_hgt,
ST_DWithin(a.the_geom, b.the_geom, 400)
FROM
public."lon_TestArea" AS a, public."lon_TestArea" AS b
Dies gibt eine Tabelle mit der ID jedes Polygons zurück und ob es sich innerhalb einer bestimmten Entfernung befindet oder nicht. Ist es möglich, eine IF/ELSE
Typanweisung mit SQL zu erstellen? (Ich habe Informationen zur Verwendung der CASE
Bedingung erhalten.) Oder sollte ich versuchen, die von mir erstellte Tabelle mit der Originaltabelle zu verbinden und die Abfrage dann erneut mit ST_Distance auszuführen?
Antworten:
Es gibt einen großen Bereich "Nächster Nachbar" auf der BostonGIS-Seite .
BEARBEITEN:
Wie wäre es mit
In Bezug auf die CASE-Anweisung :
quelle
WHERE ST_DWithin(a.the_geom, b.the_geom, 400)
verhindert, dass Entfernungen400
berechnet oder nur aufgezeichnet werden? Kann eine case-Anweisung auch für numerische Berechnungen verwendet werden? zum beispiel:CASE WHEN ST_DWithin(a.the_geom, b.the_geom, 400) == TRUE THEN ST_DWithin(a.the_geom, b.the_geom)
Hallo
Es gibt einige Dinge, die in Betracht gezogen werden, um Dinge schneller zu machen, und einige Dinge, die in Zukunft möglich sein könnten.
Zunächst haben Sie erwähnt, dass Sie erwägen, einen Puffer zu verwenden, um Polygone in einem bestimmten Mindestbereich zu finden, damit nicht alle Kombinationen berechnet werden.
Wie in einem anderen Link aus Boston besprochen, ist der richtige Weg, dies in PostGIS zu tun, die Verwendung von ST_Dwithin . ST_Dwithin verwendet den Index, um die Nachbarn in einem bestimmten Bereich zu finden.
Es hängt natürlich vom Datensatz ab, ob es ausreicht, nur einen festen Wert für st_DWithin für alle Polygone zu verwenden, oder ob Sie etwas tun müssen, das unterdunkelt und wildintellect diskutiert.
Eine zweite Sache ist, hier PostGIS 1.5+ zu verwenden. Das liegt daran, dass Polygon-zu-Polygon-Berechnungen seit 1.5 viel schneller sind, wenn sich ihre Begrenzungsrahmen nicht schneiden. Mehr dazu lesen Sie hier. .
Das dritte, was zu erwähnen ist, ist die Zukunft.
In PostgreSQL 9.1 wird es etwas geben, das als knn-gist bezeichnet wird. Dies ist ein Index, der nicht nur Ja oder Nein beantworten kann, sondern auch das direkt aus dem Index bestellte Ergebnis zurückgibt. Sie können darüber lesen Sie hier .
Auf der PostGIS-Seite wird jedoch noch viel zu tun sein, bevor der Kern der Sache hier Abhilfe schafft. Dafür gibt es hier ein Ticket .
Grüße
Nicklas
quelle
Die folgenden Seiten zu Nathan Kerrs Master-Arbeiten bieten einen guten Einblick in dieses direkte Thema. Mein Kollege hat hier und hier die Bostongis-Methode ausprobiert , hatte aber einige Probleme, damit sie richtig funktioniert.
Ein anderer Ansatz, der dem Puffer ähnelt, besteht darin, ein expandierendes / kontrahierendes Rechteck zu erstellen. Grundsätzlich gilt: Übergebe 1 mache einen Begrenzungsrahmen (es ist eine Gerade + x Einheiten zu der Bbox deines ursprünglichen Polygons). Für die Daten, die einen Schnittpunkt erhalten haben, führen Sie eine Unterabfrage durch, die diese Übereinstimmungen auf den nächsten überprüft. Für die Daten, die nicht übereinstimmen, erweitern Sie den Begrenzungsrahmen und wiederholen Sie den Vorgang.
Es handelt sich eindeutig um ein rekursives Programmierproblem, das in Python mit Shapely möglicherweise besser als 100% direkt in Postgis erledigt werden kann.
quelle