到達可能な領域にポリゴンを構築する


10

私は現在、等時性と基礎となるアルゴリズムの分野で働いています。現在問題となっているのは、等時線自体の場合の計算ではなく、結果の視覚化です。
私の等時線アルゴリズムの結果は、ポイントとエッジです。実際、私には有効なソリューションがありますが、3873エッジと1529ノードの場合、時間がかかるようです(2015 Core i7 CPUとかなり高速なSSDを含むLenovo T440sラップトップでは約2.0秒)。秒の代わりに、msec :-)のようなものがもっと欲しいです。

たぶん誰かが、到達可能な領域を視覚化するポリゴンを構築するのに必要な計算時間を短縮するのを手伝ってくれるでしょう。

しかし、待ってください...まず最初に!
これは、私の等時線の計算結果であるエッジの視覚化です。 等時線計算結果(折れ線のスケルトン存在) これらのエッジはPostGISデータベーステーブルに格納され、単純な線ストリングです。

ユーザーに見せたいのは次のようなもの ここに画像の説明を入力してください です。画像の最南端と最東端にある切断された領域に注意してください。これらは個別の領域として描画する必要があります(したがって、ここではマージできません:-))

現在、私はこのクエリを使用しています:

SELECT ST_AsGeoJson(St_Transform(ST_Multi(ST_Collect(polygons)), 4326)) AS coverage FROM (
    SELECT ST_MakePolygon(ST_ExteriorRing(ST_GeometryN(segments, generate_series(1, ST_NumGeometries(segments))))) AS polygons FROM (
        SELECT ST_Union(ST_Buffer("GEOMETRY", 20, 'quad_segs=2')) AS segments FROM my_edges AS a
    ) AS b
) AS c

私はすでにいくつかの実験を行っており、多くのドキュメントも読みましたが、より良い解決策を見つけることができません。
私の目には、大きな問題はST_Unionの使用です(ドキュメントで述べられているように、この関数は遅くなる可能性があります)。非常に興味深いのは、それをST_Collectで置き換えると、ST_Bufferの計算が遅くなるように見えるため、次のクエリのオールインオールがさらに長くかかりますが、エッジ間の領域は埋められません(ラインの周りにバッファーが作成されるだけです) ):

SELECT ST_AsGeoJson(St_Transform(ST_Multi(ST_Collect(polygons)), 4326)) AS coverage FROM (
    SELECT ST_Buffer(ST_Collect(ST_LineMerge("GEOMETRY")), 20, 'quad_segs=2') AS polygons FROM my_edges AS a
) AS b

私のシステムでは、これに約3.8秒かかります(2倍近い時間です)。この小さなベンチマークからの最初の結論は、ST_BufferがMultiLineStringに関して予想外に遅くなるということです(各行のバッファーを作成してバッファーをマージするときよりもさらに遅くなります-私の目には奇妙です)。

