Erstellen Sie einen aufgelösten Puffer aus mehreren Geometrien (Vereinigung durch gemeinsames Attribut und räumlichen Schnittpunkt).


10

Ich muss gelöste Puffer aus Mehrpunkteingabefunktionen erstellen. Im folgenden Beispiel enthält die Eingabetabelle 4 Funktionen. Das Feature #2besteht aus zwei Punktgeometrien. Nach dem Erstellen eines Puffers erhalte ich 4 Polygongeometrien:

Geben Sie hier die Bildbeschreibung ein

Gibt es eine Möglichkeit, das Ergebnis zu gruppieren? Die Puffer der Punkte #1und #2werden aufgelöst und sollten ein einzelnes Multi-Polygon-Feature sein ( a).

Was ich bisher gemacht habe:

-- collect all buffers to a single multi-polygon feature
-- dissolve overlapping polygon geometries
CREATE TABLE public.pg_multibuffer AS SELECT
    row_number() over() AS gid,
    sub_qry.*
FROM (SELECT
    ST_Union(ST_Buffer(geom, 1000, 8))::geometry(MultiPolygon, /*SRID*/) AS geom
FROM
public.multipoints)
AS sub_qry;

BEARBEITEN:

-- create sample geometries

CREATE TABLE public.multipoints (
gid serial NOT NULL,
geom geometry(MultiPoint, 31256),
CONSTRAINT multipoints_pkey PRIMARY KEY (gid)
);

CREATE INDEX sidx_multipoints_geom
ON public.multipoints
USING gist
(geom);

INSERT INTO public.multipoints (gid, geom) VALUES
(1, ST_SetSRID(ST_GeomFromText('MultiPoint(12370 361685)'), 31256)),
(2, ST_SetSRID(ST_GeomFromText('MultiPoint(13520 360880, 19325 364350)'), 31256)),
(3, ST_SetSRID(ST_GeomFromText('MultiPoint(11785 367775)'), 31256)),
(4, ST_SetSRID(ST_GeomFromText('MultiPoint(19525 356305)'), 31256));

Sie verwenden zu viele Unterabfragen. Dadurch können Sie nicht mehr nach dem Attribut gruppieren, für das Sie Cluster erstellen möchten.
Vince

Sie müssen also eine räumliche Vereinigung und dann auch eine Vereinigung basierend auf der Merkmalsnummer durchführen, weshalb Sie aus dem obigen Diagramm 3 Multipolygone erwarten. Ich vermute, dass dies einen zweistufigen Prozess erfordert, wollte aber nur die Frage klarstellen, bevor ich eine Antwort anbiete.
John Powell

Ja, ich möchte die Pufferpolygone vereinen und das Ergebnis basierend auf der Anzahl der Eingabe-Features erfassen.
Eclipsed_by_the_moon

Gibt es hierzu Neuigkeiten? Ich würde gerne wissen, ob dies für Sie funktioniert, soweit ich sehen kann, habe ich die Frage beantwortet.
John Powell

Entschuldigung für die späte Antwort, ich war seit ein paar Tagen nicht mehr online.
eclipsed_by_the_moon

Antworten:


7

Beginnend mit einigen zufälligen Punkten, um diejenigen im Bild des OP zu imitieren, bei denen sich die ersten beiden räumlich schneiden, haben der zweite und der dritte die gleiche Attribut-ID (2), mit einigen anderen Punkten, die sich weder räumlich schneiden noch haben Mit demselben Attribut erzeugt die folgende Abfrage 3 Cluster:

