Ich stehe mit PostGIS vor einer Herausforderung, bei der ich meinen Kopf nicht herumwickeln kann. Ich weiß, dass ich dies mit einer Programmiersprache lösen kann (und das ist mein Backup-Plan), aber ich mag es wirklich, dies in PostGIS zu lösen. Ich habe versucht zu suchen, konnte aber keine Antworten finden, die meinem Problem entsprechen. Dies könnte daran liegen, dass ich bei meinen Suchbegriffen unsicher bin. Entschuldigen Sie dies bitte und weisen Sie mich in die richtige Richtung, da tatsächlich eine Antwort vorliegt.
Mein Problem ist folgendes:
- Ich habe eine Tabelle mit gemischten Polygonen / MultiPolygonen
- Jedes (Multi) Polygon hat ein Attribut, das es ordnet (Priorität)
- Jedes Polygon hat auch einen Wert, den ich gerne wissen würde
- Ich habe einen Suchbereich (Polygon)
- Für meinen Abfragebereich möchte ich den Bereich finden, der von jedem Polygonwert abgedeckt wird
Beispiel:
Angenommen, ich habe die drei Polygone hier in Rot, Grün und Indigo dargestellt:
Und dass das kleinere blaue Rechteck mein Abfragepolygon ist
Darüber hinaus sind die Attribute
geom | rank | value
-------|------|----
red | 3 | 0.1
green | 1 | 0.2
indigo | 2 | 0.2
Ich möchte diese Geometrien so auswählen, dass der höchste Rang (grün) den gesamten Bereich ausfüllt, den er kann (dh den Schnittpunkt zwischen meinem Abfrage-Geom und diesem Geom), und der nächsthöhere (Indigo) den Schnittpunkt zwischen dem Abfrage-Geom ausfüllt und das geom MINUS das bereits abgedeckte) etc.
Ich habe diese Frage gefunden: Verwenden Sie ST_Difference, um überlappende Features zu entfernen? aber es scheint nicht zu tun, was ich will.
Ich kann selbst herausfinden, wie man Bereiche und dergleichen berechnet, daher ist eine Abfrage, die mir die drei Geometrien gibt, wie im zweiten Bild dargestellt, in Ordnung!
Zusätzliche Informationen: - Dies ist keine große Tabelle (~ 2000 Zeilen) - Es kann keine oder mehrere Überlappungen geben (nicht nur drei) - Es gibt möglicherweise keine Polygone in meinem Abfragebereich (oder nur in Teilen davon) - i ' Ich laufe Postgis 2.3 auf Postgres 9.6.6
Meine Fallback-Lösung besteht darin, eine Abfrage wie folgt durchzuführen:
SELECT
ST_Intersection(geom, querygeom) as intersection, rank, value
FROM mytable
WHERE ST_Intersects(geom, querygeom)
ORDER by rank asc
Und dann iterativ Teile der Geometrien im Code "abhacken". Aber wie gesagt, ich würde das wirklich gerne in PostGIS machen
WITH RECURSIVE ...
Antworten:
Ich denke das funktioniert.
Es handelt sich um eine Fensterfunktion, die den Unterschied zwischen dem Schnittpunkt jeder Geometrie mit dem Abfragefeld und der Vereinigung der vorhergehenden Geometrien ermittelt.
Die Koaleszenz wird benötigt, da die Vereinigung der vorhergehenden Geometrien für die erste Geometrie null ist, was anstelle des gewünschten Ergebnisses ein Nullergebnis ergibt.
Ich bin mir allerdings nicht sicher, wie es funktioniert. Da jedoch sowohl ST_Union als auch ST_Intersection als unveränderlich markiert sind, ist dies möglicherweise nicht so schlimm.
quelle
Ein etwas anderer Ansatz. Es gibt eine Einschränkung, bei der ich nicht weiß, wie die Leistung skaliert werden soll, aber bei einer indizierten Tabelle sollte dies in Ordnung sein. Es funktioniert ungefähr genauso wie Nicklas 'Abfrage (ein bisschen langsamer?), Aber die Messung an einer so kleinen Stichprobe ist schwierig.
Es sieht viel hässlicher aus als die Abfrage von Nicklas, vermeidet jedoch eine Rekursion in der Abfrage.
quelle
Da ich darüber
WITH RECURSIVE
geredet habe, werde ich damit eine schnelle und schmutzige Antwort hinzufügen.Dies ist ungefähr so gut wie die Lösung von @ NicklasAvén für drei Polygone, die beim Hochskalieren nicht getestet werden konnte.
Nach dem Stand beider Lösungen hat diese einen kleinen Vorteil gegenüber der anderen: Wenn zum Beispiel das Polygon mit Rang = 2 in dem von Rang = 1 enthalten ist , werden die
...WHERE GeometryType = 'POLYGON'
Filter herausgefiltert, während es sonst ein gibtGEOMETRYCOLLECTION EMPTY
(ich habe die Geometrie geändert des jeweiligen Polygons in meiner Lösung entsprechend, um ein Beispiel zu geben; dies gilt auch für andere Fälle, in denen kein Schnittpunkt mit der Differenz gefunden wird). Dies ist jedoch leicht in den anderen Lösungen enthalten und möglicherweise nicht einmal von Belang.quelle