ST_Differenceを使用して重複するフィーチャを削除しますか?


11

ST_Differenceを使用して、PostGis 2.1(およびPostgres SQL 9.3)を使用する別のポリゴンのセット(test.single_geometry_1)でカバーされる領域を含まないポリゴンのセット(processing.trimmedparcelsnew)を作成しようとしています。これが私のクエリです:

CREATE TABLE processing.trimmedparcelsnew AS
SELECT
    orig.id, ST_Difference(orig.geom, cont.geom) AS difference
FROM 
    test.single_geometry_1 cont,
    test.multi_geometry_1 orig;

しかし、結果のポリゴンはトリミングされておらず、代わりに他のレイヤーと交差する場所で分割されているようです。結果をテーブルに入れずにselectを実行するだけで、他に考えられるすべてのものを試しましたが、この関数を機能させることができません。

結果の写真を添付し​​ました

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


コメントの後、WHERE句を追加してみました。交差のないパーセルと、他のパーセルの交差する領域を削除します(レイヤーtest.single_geometryは、パーセルから削除する汚染を表します)。交差を試してみましたが、もちろん実際には非交差が必要なので、分離を試行しています。また、テーブルにorigを追加しようとしましたが、ST_Difference(http://postgis.net/docs/ST_Difference.html)のドキュメントには、必要な正確なジオメトリ(ジオメトリAのその部分を表すジオメトリ)が返されると記載されていますはジオメトリB)と交差しないため、テーブルの元のポリゴンを代わりに使用する理由がわかりません。とにかく、ここに私の変更されたコードがあります:

CREATE TABLE processing.trimmedparcelsnew AS
SELECT
    orig.id, ST_Difference(orig.geom, cont.geom) AS difference, orig.geom AS geom
FROM 
    test.single_geometry_1 cont,
    test.multi_geometry_1 orig
WHERE ST_Disjoint(orig.geom, cont.geom);

dbastonの回答に続いて、私は今試しました:

CREATE TABLE processing.parcels_trimmed AS
SELECT id, COALESCE(ST_Difference(geom, (SELECT ST_Union(b.geom) 
                                         FROM test.single_geometry_1 b
                                         WHERE ST_Intersects(a.geom, b.geom)
                                         AND a.id != b.id)), a.geom)
FROM test.multi_geometry_1 a;

この結果は、test.multi_geometry_1のコピーです。現在は分割は行われていませんが。

以前のバージョンを試しましたが、もう一度test.multi_geometry_1のコピーを取得します。

CREATE TABLE processing.parcels_trimmed_no_coalesce AS
SELECT id, COALESCE(ST_Difference(geom, (SELECT ST_Union(b.geom) 
                                         FROM test.single_geometry_1 b
                                         WHERE ST_Intersects(a.geom, b.geom)
                                         AND a.id != b.id)), a.geom)
FROM test.multi_geometry_1 a;

他に何か間違っているのではないかと思い始めています。次のステートメントは次のとおりです。

DROP TABLE IF EXISTS processing.parcels_trimmed_no_coalesce;

そして、PostgreSQL SQLクエリウィンドウとOpenjumpからクエリを実行しています。

テーブルを表示するために使用するステートメントは次のとおりです。

SELECT * FROM processing.parcels_trimmed_no_coalesce;

簡略化のために、このクエリを次のように減らしました。

SELECT id, COALESCE(ST_Difference(geom, (SELECT ST_Union(b.geom) 
                                         FROM test.geometriestocutagainst b
                                         WHERE ST_Intersects(a.geom, b.geom)
                                         AND a.id != b.id)), a.geom)
FROM test.geometriestocut a;

これでも、望みの結果がtest.geometriestocutagainstに対してトリミングされた元の場合、元のポリゴン(test.geometriestocut)のみになります。


WHERE句を指定しなかったため、結果のテーブルに多項式展開がある可能性があります。trimmedparcelsnewいくつの行がありますか?
ビンス

それらが交差する場所の違いだけが必要な場合は、WHERE ST_Intersects(orig.geom、cont.geom)を追加してみてください。それ以外の場合、交差しない2つのポリゴンの違いは、元のポリゴンです。
ジョンパウエル

トリミングされたパーセルには24行ありますが、交差しない場合でも違いが欲しいので、違いではなくテーブルでorig.geomを使用する必要があることを修正しますか?
2015

各機能-ばらばらのテストでは、多項式展開を生成する必要があります続きを内のすべての機能のために一度表示されるようにorigが重複していない、との違いはなり決して入力ジオメトリ変更しない
ビンス・

わかりやすく説明してくれてありがとう。でも、なぜ元のコードが機能しないのかはまだわかりません。ST_Difference(orig.geom、cont.geom)がbと交差しないaのジオメトリを返す場合、テーブルにbと交差しないaのジオメトリではなく分割されたジオメトリが含まれているのはなぜですか。
マート

回答:


14

自己結合を使用すると、2つのフィーチャのペア間の関係を操作できます。しかし、私はあなたがペアに興味があるとは思わない:各機能について、その機能とデータセット内の他のすべての機能との間の関係を操作したい。これはサブクエリ式で実現できます。

CREATE TABLE parcels_trimmed AS
SELECT id, ST_Difference(geom, (SELECT ST_Union(b.geom) 
                                FROM parcels b
                                WHERE ST_Intersects(a.geom, b.geom)
                                  AND a.id != b.id))
FROM parcels a;

ただし、結果が変に見える場合があります。オーバーラップのないパーセルは完全に削除されます!それはので、だST_Union空のレコードの集合体であることを行っているNULL、とST_Difference(geom, NULL)ありますNULL。これをスムーズにするには、ST_Difference呼び出しを次のようにラップする必要がありますCOALESCE

CREATE TABLE parcels_trimmed AS
SELECT id, COALESCE(ST_Difference(geom, (SELECT ST_Union(b.geom) 
                                         FROM parcels b
                                         WHERE ST_Intersects(a.geom, b.geom)
                                         AND a.id != b.id)), a.geom)
FROM parcels a;

つまり、の結果ST_DifferenceがのNULL場合、結合された式は元のジオメトリに評価されます。

上記のクエリは、重複する領域をドメインから完全に削除します。代わりに勝者を選びたい場合は、代わりa.id < b.idにやその他の基準を使用できますa.id != b.id


応答をありがとう、残念ながら私はこれをうまく機能させるのに苦労していますが、代わりに元のポリゴン(a)で終わります。質問の詳細を編集します。再度、感謝します。
2015

2

私はあなたと同じ問題を抱えていました。あなたがあなたの問題の解決策をすでに見つけたかどうかはわかりませんが、私は上記の受け入れられた答えを変更し、私が望んだものを得ました。

CREATE TABLE parcels_trimmed AS
SELECT id, COALESCE(ST_Difference(geom, (SELECT ST_Collect(b.geom) 
                                         FROM parcels b
                                         WHERE ST_Intersects(a.geom, b.geom)
                                         )), a.geom)
FROM parcels a;

1

PostGISアドオンの ST_DifferenceAgg()を使用しています。2つのテーブルをマージし、ジオメトリ列に一意の識別子とインデックスを設定する必要があります。以下に短い例を示します。

WITH overlappingtable AS (
  SELECT 1 id, ST_GeomFromText('POLYGON((0 1, 3 2, 3 0, 0 1), (1.5 1.333, 2 1.333, 2 0.666, 1.5 0.666, 1.5 1.333))') geom
  UNION ALL
  SELECT 2 id, ST_GeomFromText('POLYGON((1 1, 3.8 2, 4 0, 1 1))')
  UNION ALL
  SELECT 3 id, ST_GeomFromText('POLYGON((2 1, 4.6 2, 5 0, 2 1))')
  UNION ALL
  SELECT 4 id, ST_GeomFromText('POLYGON((3 1, 5.4 2, 6 0, 3 1))')
  UNION ALL
  SELECT 5 id, ST_GeomFromText('POLYGON((3 1, 5.4 2, 6 0, 3 1))')
)
SELECT a.id, ST_DifferenceAgg(a.geom, b.geom) geom
FROM overlappingtable a,
     overlappingtable b
WHERE a.id = b.id OR -- Make sure to pass at least once the polygon with itself
      ((ST_Contains(a.geom, b.geom) OR -- Select all the containing, contained and overlapping polygons
        ST_Contains(b.geom, a.geom) OR
        ST_Overlaps(a.geom, b.geom)) AND
       (ST_Area(a.geom) < ST_Area(b.geom) OR -- Make sure bigger polygons are removed from smaller ones
        (ST_Area(a.geom) = ST_Area(b.geom) AND -- If areas are equal, arbitrarily remove one from the other but in a determined order so it's not done twice.
         a.id < b.id)))
GROUP BY a.id
HAVING ST_Area(ST_DifferenceAgg(a.geom, b.geom)) > 0 AND NOT ST_IsEmpty(ST_DifferenceAgg(a.geom, b.geom));

これにより、重なり合う部分が最大の重なり合うポリゴンとマージされます。オーバーラップする部分を分離したままにする場合は、ST_splitAgg()の例をご覧ください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.