PostGISを使用して交差に基づいてポリゴンを分離する


36

いくつかが互いに交差するポリゴンのPostGISテーブルがあります。これは私がやろうとしていることです:

  • idで選択された特定のポリゴンについて、交差するすべてのポリゴンを教えてください。基本的に、select the_geom from the_table where ST_Intersects(the_geom, (select the_geom from the_table where source_id = '123'))
  • これらのポリゴンから、交差が新しいポリゴンになるように新しいポリゴンを作成する必要があります。したがって、ポリゴンAがポリゴンBと交差する場合、AマイナスAB、AB、およびBマイナスABの3つの新しいポリゴンが得られます。

何か案は?


1
うーん、私はあなたが得ているものを見ると思うが、シンプルなグラフィックは私(および他の人)があなたが望むものを正確に見るのを助けるために不思議になるかもしれない。
ジェイソン

私の答えにいくつか追加しました。
アダムMatan

回答:


29

興味のあるポリゴンごとに交差するポリゴンのグループを取得したと言ったので、「ポリゴンオーバーレイ」と呼ばれるものを作成することができます。

これは、Adamのソリューションが行っていることとはまったく異なります。違いを確認するには、ABC交差点のこの写真を見てください。

ABC交差点

Adamのソリューションは、「AB!C」と「ABC」の両方の領域をカバーする「AB」ポリゴン、および「AC!B」と「ABC」をカバーする「AC」ポリゴン、および「 「BC」ポリゴンは「BC!A」および「ABC」です。そのため、「AB」、「AC」、および「BC」の出力ポリゴンはすべて「ABC」エリアと重なります。

ポリゴンオーバーレイは重複しないポリゴンを生成するため、AB!Cは1つのポリゴン、ABCは1つのポリゴンになります。

PostGISでポリゴンオーバーレイを作成するのは、実際には非常に簡単です。

基本的に3つのステップがあります。

ステップ1は、ラインワークを抽出します[ 多角形の外部リングを使用していることに注意してください。穴を正しく処理する場合、少し複雑になります]:

SELECT ST_ExteriorRing(polygon_col) AS the_geom FROM my_table) AS lines

ステップ2は、ラインワークを「ノード化」することです(交差点ごとにノードを作成します)。JTSなどの一部のライブラリには、これを行うために使用できる「Noder」クラスがありますが、PostGISでは、ST_Union関数がそれを行います。

SELECT ST_Union(the_geom) AS the_geom FROM (...your lines...) AS noded_lines

ステップ3では、ST_Polygonize関数によって、これらのすべてのラインから発生する可能性のあるすべての重複しないポリゴンを作成します。

SELECT ST_Polygonize(the_geom) AS the_geom FROM (...your noded lines...)

これらの各ステップの出力を一時テーブルに保存することも、すべてを1つのステートメントに結合することもできます。

CREATE TABLE my_poly_overlay AS
SELECT geom FROM ST_Dump((
    SELECT ST_Polygonize(the_geom) AS the_geom FROM (
        SELECT ST_Union(the_geom) AS the_geom FROM (
            SELECT ST_ExteriorRing(polygon_col) AS the_geom FROM my_table) AS lines
        ) AS noded_lines
    )
)

ST_Polygonizeの出力はジオメトリコレクションであり、各行がポリゴンオーバーレイを構成するポリゴンの1つであるテーブルが(通常)より便利なので、ST_Dumpを使用しています。


ST_ExteriorRing穴が落ちることに注意してください。ST_Boundaryは内部リングを保持しますが、内部にポリゴンも作成します。
jpmc26

ポリゴンが多すぎると、外部リングの結合がクラッシュします。残念ながら、この「単純な」ソリューションは、小さなカバレッジに対してのみ機能します。
ピエールラシーン

13

私が正しく理解していれば、あなたは取りたい(Aは左のジオメトリ、Bは右のジオメトリ):

A∪Bの画像http://img838.imageshack.us/img838/3996/intersectab1.png

そして抽出:

A∖AB

A∖ABの画像http://img830.imageshack.us/img830/273/intersectab2.png

