Ich habe eine PostGIS-Tabelle polygon_b
mit einigen Polygon-Features. Es gibt auch eine Tabelle polygon_a
mit den gleichen Polygonen wie polygon_b
mit geringfügigen Änderungen. Jetzt möchte ich Linien erstellen, um die Unterschiede zwischen den Polygon-Features zu visualisieren.
Das nehme ich an ST_ExteriorRing
und ST_Difference
werde den Job machen, aber die WHERE-Klausel scheint ziemlich knifflig zu sein.
CREATE VIEW line_difference AS SELECT
row_number() over() AS gid,
g.geom::geometry(LineString, yourSRID) AS geom
FROM
(SELECT
(ST_Dump(COALESCE(ST_Difference(ST_ExteriorRing(polygon_a.geom), ST_ExteriorRing(polygon_b.geom))))).geom AS geom
FROM polygon_a, polygon_b
WHERE
-- ?
) AS g;
Kann mir jemand helfen?
EDIT 1
Wie von 'tilt' gepostet, habe ich versucht, ST_Overlaps(polygon_a.geom, polygon_b.geom) AND NOT ST_Touches(polygon_a.geom, polygon_b.geom)
aber das Ergebnis ist nicht wie erwartet.
CREATE VIEW line_difference AS SELECT
row_number() over() AS gid,
g.geom::geometry(LineString, your_SRID) AS geom
FROM
(SELECT
(ST_Dump(COALESCE(ST_Difference(ST_ExteriorRing(polygon_a.geom), ST_ExteriorRing(polygon_b.geom))))).geom AS geom
FROM polygon_a, polygon_b
WHERE
ST_Overlaps(polygon_a.geom, polygon_b.geom) AND NOT ST_Touches(polygon_a.geom, polygon_b.geom))
AS g;
BEARBEITEN 2
workupload.com/file/J0WBvRBb (Beispieldatensatz)
Ich habe versucht, die Polygone vor der Verwendung von ST_Difference in Mehrfachlinien umzuwandeln, aber die Ergebnisse sind immer noch seltsam.
CREATE VIEW multiline_a AS SELECT
row_number() over() as gid,
ST_Union(ST_ExteriorRIng(polygon_a.geom))::geometry(multilinestring, 4326) AS geom
FROM
polygon_a;
CREATE VIEW multiline_b AS SELECT
row_number() over() as gid,
ST_Union(ST_ExteriorRIng(polygon_b.geom))::geometry(multilinestring, 4326) AS geom
FROM
polygon_b;
CREATE VIEW line_difference AS SELECT
row_number() over() as gid,
g.geom
FROM
(SELECT
(ST_Dump(COALESCE(ST_Difference(multiline_a.geom, multiline_b.geom)))).geom::geometry(linestring, 4326) AS geom
FROM
multiline_a, multiline_b)
As g;
quelle
Antworten:
Hier sind ein paar neue Tricks:
EXCEPT
Um Geometrien aus jeder Tabelle zu entfernen, die identisch sind, können wir uns nur auf Geometrien konzentrieren, die für jede Tabelle (A_only
undB_only
) eindeutig sind .ST_Snap
um genaue Knoten für Overlay-Operatoren zu erhalten.ST_SymDifference
Overlay-Operator, um den symmetrischen Unterschied zwischen den beiden Geometriesätzen zu ermitteln und die Unterschiede anzuzeigen. Update :ST_Difference
zeigt das gleiche Ergebnis für dieses Beispiel. Sie können beide Funktionen ausprobieren, um zu sehen, was sie erhalten.Dies sollte bekommen, was Sie erwarten:
Um diese Antwort ein bisschen mehr auszupacken,
ST_Boundary
erhält der erste Schritt mit die Grenze jedes Polygons und nicht nur das Äußere. Wenn es zum Beispiel Löcher gäbe, würden diese durch die Grenze verfolgt.Mit dieser
EXCEPT
Klausel werden Geometrien aus A, die Teil von B sind, und Zeilen aus B, die Teil von A sind, entfernt. Dadurch wird die Anzahl der Zeilen verringert, die nur Teil von A und nur Teil von B sind. ZB um A_only zu bekommen:Hier sind die 6 Zeilen von A_only und 3 Zeilen von B_only:
Als nächstes
ST_Union(DISTINCT A_only.geom)
wird verwendet, um die Linien in einer einzigen Geometrie zu kombinieren, normalerweise einem MultiLineString.Mit ST_Snap werden Knoten von einer Geometrie zu einer anderen gefangen. Zum Beispiel
ST_Snap(A, B, tol)
wird die A-Geometrie genommen und weitere Knoten aus der B-Geometrie hinzugefügt oder in die B-Geometrie verschoben, wenn sie sich innerhalb destol
Abstands befinden. Es gibt wahrscheinlich mehrere Möglichkeiten, diese Funktionen zu verwenden, aber die Idee ist, Koordinaten von jeder Geometrie zu erhalten, die genau zueinander sind. So sehen die beiden Geometrien nach dem Einrasten aus:Um Unterschiede anzuzeigen, können Sie entweder
ST_SymDifference
oder auswählenST_Difference
. Sie zeigen beide das gleiche Ergebnis für dieses Beispiel.quelle
Ich denke, es ist ein bisschen knifflig, weil die beiden Polygone unterschiedliche Knotensätze haben (grünes Polygon A, rote unterschiedliche Segmente von Polyon B). Der Vergleich der Segmente beider Polygone gibt einen Hinweis darauf, welche Segmente von Polygon B modifiziert werden.
Knotenpolygon A
Knoten des "unterschiedlichen" Segmentpolygons B
Leider zeigt dies nur den Unterschied in der Segmentstruktur, aber ich hoffe, es ist ein Ausgangspunkt und es funktioniert so:
Nach einem Download- und Entpackvorgang habe ich den Datensatz mit PostgrSQL 9.46, PostGIS 2.1 unter Debian Linux Jessie mit den Befehlen importiert.
Unter der Annahme, dass die Segmente von Polygon A nicht in B und umgekehrt sind, versuche ich, den Unterschied zwischen den Segmenten beider Polygonsätze zu bilden, wobei ich die Segmentzugehörigkeit zu den Polygonen in jeder Gruppe (A oder B) vernachlässige. Aus didaktischen Gründen formuliere ich das SQL-Zeug in mehreren Ansichten.
Entsprechend diesem GIS-SE-Beitrag zerlege ich die beiden Polygone in Segmenttabellen
segments_a
undsegments_b
Das Segmenttabellenpolygon A:
Das gleiche Verfahren wurde auf Polygon B angewendet.
Das Segmenttabellenpolygon B
Ich kann eine Differenztabellenansicht namens erstellen
segments_diff_{a,b}
. Die Differenz ergibt sich aus dem Nichtauftreten sortierter Start- oder Endpunkte in der Segmentmenge A und B.Und das Komplementäre:
Fazit: Um ein korrektes Ergebnis für die kleinen Segmente zu erhalten, die Sie mit dem roten Pfeil markiert haben, müssen beide Polygone die gleiche Knotenstruktur aufweisen und ein Schnittschritt auf Knotenebene (Einfügen von Eckpunkten von Polygon A in B) ist erforderlich. Die Überschneidung könnte erfolgen durch:
Aber mit seltsamen Ergebnissen ...
quelle
Im Beispiel bedeutet die Änderung, dass sich geänderte Features aus der neuen Tabelle immer mit Features aus der alten Tabelle überschneiden. Damit wären Sie erledigt
Die Negation bei Berührungen besteht darin, dass sich Features auch überlappen, wenn nur ihre Ränder die gleichen Eckpunkte aufweisen.
quelle