マルチジオメトリからディゾルブバッファーを作成(共有属性と空間的交差による結合)


10

マルチポイント入力機能から溶解バッファーを作成する必要があります。以下の例では、入力テーブルに4つのフィーチャが含まれています。フィーチャ#2は2つのポイントジオメトリで構成されています。バッファを作成した後、4つのポリゴンジオメトリを取得します。

ここに画像の説明を入力してください

結果をグループ化する方法はありますか?ポイント#1とのバッファ#2はディゾルブされ、単一のマルチポリゴンフィーチャである必要があります(a)。

これまでに行ったこと:

-- 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;

編集:

-- 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));

サブクエリを使いすぎています。これにより、クラスター化する属性でGROUP BYを実行できなくなります。
Vince

したがって、空間ユニオンを実行してから、フィーチャ番号に基づいてユニオンを実行する必要があります。これが、上の図から3つのマルチポリゴンを期待する理由です。これには2段階のプロセスが必要だと思いますが、回答を提供する前に、質問を明確にしたいと思っていました。
John Powell

はい、バッファポリゴンを結合し、入力フィーチャの数に基づいて結果を収集します。
eclipsed_by_the_moon 2017年

これに関する更新はありますか?これがあなたのために働くかどうか知りたいのですが、私が見る限り、私は質問に答えました。
John Powell

返信が遅くなって申し訳ありません。数日間オンラインになりませんでした。
eclipsed_by_the_moon 2017

回答:


7

最初の2つが空間的に交差するOPの画像のそれらを模倣するためのいくつかのランダムな点から始めて、2番目と3番目は同じ属性ID(2)を持ち、空間的に交差もせず、他にもいくつかの点があります。同じ属性で、次のクエリは3つのクラスターを生成します。

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;

ここにはいくつかのステップがあります:

  1. 使用ST_Union属性によって最初のグループに、idでグループ化し、
  2. ST_ClusterIntersecting空間的に交差する同じグループからのそれらを組み合わせるために使用
  3. 各クラスター(テーブルマルチ)にIDを追加します。これをClusterIntersectingで直接実行しようとすると、すべてのジオメトリのIDが1になります。
  4. 手順2のダンプされたジオメトリを統合し、手順3のIDでグループ化します。これがディゾルブパーツです。これにより、クラスターAの2つの重なり合うポリゴンは、手順2の最後にあるように、重なり合うのではなく、結合されます。

かなり長いですが、うまくいきます(そして、もっと短い方法があると私は確信しています)。

QGISでWKTツールを使用すると(そして編集ツールで私がどれほどひどいのかを発見すると)、次のようなクラスターが生成されます。

ここに画像の説明を入力してください

ST_AsTextを決勝ラウンドのST_UNION(d.geom)に配置すると、結果を直接見ることができます。

コメントでより多くの情報を編集してください:ポイントから始めるときに、バッファーを元のソリューションに組み込む必要があります-ダイアグラムを模倣するために最初に一時CTEに入れました。ユニオンCTEにバッファを追加する方が簡単なので、一度にすべてのジオメトリを実行できます。したがって、例としてバッファー距離1000を使用すると、期待どおりに次のように3つのクラスターが返されます。

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;

ご返信に時間がかかりすぎて申し訳ありません。QGISでバッファジオメトリを視覚化するのに問題があります。私が使用してクエリを変更しようとしたST_SetSRIDST_Multiそして::geometry(Multipolygon, /*SRID*/)、現時点ではそれが働いていません。
eclipsed_by_the_moon 2017

OK、あなたのコードを投稿できれば、さらに良いデータがあれば、私がお手伝いできるかもしれません。
John Powell

サンプルポイントを作成するためにSQLをいくつか追加しました。
eclipsed_by_the_moon 2017

今日は少し拘束されています。できるだけ早く元に戻します。クエリにもマルチポイントを使用する必要があります。
John Powell

3

これを行う1つの方法は、ST_Unionすべてのバッファーを一緒にしST_Dumpて、結果のポリゴンのコンポーネントを取得ST_Intersectsし、入力ポイントに結合して、各クラスターを構成するポイントの数/ポイントを見つけることです。

これは、を呼び出す前にポイントをグループ化することで、結合を必要とせずに実行できますST_Buffer。2つのポイントを同じディゾルブバッファー内に配置するには、それらのポイントが未満の距離のポイント間のホップで到達可能である必要がありますeps。これは、最小限のリンケージクラスタリングの問題であり、次を使用して解決できます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;

PostGISバッファーは完全な円ではなく、1000m離れた2点が2つの500mバッファーで接続されていない可能性があるため、これはbuffer-firstメソッドとまったく同じ結果を生成しないことに注意してください。


似たようなアイデアがあったようです。私はあなたのものをテストしていませんが、それがうまくいくと確信しています。
John Powell

PostGIS 2.2.1はST_ClusterDBSCANをサポートしていないようです。PostGIS 2.3.2をインストールしましたが、pgAdminの新しいpostgis拡張機能はまだバージョン2.2.1です。
eclipsed_by_the_moon 2017

0

この回答によると、サブクエリ内でST_DUMPを実行する必要があります。

このようなもの:

-- 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;

その理由はST_UNION、すべてのフィーチャのST_DUMP分解されたマルチポリゴンを返し、これを個々のポリゴンフィーチャ(分解された)に分割するためです。


1
これは実際には機能しません。目的のマルチパートポリゴンをクラスター化するために必要な属性が失われているためです。
Vince

私は試しましたがST_Multi((ST_Dump(ST_Union(ST_Buffer(geom, 1000, 8)))).geom)::geometry(MultiPolygon, /*SRID*/) AS geom、これは3ではなく4つの機能を作成します
eclipsed_by_the_moon

ああ、そうですか、番号でグループ化したいですか?あなたはあなたのGROUP_BY前にする必要がありますST_UNION
Alex Leith 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.