源流ポリゴンを見つける


8

これは、この質問のフォローアップ質問です。

河川網(複数線)といくつかの排水ポリゴンがあります(下の画像を参照)。私の目標は、源流ポリゴン(緑)のみを選択することです。

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

ジョンのソリューション私は簡単に川の開始点(星)を抽出することができます。ただし、ポリゴンに始点がある状況(赤いポリゴン)がある場合がありますが、ポリゴンは河川を通って飛んでいるため、源流ポリゴンではありません。源流ポリゴンだけが必要です。

ポリゴンと川の交差点の数を数えてそれらを選択しようとしました(理由:源流ポリゴンには川との交差点が1つだけである必要があります)

SELECT 
    polyg.*
FROM 
    polyg, start_points, stream
WHERE 
    st_contains(polyg.geom, start_points.geom)
    AND ST_Npoints(ST_Intersection(poly.geom, stream.geom)) = 1

ここで、poylgpoylgonsであり、johnsのstart_pointsは答え、streamは私の河川ネットワークです。

しかし、これは永遠にかかり、私はそれを実行しませんでした:

"Nested Loop  (cost=0.00..20547115.26 rows=641247 width=3075)"
"  Join Filter: _st_contains(ezg.geom, start_points.geom)"
"  ->  Nested Loop  (cost=0.00..20264906.12 rows=327276 width=3075)"
"        Join Filter: (st_npoints(st_intersection(ezg.geom, rivers.geom)) = 1)"
"        ->  Seq Scan on ezg_2500km2_31467 ezg  (cost=0.00..2161.52 rows=1648 width=3075)"
"              Filter: ((st_area(geom) / 1000000::double precision) < 100::double precision)"
"        ->  Materialize  (cost=0.00..6364.77 rows=39718 width=318)"
"              ->  Seq Scan on stream_typ rivers  (cost=0.00..4498.18 rows=39718 width=318)"
"  ->  Index Scan using idx_river_starts on river_starts start_points  (cost=0.00..0.60 rows=1 width=32)"
"        Index Cond: (ezg.geom && geom)"

だから私の質問は:どうやって源流ポリゴンを効率的にクエリできるのですか?

アップデート: 私は私にいくつかのサンプルデータを追加しましたDropboxの。データはドイツ南西部のものです。これは2つのシェイプファイルで、1つはストリーム、もう1つはポリゴンです。


したがって、明確にするために、開始点自体ではなく開始点のみを含むポリゴンが必要です。そして、出発点はあなたの以前の質問(私が答えた、そして私が知る限り)のように正しく定義されていますか?
John Powell

Jupp、開始点を含み、かつ川を通過せず、川の始まりにすぎないポリゴンのみ。上の赤​​いポリゴンには始点が含まれていますが、川が流れるため、源流ポリゴンではありません/ポリゴン内で始まらない...
EDi

そのため、polygons(前の質問からの)川の源であるポイントのみを含むセットと、2つの川が交わる場所を除外する必要があります。すみません、すべての質問について、確認したいだけです。
John Powell、

いいえ、たとえば下の緑のポリゴンでは、2つの川が合流しています。polygons川が通り過ぎる(川がポリゴンに出入りする)ものを除外し、開始点を維持します(川はこのポリゴンだけを離れます)。
EDi、2015年

1
PostGISがわからないので、直接コードを作成することはできませんが、ArcGISでは次の線に沿って移動します。(1)線とポリゴンの間で交差してポイントファイルにします。(2)同一のポイントを(空間的に)削除します。(3)すべてのポイントの値が1の数値フィールドをポイントパラメータに追加します。(4)ポリゴンをポイントに空間的に結合し、数値フィールドの合計を使用して排水のタイプを示します。1の合計は、それが岬であることを意味します。1より大きい場合、入口または出口が複数あることを意味します。
Mikkel Lydholm Rasmussen、2015

回答:


4

一般的な概要(これまでに部分的にテストされた)は次のとおりです。

  1. この回答のように、ストリームソースを表すポイントを見つけます

  2. ポリゴンテーブルと交差して、ポリゴンごとのソース頂点の数を取得します。

  3. 各ポイントの数を取得するには、ST_DumpPointsをgroup by geometryと組み合わせて使用します。ある時点でいくつの川が合流するかを数えるという考えです。

そのようなクエリの例:

SELECT count(geom), ST_AsText(geom) as wkt
FROM 
   (SELECT (ST_DumpPoints(foo.geom)).geom 
   FROM 
     (SELECT 
        ST_Collect(ST_MakeLine(ST_MakePoint(0,0), ST_MakePoint(10,10)),
                   ST_MakeLine(ST_MakePoint(0,0), ST_MakePoint(20,20))
        ) as geom
     ) foo 
 ) bar 
 GROUP BY geom; 

