Identifizieren von "langen und schmalen" Polygonen in PostGIS

10

Ich habe eine Reihe von Polygonen, die große Gebiete darstellen, beispielsweise Stadtviertel. Ich möchte die großen überlappenden Bereiche zwischen ihnen identifizieren.

Aber es gibt ein Problem: Manchmal überlappen sich diese Polygone entlang ihres Umfangs (weil sie mit geringer Genauigkeit gezeichnet wurden). Dies erzeugt lange und enge Überlappungen, die mir egal sind.

In anderen Fällen kommt es jedoch zu großen Überlappungen robuster Polygone, dh zu großen Bereichen, in denen das Polygon eines Stadtviertels ein anderes überlappt. Ich möchte nur diese auswählen.

Siehe das Bild unten nur der Überlappungen. Stellen Sie sich vor, ich wollte nur das blaue Polygon in der unteren linken Ecke auswählen.

Überlappung

Ich könnte mir Bereiche ansehen, aber manchmal sind die schmalen so lang, dass sie Bereiche haben, die so groß sind wie das blaue Polygon. Ich habe versucht, ein Verhältnis von Fläche / Umfang zu erreichen, aber das hat auch zu gemischten Ergebnissen geführt.

Ich habe es sogar versucht ST_MinimumClearance, aber manchmal ist an den großen Flächen ein schmaler Teil oder zwei sehr enge Eckpunkte angebracht.

Irgendwelche Ideen für andere Ansätze?


Am Ende funktionierte für mich am besten ein negativer Puffer, wie von @Cyril und @FGreg unten vorgeschlagen.

Ich habe so etwas benutzt wie:

ST_Area(ST_Buffer(geom, -10)) as neg_buffer_area

In meinem Fall waren Einheiten Meter, also 10 m negativer Puffer.

Bei schmalen Polygonen gab dieser Bereich Null zurück (außerdem wäre die Geometrie leer). Dann habe ich diese Spalte verwendet, um die schmalen Polygone herauszufiltern.

bplmp
quelle
4
Sicherlich könnte hierfür das Flächen / Umfang-Verhältnis verwendet werden.
Vince
Es ist schwer zu sagen, wo sich die verschiedenen Polygone im Bild befinden, aber so etwas könnte funktionieren: gis.stackexchange.com/a/265233/64838 ? Berechnen Sie den minimalen gedrehten Begrenzungsrahmen und werfen Sie diejenigen mit geringer Breite oder Höhe weg.
FGreg
Sie können auch versuchen, einen negativen Puffer zu verwenden, wie hier beschrieben: Wie kann ich wirklich dünne Polygone in meiner Formdatei identifizieren?
FGreg

Antworten:

5

Ich würde versuchen, einen negativen Puffer zu erstellen. Wenn er dünne Polygone frisst, ist er gut. Wenn er das Polygon nicht frisst, gehört er mir ... :-)

Führen Sie dieses Skript aus, nachdem Sie zuvor 2/3 der Breite der linearen Polygone festgelegt haben ...

create table name_table as
SELECT ST_Buffer(
(ST_Dump(
(ST_Union(
ST_Buffer(
(geom),-0.0001))))).geom,
0.0001)) as geom from source_table

Betriebssystem: -) ...

Cyril Mikhalchenko
quelle
Am Ende hat Ihr Vorschlag für mich am besten funktioniert. Ich habe so etwas wie beendet ST_Area(ST_Buffer(geom, -10)), wobei -10 in meinem Fall -10 Meter sind. Wenn irgendetwas von diesem Ausdruck 0 zurückgibt, kann ich es herausfiltern.
bplmp
9

Anstelle von Fläche / Umfang ist es besser, die Fläche zu verwenden, die durch das Quadrat des Umfangs (oder dessen Umkehrung) geteilt wird.

Dies wird auch als "Formindex" bezeichnet. Das Quadrat des Umfangs geteilt durch die Fläche hat einen Mindestwert von 4 * Pi () (im Fall einer Scheibe, bei der es sich um die kompakteste 2D-Geometrie handelt), sodass es zur Vereinfachung durch 4 * Pi () normalisiert werden kann Interpretation (normalisierte Werte nahe 1 bedeuten dann, dass Sie sehr kompakte Objekte haben und Quadrate Werte von ungefähr 1,27 haben).

BEARBEITEN: Ein Schwellenwert für den Bereich wäre nützlich, um die sehr kleinen Artefakte zu entfernen, die kompakt sein könnten. Dann würde der Formindex einen besseren Kontrast zeigen. BEARBEITEN: Zusätzlich zu dieser Antwort kann die Verwendung von ST_Snap Ihnen helfen, das Problem zu lösen, bevor es auftritt.

