PostGISを使用して道路の交差点を特定する


17

道路が交差する場所を特定し、交差点を形成する道路の数をリストして、この交差点でポイントを作成しようとしています。

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

これを達成するためにST_NumPointsを使用する方法があるかどうか疑問に思っていましたが、私は何をすべきかを理解できません。次のコードを使用して、線が交差するポイントのテーブルを作成しました。

CREATE TABLE test_points as
SELECT      
    ST_Intersection(a.geom, b.geom),
    a.gid
FROM
    roads as a,
    roads as b
WHERE
    ST_Touches(a.geom, b.geom);

道路のサンプルでこれを実行すると、次の点のグリッドが得られます(道路は説明のために示されています)。

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

ポイントの1つを調べると、多くのポイントが積み重なっていることがわかります。

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

ここのGIDは道路IDですが、なぜ多くのポイントがあるのか​​理解できません。中央の道路の交差点で4つのポイントがカウントされることは理解できますが、ここには12ポイントがリストされています。PostGISでこの計算を実行するより良い方法はありますか?

回答:


21

グループ化する場合、一意のポイントのみを取得する必要があります。

CREATE TABLE test_points as
SELECT      
    ST_Intersection(a.geom, b.geom),
    Count(Distinct a.gid)
FROM
    roads as a,
    roads as b
WHERE
    ST_Touches(a.geom, b.geom)
    AND a.gid != b.gid
GROUP BY
    ST_Intersection(a.geom, b.geom)
;

ただし、ジオメトリによるグループ化は、ジオメトリ自体ではなく、ジオメトリのbboxによるグループ化になります。ポイントを扱うとき、それは重要ではありません。よくほとんど。Bboxesはポイント自体よりも精度が低く、理論上は同一ではない2つのポイントをグループ化することになります。
ニックラスアベン

ありがとう@NicklasAvén。Bboxの比較はどれくらい正確ですか?このユースケースにはこれで十分だと思います。
暗闇

1
ありがとう@underdark。交差する線の数をどのように数えることができるか知っていますか?私はいくつかの組み合わせを試してみたCOUNT()などをCOUNT(ST_Touches(..))してCOUNT(ST_Intersection(..))ますが、これはあるすべての値として動作するようには思えません12
-djq

@underdark、はい、それは絶対に十分です、それが私が「理論上」を書いた理由です。ボックスはfloat4にあり、ポイントの座標は倍精度です。そのため、ST_Point(1.000001,1.0)とST_Point(1.000002,1.0)のボックスは同じように見えます(少なくとも私のシステムでは、試したばかりです。toポイントをグループ化します)。このボックスと実際のジオメトリの違いは、dev-listでしばらく議論されてきました。
ニックラスアベン

@AlexOs提案の修正を参照してくださいgis.stackexchange.com/a/151277/3195
マーティンF

6

これは、予想より少し複雑です。ペア以上の関係を分析する良い方法がないためです。3行を関数に入れて、それらすべてが交差するかどうかを尋ねることはできません。

ただし、少なくとも1つの方法として、最初に交差点を見つけてから、各交差点で何本の道路が接触しているかを確認することができます(同じクエリですべて実行できます)。

道路が互いに完全に接続し、交差点を通過する道路がない場合、次のようなことができます(テストされていません):
忘れられたグループ句で編集されています(まだテストされていません):

SELECT distinct_crosspoints.geom as crossing, array_agg(roads.gid), count(*) FROM
  (SELECT DISTINCT (geom) geom FROM 
    (SELECT ST_Intersection(a.geom, b.geom) geom 
     FROM roads a, roads b 
     WHERE ST_Intersects(a.geom, b.geom)
    ) all_crosspoints
   ) distinct_crosspoints
   ,roads 
 WHERE ST_Intersects(distinct_crosspoints.geom, roads.geom)
 GROUP BY distinct_crosspoints.geom;

道路が適切に接続されていない場合や、一部の道路が交差点を通過している場合は、より複雑になります。

HTH

ニクラス


こんにちは、@ Nicklas、これを実行することはできません。2つの内部句は正常に機能します。をdistinct_crosspoints ,roadsテーブル名(roads_test)に置き換える必要がありますか?私はそれを試してみましたが、geomあいまいであることについてエラーが発生しました。
djq

1
@celenius、グループ条項を忘れてしまいました。また、特別なレベルで個別に配置する必要がないこともわかります。交差点に直接置くことができます。暗闇の答えの下での議論によると、Distinctはgroupと同じ動作をすることに注意してください。
ニックラスアベン

Nick_laserにdistinct_crosspoints.geomを追加して、クエリを実行しました。私のために今動作します。
フランク

1
 CREATE TABLE test_points as
    SELECT      
        ST_Intersection(a.geom, b.geom),
        Count(Distinct a.gid)
    FROM
        roads as a,
        roads as b
    WHERE
        ST_Touches(a.geom, b.geom)
        AND a.gid < b.gid   /* !!! Changed "!=" for "<"  */
    GROUP BY
        ST_Intersection(a.geom, b.geom)
    ;

ラインA(id 1)がラインB(id 2)と交差する場合、これが必要な交点です。ただし、ラインBは同じポイントでラインAと交差しています。しかし、この点は二度必要ではありません。それが私がa.gid < b.gid 代わりに使用している理由ですa.gid != b.gid

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