これは次を返します:

count  |  wkt      
-------+--------------
 2     | POINT(0 0)
 1     | POINT(10 10)
 1     | POINT(20 20)
  1. 3ポリゴンテーブルに対しての交差を実行して、ポリゴンごとの川のジャンクションの数(頂点の合計)を取得します。

  2. ポリゴンに参加する24は、接合部の点の数(頂点の和)は、この条件が成立すれば、ステップ1及び2からポリゴンによってソースを加算した河川源の合計よりも大きいものを拒絶します、ジャンクションで合流する川の少なくとも1つが、問題のポリゴンの外側から始まったことを意味します。

いくつかのテーブルがポイントを含むステップから作成された(およびインデックス付けされた)場合を除いて、これらはすべてCTEの大まかなシーケンスで組み合わせることができます。

これのランタイムが完全なデータセットでどのようになるかはわかりませんが、サブセットでこれの一部のみをテストしたのですが、ポリゴンテーブルに空間インデックスがあると、何らかの支援があります-明らかにできませんST_DumpPointsから出現するポイントにインデックスを適用するため、その時点でメモリ内にあるはずですが、そこでフルスキャンが必要になります。

これは完全な回答として投稿されているのではなく、進行中の作業、およびロジックの欠陥を見つけるチャンスとして投稿されています。実用的なクエリはすぐに来る。

編集1

これは私が思いついたクエリで、データの小さなサブセットで機能するように見えますが、完全なデータセットで数時間実行されます。

CREATE TABLE good_polys as  
   WITH 
     rivers as 
       (SELECT (ST_DUMP(ST_LineMerge(geom))).geom as geom FROM streams),
     start_points as
       (SELECT ST_StartPoint(geom) as geom FROM rivers),
     end_points as 
        (SELECT ST_EndPoint(geom) as geom FROM rivers),
     junctions as 
        (SELECT (ST_DumpPoints(geom)).geom 
        FROM (SELECT geom FROM streams) s),
     source_polygons as 
        (SELECT 
            count(rivers.geom) as source_count, 
            polygons.geom, 
            polygons.gid 
         FROM rivers, polygons
         WHERE st_intersects(polygons.geom, rivers.geom) 
         GROUP BY polygons.geom, polygons.gid),
     junction_polygons as 
        (SELECT 
            count(junctions.geom) as junction_count, 
            polygons.geom, 
            polygons.gid 
         FROM junctions, polygons
         WHERE st_intersects(polygons.geom, junctions.geom) 
         GROUP BY polygons.geom, polygons.gid)
    SELECT 
       jp.gid 
    FROM 
       junction_polygons jp, source_polygons sp 
    WHERE ST_Equals(jp.geom, sp.geom) 
    AND junction_count <= source_count;

編集2。これは小さなサブセットで正しい答えを生成するように見えますが、おそらく最後のクエリがn ^ 2比較を実行していて、空間インデックスを使用していないため、データセット全体の実行時間は恐ろしいものです。考えられる解決策は、クエリを分解し、最初のポイントとポリゴンクエリのポイントからテーブルを作成することです。これにより、最後のステップの前に空間的にインデックスを付けることができます。


現在、クエリはデスクトップで実行されています。あなたのデータの小さなサンプルからは妥当に見えましたが、どれくらい時間がかかるか、それが正しいかどうかはわかりません。どれだけの数のポリゴンが基準を満たしているかわかりますか?
John Powell、

サーバーでクエリを実行します。ポリゴンのごく一部のみが選択基準を満たすと思います...
EDi

それが私がサブセットで見つけたものです。終了したらクエリを投稿します
John Powell

明日は簡素化。
John Powell

今日は忙しいです。答えは、最初にソースクエリと川のジャンクションクエリを実行し、ポリゴンテーブルと交差してポリゴンあたりの数を取得し、これらをテーブルとして保存してから、インデックスを作成することです。次に、ジオメトリが等しい最後のステップを実行し、2つのテーブルのポイント数を比較します。これにより、現在のようにn²比較を行うのではなく、インデックスを使用することを期待しています。後で投稿します。
ジョンパウエル

0

疑似コードでは、これはうまくいくはずです:

  • ポリゴンからすべて選択
  • (FULL OUTER?)ポリゴン上のポイントと結合してポイントが交差する
  • (FULL OUTER?)ポリゴンとラインが交差するラインを結合する
  • line.riveridがpoint.riveridと等しくない
  • polygonidでグループ化
  • カウント(pointid)> 0

クエリの作成方法がよくわからないので、データベースをテストしないとテストできません。かなりクレイジーなクエリだと思います。しかし、それはうまくいくはずです!

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