AB

ABの画像http://img828.imageshack.us/img828/7413/intersectab3.png

とB∖AB

B∖ABの画像http://img839.imageshack.us/img839/5458/intersectab4.png

つまり、交差するペアごとに3つの異なるジオメトリです。

まず、交差するすべてのジオメトリのビューを作成しましょう。テーブル名がpolygons_tableであると仮定すると、次を使用します。

CREATE OR REPLACE VIEW p_intersections AS    -- Create a view with the 
SELECT t1.the_geom as t1_geom,               -- intersecting geoms. Each pair
       t2.the_geom as t2_geom                -- appears once (t2.id<t2.id)
    FROM polygons_table t1, polygons_table t2  
         WHERE t1.id<t2.id AND t1.the_geom && t2.the_geom 
                           AND intersects t1.the_geom, t2.the_geom;

これで、交差するジオムのペアを格納するビュー(実際には、読み取り専用のテーブル)ができました。各ペアは、t1.id<t2.id条件のために1回だけ表示されます。

次に、3つのクエリすべてでSQLを使用してA∖AB、交差点- 、ABおよびを収集します。B∖ABUNION

--AB:
SELECT ST_intersection(t1.the_geom, t2.the_geom) 
    AS geom 
    FROM p_intersections

UNION 

--AAB:
SELECT ST_Difference(t1.the_geom, t2.the_geom) 
    AS geom 
    FROM p_intersections

UNION

--BAB:
SELECT ST_Difference(t2.the_geom, t1.the_geom) 
    AS geom 
    FROM p_intersections;

ノート:

  1. &&オペレータは、前フィルタとして使用されるintersectsパフォーマンスを向上させるために、オペレータ。
  2. VIEW1つの巨大なクエリの代わりに作成することにしました。これは便宜上のみです。
  3. AB交点ではなくユニオンを意味する場合、AおよびB- UNION適切な場所のクエリでst_intersectionではなくST_Unionを使用します。
  4. 記号は、設定差のUnicodeサインです。データベースを混乱させる場合は、コードから削除してください。
  5. 写真はウィキメディアコモンズの素敵なセット理論のカテゴリの好意による。

メタに私のバグチケット:meta.gis.stackexchange.com/questions/79/...
アダムMatan

いい説明だ!結果はscwソリューションと同じですが、彼の方法はより高速である必要があります(AとBの追加の交差点を計算/保存/しない)
-stachu

ありがとう!テーブルではなくSQL VIEWのみを作成するため、余分な情報は保存しないと思います。
アダムマタン

はい、それは本当ですが、AとBの追加の交差を計算します。これは必要ではありません
-stachu

5
この回答の画像はもう機能しません。
フェスター

8

説明しているのは、ArcGISでのUnion演算子の動作方法ですが、GEOSの世界ではUnionまたはIntersectionとは少し異なります。Shapelyマニュアルには、GEOSでセットがどのように機能するかの例があります。ただし、PostGIS wikiには、あなたのためのトリックを行うラインワークを使用した良い例があります。

あるいは、次の3つのことを計算できます。

  1. ST_Intersection(geom_a、geom_b)
  2. ST_Difference(geom_a、geom_b)
  3. ST_Difference(geom_b、geom_a)

これらは、2番目の箇条書きで述べた3つのポリゴンである必要があります。


2
PostGIS wikiの例は良いです
fmark

ST_Intersectsは、交差するかどうかにかかわらずブール値を返しませんか?ST_Intersectionが機能すると思います。
ジェイソン

ええ、私の部分のタイプミス-今はオリジナルで修正されています、ありがとうジェイソン!
scw

-2

何かのようなもの:

INSERT INTO new_table VALUES((select id、the_geom from old_table where st_intersects(the_geom、(select the_geom from old_table where id = '123')))= true

編集:ポリゴンの実際の交差が必要です。

INSERT INTO new_table values((select id、ST_Intersection(the_geom、(select the_geom from old where id = 123)))

それがうまくいくかどうかを確認してください。

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