Berechnung eines nächsten Nachbarn mit PostGIS optimieren

13

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

Bildbeschreibung hier eingeben

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/ELSETypanweisung mit SQL zu erstellen? (Ich habe Informationen zur Verwendung der CASEBedingung 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?

djq
quelle
Werfen Sie einen Blick auf das zweite Beispiel im Boston GIS-Link in meiner Antwort. Sie sollten st_dwithin im where-Teil der Abfrage verwenden.
Nicklas Avén

Antworten:

7

Es gibt einen großen Bereich "Nächster Nachbar" auf der BostonGIS-Seite .


BEARBEITEN:

Wie wäre es mit

CREATE TABLE mytable_withinRange AS SELECT 
 a.hgt AS a_hgt,
 b.hgt AS b_hgt
FROM 
 public."lon_TestArea" AS a, public."lon_TestArea" AS b
WHERE 
 ST_DWithin(a.the_geom, b.the_geom, 400)

In Bezug auf die CASE-Anweisung :

SELECT a,
   CASE WHEN a=1 THEN 'one'
        WHEN a=2 THEN 'two'
        ELSE 'other'
   END
FROM test;
Underdunkel
quelle
Wissen Sie, ob die Linie WHERE ST_DWithin(a.the_geom, b.the_geom, 400)verhindert, dass Entfernungen 400berechnet 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)
djq
1
@celenius Wenn die Entfernung mehr als 400 m beträgt, wird nichts im ausgewählten Teil berechnet. Ich verstehe nicht, warum Sie Fall in die Mischung setzen wollen.
Nicklas Avén
@Nicklas ok - ich verstehe. Ich dachte, es hätte bedeuten können, dass nur Entfernungen von weniger als 400 gespeichert wurden; das macht es viel einfacher als ich. Vielen Dank!
DJQ
3

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

Nicklas Avén
quelle
Danke für die Vorschläge Nicklas; da ich es schwierig fand, pgAdmin / PostGIS zum Laufen zu bringen, denke ich, dass ich es im Moment vermeiden werde, 1.5 zu verwenden. Es scheint, als wäre ST_Dwithin () eine Möglichkeit, dies zu lösen.
8.
2
Die Installation von 1.5 hat keinen Einfluss auf die Beziehung zwischen postgresql und pgadmin. Sie können mehr als eine Version von Postgis auf dem Datenbankserver haben und dann eine von ihnen in die Datenbank laden. Sie können also eine 1.4- und eine 1.5-Datenbank auf demselben Datenbankserver haben.
Nicklas Avén
1

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.

Wildintellekt
quelle