Radouxju
quelle
Vielen Dank! Aber ich bin mir nicht sicher, wie ST_Snap in diesem Fall helfen könnte ... Wenn ich es richtig verstanden habe, schlagen Sie so etwas vor (o.overlap_perimeter^2 / o.overlap_area) / (4 * Pi()) as overlap_ratio? Dies hat für mich schlechtere Ergebnisse als nur Fläche / Umfang.
bplmp
Verwenden Sie jetzt o.overlap_perimeter / (4 * sqrt(o.overlap_area)) as overlap_rationach diesem Artikel, aber noch schlechtere Ergebnisse (obwohl das schwer zu quantifizieren ist, was ich mit schlechter meine) isprs-ann-photogramm-remote-sens-spatial-inf-sci.net/I-7/135/… , Seite 183.
bplmp
2
Vielen Dank dafür, ich hatte noch nie vom "Formindex" gehört. Ich hatte immer gedacht, dass die Verwendung eines minimalen Begrenzungsrechtecks ​​der beste Weg ist, um diese Art von Frage zu beantworten. Ich fand dies, repository.asu.edu/attachments/111230/content/… , was interessant ist.
John Powell
@ JohnPowell interessantes Papier, danke. Ich sehe, dass das, was ich als Formindex kenne, im Papier als Zirkularitätsindex bezeichnet wird. Mein Problem mit minimalen Begrenzungsrechtecken ist, dass es nicht mit sehr konkaven Objekten (z. B. U-förmig)
funktioniert
@bplmp ST_Snap würde Ihnen helfen, die Eckpunkte "fast" benachbarter Polygone so zu fangen, dass sie sich nicht mehr überlappen. Ihre Figuren haben keine Skalierung, aber Ihr Artefakt sieht aus wie Linien. Ich denke, Sie können einen Toleranzwert verwenden, der ausreicht, um Artefakte zu vermeiden, aber die großen Polygone nicht beeinflusst.
Radouxju
5

Eine Möglichkeit wäre, das Verhältnis der Fläche des Polygons zur längsten Linie zu verwenden, die mit ihren Enden gezeichnet werden kann. Lange schmale Polygone identifizieren.

select * from polygons where ST_Length(ST_LongestLine(geom, geom)) < ST_Area(geom) * 4

Dies funktioniert ziemlich gut für Splitterpolygone. Sie können das Verhältnis (mit dem Sie die Fläche multiplizieren) an Ihre Bedürfnisse und Ihre Projektion anpassen.

HeikkiVesanto
quelle
1

Es hört sich so an, als würde dies Ihrem Anwendungsfall entsprechen: Beseitigen Sie ausgewählte Polygone

Kombiniert ausgewählte Polygone der Eingabeebene mit bestimmten benachbarten Polygonen, indem ihre gemeinsame Grenze gelöscht wird. Das benachbarte Polygon kann entweder dasjenige mit der größten oder kleinsten Fläche sein oder dasjenige, das die größte gemeinsame Grenze mit dem zu eliminierenden Polygon teilt.

Eliminieren wird normalerweise verwendet, um Splitterpolygone zu entfernen, dh winzige Polygone, die das Ergebnis von Polygonschnittprozessen sind, bei denen die Grenzen der Eingaben ähnlich, aber nicht identisch sind.

Es hört sich so an, als ob Sie die Option "Größte gemeinsame Grenze" ausprobieren möchten.

FGreg
quelle
Mir ist klar, dass Sie jetzt nach Postgis-Lösungen gefragt haben, nicht nach QGIS-Lösungen. Ich entschuldige mich, ich glaube nicht, dass Postgis eine gleichwertige Funktion hat, aber ich überlasse dies der Nachwelt.
FGreg
0

Dies scheint mir ein perfekter Anwendungsfall für die PostGIS-Topologieerweiterung zu sein . Der Toleranzparameter der Topologie bestimmt, wie weit Scheitelpunkte an anderen vorhandenen Polygonen ausgerichtet werden können, um mit der geringen Genauigkeit der Quelldaten fertig zu werden und diese zu bereinigen.

Kurz gesagt lautet die Strategie:

1. Aktivieren Sie die Topologieerweiterung

CREATE EXTENSION postgis_topology;

2. Erstellen Sie eine neue leere Topologie

SELECT topology.CreateTopology('neighborhoods_topo', 4326, 1e-7);

Der dritte Parameter ist die Toleranz in den Einheiten des CRS; wähle es mit Bedacht aus. Idealerweise möchten Sie ein CRS, bei dem die Einheit Meter ist. Wenn die CRS-Einheit keine Messgeräte ist, wie bei WGS 84 aka 4326, verwenden Sie ST_Transformdiese Option, um Ihre Polygone neu zu projizieren.

3. Fügen Sie der Polygontabelle eine TopoGeometry-Spalte hinzu

SELECT topology.AddTopoGeometryColumn('neighborhoods_topo', 'public', 'neighborhoods', 'topogeom', 'POLYGON');

Dies gibt eine neue zurück layer_id. Speichern Sie es, es wird später benötigt. Es wird eine Ebene sein, 1wenn Sie von vorne beginnen, und bei jedem neuen Anruf erhöht.

4. Fügen Sie der Polyologie alle Polygone hinzu

UPDATE public.neighborhoods
SET topogeom = topology.toTopoGeom(geom, 'neighborhoods_topo', 1, 1e-7);

Dies kann für einen großen Datensatz mehrere Stunden dauern. Seien Sie geduldig. 1ist die zuvor zurückgegebene layer_id.

5. Finden Sie Gesichter, die in mehreren Stadtteilen erscheinen

Finden Sie alle Gesichter aus der Topologie, die in 2 oder mehr Topogeometrien vorhanden sind. Ich werde die Abfrage als Übung verlassen. Am einfachsten ist es wahrscheinlich mit der GetTopoGeomElementsFunktion, dann nach Gesichts-ID zu gruppieren und diejenigen mit einer Anzahl von 2 oder mehr zu betrachten. Alternativ können Sie eine neue Tabelle mit der bereinigten Geometrie aus der Topogeom-Spalte erstellen, sie einfach in die Standardgeometrie umwandeln topogeom::geometryund das wiederholen, was Sie bereits jetzt haben, aber jetzt mit einem sauberen Datensatz, ohne dass sich die Faserbandüberlappungen ergeben.

François
quelle