WITH 
  temp (id, geom) AS 
     (VALUES (1, ST_Buffer(ST_Makepoint(0, 0), 2)),
        (2, ST_Buffer(ST_MakePoint(-0.7,0.5), 2)),
        (2, ST_Buffer(ST_MakePoint(10, 10), 2)), 
        (3, ST_Buffer(ST_MakePoint(-2, 12), 2)), 
        (4, ST_Buffer(ST_MakePoint(5, -6), 2))),
 unions(geoms) AS 
      (SELECT ST_Union(geom) FROM temp GROUP BY id),
 clusters(geoms) AS 
      (SELECT ST_CollectionExtract(unnest(ST_ClusterIntersecting(geoms)), 3) 
         FROM unions),
 multis(id, geoms) AS 
      (SELECT row_number() over() as id, geoms FROM clusters)
 SELECT ST_UNION(d.geom) FROM 
      (SELECT id, (ST_DUMP(geoms)).geom FROM multis) d GROUP BY id;

Hier gibt es mehrere Schritte:

  1. Verwenden Sie " ST_UnionGruppieren nach ID", um zuerst nach Attribut zu gruppieren
  2. Verwenden Sie ST_ClusterIntersectingdiese Option, um diejenigen aus derselben Gruppe zu kombinieren, die sich räumlich schneiden
  3. Fügen Sie jedem Cluster eine ID hinzu (Tabelle Multis). Wenn Sie dies direkt im ClusterIntersecting versuchen, erhalten alle Geometrien eine ID von 1
  4. Vereinigen Sie die gedumpten Geometrien aus Schritt 2 und gruppieren Sie sie nach der ID aus Schritt 3 - dies ist der Auflösungsteil . Dies führt dazu, dass die beiden überlappenden Polygone in Ihrem Cluster A miteinander verbunden werden, anstatt sich zu überlappen, wie sie sich am Ende von Schritt 2 befinden.

Ziemlich lang, aber es funktioniert (und ich bin sicher, es gibt einen kürzeren Weg).

Wenn Sie das WKT-Tool in QGIS verwenden (und feststellen, wie schrecklich ich mit den Bearbeitungswerkzeugen bin), werden Cluster wie die folgenden erstellt, in denen Sie sehen können, dass der Cluster, den Sie als gekennzeichnet haben, alle zusammen ist - dh eine Farbe.

Geben Sie hier die Bildbeschreibung ein

Wenn Sie einen ST_AsText um das Finale ST_UNION (d.geom) setzen, können Sie die Ergebnisse direkt sehen.

BEARBEITEN Sie nach weiteren Informationen in den Kommentaren: Wenn Sie mit Punkten beginnen, müssen Sie den Puffer in meine ursprüngliche Lösung integrieren - die ich zu Beginn in den temporären CTE eingefügt habe, um Ihr Diagramm nachzuahmen. Es wäre einfacher, den Puffer im CTE der Gewerkschaften hinzuzufügen, damit Sie alle Geometrien gleichzeitig ausführen können. Am Beispiel eines Pufferabstands von 1000 gibt das Folgende nun erwartungsgemäß 3 Cluster zurück.

WITH temp(id, geom) AS 
  (VALUES 
      (1, ST_SetSRID(ST_GeomFromText('MultiPoint(12370 361685)'), 31256)),   
      (2, ST_SetSRID(ST_GeomFromText('MultiPoint(13520 360880, 19325 364350)'), 31256)),                                                
      (3, ST_SetSRID(ST_GeomFromText('MultiPoint(11785 367775)'), 31256)),
      (4, ST_SetSRID(ST_GeomFromText('MultiPoint(19525 356305)'), 31256))
),                                              
unions(geoms) AS 
  (SELECT st_buffer(ST_Union(geom), 1000) FROM temp GROUP BY id),
clusters(geoms) AS 
  (SELECT ST_CollectionExtract(unnest(ST_ClusterIntersecting(geoms)), 3) 
     FROM unions),
multis(id, geoms) AS 
  (SELECT row_number() over() as id, geoms FROM clusters)
SELECT id, ST_UNION(d.geom) FROM 
  (SELECT id, (ST_DUMP(geoms)).geom FROM multis) d GROUP BY id;

Es tut mir leid, dass ich so lange gebraucht habe, um mich bei Ihnen zu melden. Ich habe einige Probleme, die Puffergeometrien in QGIS zu visualisieren. Ich habe versucht , Kriterien zu ändern ST_SetSRID, ST_Multiund ::geometry(Multipolygon, /*SRID*/), aber im Moment ist es funktioniert nicht.
eclipsed_by_the_moon