また、(pgRoutingからの実装を使用して)アルファ形状を使用しようとしましたが、設定するアルファ値がないため(そして、実際には、どの値にそのような値を設定するのかは実際にはありません)、1つの優れたポリゴン(だから私は非常に南と東の地域を別々の地域として失ってしまいます。
また、ST_Polygonize(最初に頭に浮かんだこと)は使用可能な結果を​​生成しませんでしたが、おそらくここで何かを見落としました...

PostGISに表示されるエリアを作成するより良い方法はありますか?多分Javaコード(jts)またはクライアント側のjavascriptコード(jsts)を使用することによって?実際、結果に表示された領域が分離されたままであり、計算が(はるかに)高速になる限り、詳細を失うことで我慢できます。


ST_Exteriorring(ST_Dump(ST_Union(ST_Buffer(geom、....))))。geomを使用することはできませんか。バッファリングされたものはいずれにしてもポリゴンであり、ST_Unionは交差するすべてのジオメトリを接続するため、MakePolygonやGeometryNは必要ありません。バッファ後のST_Unionから時々発生するラインストリングをテストする必要があるかもしれませんが、ST_GeometryType(geom)を使用すると簡単です。Javaまたはjstsを使用することに関しては、可能ですが、 Postgis(GEOS)関数の大部分は、そもそもJTSのC / C ++ポートです
John Powell

そうです、これは機能しますが、実際には速くはありません(GeometryNを使用すると2秒かかりますが、3.1秒ほどかかります)。これが私が使用したものです:SELECT ST_AsGeoJson(ST_Transform(ST_Exteriorring((ST_Dump(ST_Union(ST_Buffer( "GEOMETRY"、20))))。geom)、4326))FROM my_edges;
Nikolaus Krismer、2015

@john-barça:ああ..あなたのアプローチを試すときに、ST_Bufferのquad_segs = 2の部分を曇らせます...その変更で、クエリは偶数です(両方とも約2秒)。しかし、これはまだ非常に遅いです(私の目では)、それを試す別の方法はありますか?
Nikolaus Krismer、2015

興味深い問題...テストデータを共有しますか?
dbaston

それが役に立ったら、私はいくつかのデータを共有して満足しています。ここで私がすることはすべてオープンソースなので、これは大きな問題ではありません。最初に注意すること:テスト用のWebアプリケーションはdbis-isochrone.uibk.ac.at:8080/testingにあります。私が取り組んでいることに関する詳細情報は、dbis-isochrone.uibk.ac.atにあります。ウェブサイトの「リンク」セクションには、さらにいくつかの参照(いくつかのテストデータを含む)があります
Nikolaus Krismer

回答:


5

GeoJSONシリアライゼーションを別にして、以下は私のラップトップで約6.3秒かかります:

SELECT
  ST_MakePolygon(
    ST_ExteriorRing(
      (ST_Dump(
        ST_Union(
          ST_Buffer(geom, 20, 2)))).geom))
FROM bz_edges

OpenJUMPのデータを見ると、出力の望ましい詳細レベルと比較して、ストリートセグメントのかなりの詳細に気づきました。これらのラインをその場で簡略化しても、PostGISで大幅な高速化が実現できるようです。

SELECT
  ST_MakePolygon(
    ST_ExteriorRing(
      (ST_Dump(
        ST_Union(
          ST_Buffer(ST_Simplify(geom, 10), 20, 2)))).geom))
FROM bz_edges

2.3秒に短縮されます。その場で計算するのではなく、別の列に一般化されたジオメトリを格納することで、もっと上手くできるかもしれないと思ったのですが、実際には追加のメリットはありませんでした。

自分でどれだけの量のコードを書こうと思っているかによって、複数のコアを利用できるので、Javaの方がほぼ間違いなくより良い結果が得られます。(それだけの価値があるため、JTSは上記の操作を2.8秒で実行します)。1つのアプローチはCascadedPolygonUnion、いくつかのユニオン操作を並行して実行するように拡張することです。(更新-これはParallelCascadedPolygonUnionです

サンプルデータで、エッジが開始ノードと終了ノードへの参照で保存されていることに気付きました。つまり、事前に作成されたグラフがあります。一般的なジオメトリ操作を使用する代わりにグラフから作業する場合、これらのポリゴンより迅速に生成できると思います。たとえば、次のようにできると思います。

  1. グラフの関連コンポーネントを特定する
  2. 接続されている各コンポーネントについて、最小のX座標を持つノードを見つけます(コンポーネントの外側にあることが保証されています)
  3. コンポーネントの端を歩く。可能な場合は常に左(または右)に曲がる。これにより、各コンポーネントの外部リングが得られます。
  4. 外部リングをポリゴン化し、適切にバッファリングします。

おかげで...簡素化は素晴らしい、さらには「単純な」改善です。私のラップトップで必要な時間は1.5秒に短縮されました。それは私がなりたい場所ではありませんが、少し良いです。
Nikolaus Krismer、2015

提案された解決策について(ポイント1〜4)。サウンドも非常にシンプルで、試してみる価値があります。私は似たようなことを考えましたが、point1で立ち往生しています(とても早い:-))。接続されたコンポーネントを特定するにはどうすればよいでしょうか(私が考えることができるのは、非常に遅い再帰クエリです)。
Nikolaus Krismer、2015

@NikolausKrismer私はJGraphTルームの両方をこのようなタスクに使用します。代わりに独自のグラフメソッドを記述する場合(最高のパフォーマンスを得るために悪い考えではありません)、深さ優先検索でコンポーネントが見つかります。(これらは次のPostGIS 2.2で見つけることができますST_ClusterIntersectingが、とにかくデータベースの外であらゆる種類のグラフ処理を実行したいので、これはおそらく役に立たないでしょう)。
dbaston 2015

これらはいくつかの素晴らしいヒントです。私はJGraphTを見ましたが、これは間違いなく私の問題の解決に役立つでしょう。ただし、Postgis 2.2とST_ClusterIntersecting関数も確認しました。上記のケースで異なるクラスターを特定するには、約200〜250ミリ秒かかります。それは私には大丈夫です(JGraphTは確かにより良くできます)。次に、exteriorRingの作成に対処する必要があります(ST_MakePolygonは私のリンクはシェルではないと言うため、ST_ExteriorRingは失敗します)
Nikolaus Krismer

(a)外部リングだけでなく、そのリングから外側に伸びるすべてのセグメントも必要であり、(b)線が実際には一部の交差点で交差していないように見えます。グラフウォークの結果からジオメトリを構築しようとする場合は、(b)を修正する必要があります。
dbaston 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.