OK, wenn Sie Ihren Code und noch besser einige Daten veröffentlichen können, kann ich Ihnen möglicherweise helfen.
John Powell

Ich habe SQL hinzugefügt, um Beispielpunkte zu erstellen.
eclipsed_by_the_moon

Heute etwas gefesselt, werde ich zurückkehren, sobald ich kann. Muss auch den Mehrpunkt in die Abfrage einarbeiten.
John Powell

3

Eine Möglichkeit, dies zu tun, besteht darin, ST_Unionalle Puffer zusammen zu ST_Dumperstellen, um die Komponenten des resultierenden Polygons abzurufen und mit ST_Intersectsden Eingabepunkten zu verbinden, um herauszufinden, wie viele / welche Punkte die einzelnen Cluster bilden.

Dies kann ohne Join erfolgen, indem die Punkte vor dem Aufruf gruppiert werden ST_Buffer. Damit sich zwei Punkte innerhalb desselben gelösten Puffers befinden, müssen sie durch Sprünge zwischen Punkten mit einer Entfernung von weniger als erreichbar sein eps. Dies ist nur ein Minimum-Linkage-Clustering-Problem, das gelöst werden kann mit ST_ClusterDBSCAN:

SELECT
  cluster_id,
  ST_Union(ST_Buffer(geom, 1000)) AS geom,
  count(*)                        AS num_points,
  array_agg(point_id)             AS point_ids
FROM (
  SELECT
    point_id,
    ST_ClusterDBSCAN(geom, eps := 2000, minpoints := 1) OVER() AS cluster_id ,
    geom
  FROM points) sq
 GROUP BY cluster_id;

Beachten Sie, dass dies nicht genau das gleiche Ergebnis wie die Buffer-First-Methode liefert, da PostGIS-Puffer keine perfekten Kreise sind und zwei 1000 m voneinander entfernte Punkte möglicherweise nicht durch zwei 500 m-Puffer verbunden sind.


Scheint, wir hatten eine ähnliche Idee. Ich habe deine nicht getestet, aber ich bin sicher, dass sie funktioniert und sauberer als meine.
John Powell

Es scheint, dass PostGIS 2.2.1 ST_ClusterDBSCAN nicht unterstützt. Ich habe PostGIS 2.3.2 installiert, aber neue Postgis-Erweiterungen in pgAdmin sind immer noch Version 2.2.1.
eclipsed_by_the_moon

0

Entsprechend dieser Antwort möchten Sie ST_DUMP in Ihrer Unterabfrage ausführen.

Etwas wie das:

-- collect all buffers to a single multi-polygon feature
-- dissolve overlapping polygon geometries
CREATE TABLE public.pg_multibuffer AS SELECT
    row_number() over() AS gid,
    sub_qry.*
FROM (SELECT
    ST_Dump(ST_Union(ST_Buffer(geom, 1000, 8))::geometry(MultiPolygon, /*SRID*/)) AS geom
FROM
public.multipoints)
AS sub_qry;

Der Grund dafür ist, dass ST_UNIONein aufgelöstes Multipolygon aller Merkmale zurückgegeben wird und ST_DUMPdieses in die einzelnen Polygonmerkmale (die aufgelöst wurden) aufgeteilt wird.


1
Dies funktioniert nicht wirklich, da alle Attribute, die zum Clustering des gewünschten mehrteiligen Polygons erforderlich wären, verloren gegangen sind.
Vince

Ich habe es versucht ST_Multi((ST_Dump(ST_Union(ST_Buffer(geom, 1000, 8)))).geom)::geometry(MultiPolygon, /*SRID*/) AS geom, aber dies schafft 4 Funktionen anstelle von 3.
Eclipsed_by_the_moon

Oh, richtig, Sie möchten nach der Nummer gruppieren? Sie müssen GROUP_BYvor Ihnen ST_UNION.
Alex Leith
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.