ポイントがPostGISの行の左側または右側にあるかどうかを検出しますか?


16

postgisにラインストリングテーブルとポイントテーブルがあります。

任意のポイントに最も近い線を知っています。私が知っておく必要があるのは、その行のどの「サイド」がポイントであるかです。与えられたポイントからライン(ライン上の最も近いポイント)に垂直なラインを作成し、座標を比較することでそれを行う必要があると思いますが、それを行う方法は正確にはわかりません。線が変化するため、方向が変わります。

私は自分の仕事を説明するために写真を作りました。

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

線自体は黒で、その方向は緑の矢印で示されています。ポイントテーブルに「サイド」列を追加する必要があります。そのため、赤いポイントの値は「right」、青いポイントの値は「left」になります。

誰かがポイントの「サイド」値を計算するSQLコードの例を提供できますか?

回答:


12
select (ST_Azimuth(h.vec) - ST_Azimuth(h.seg))
from (
    select 
        ST_MakeLine(cp.p, point.geom) vec,
        ST_MakeLine(cp.p, 
            ST_LineInterpolatePoint(
                line.geom, 
                ST_LineLocatePoint(line.geom, cp.p) * 1.01)
        ) seg
        from (
            select 
                ST_ClosestPoint(line.geom, point.geom)
        ) p as cp
    ) as h

したがって、アイデアは、最も近いラインセグメント間の角度と、ライン上の最も近いポイントからポイントまでのベクトルを計算することです。

線上の最も近い点を取得する

select ST_ClosestPoint(line.geom, point.geom)

あなたのポイントに最も近いポイントからベクトルを作成します

ST_MakeLine(cp.p, point.geom) vec

ライン間にベクトルを作成します

ST_MakeLine(
    --original point
    cp.p, 
    --find a point next to the closest point on line
    ST_LineInterpolatePoint(line.geom, 
         ST_LineLocatePoint(line.geom, cp.p) * 1.01)) seg

方向の違いを取得

ST_Azimuth(h.vec) - ST_Azimuth(h.seg)

そのため、右と左はゼロより大きくゼロより小さいです。


おかげで、それは良い解決策のように思えますが、* 1.01の部分は好きではありません。このクエリの信頼性を高めるために、ラインの次に近いポイントを選択できますか?
mofoyoda

最も近いセグメントを取得しようと考えていましたが、そのような機能はありません。しかし、ST_LineInterpolateが指示されているため、これはより信頼性の高いソリューションです。これにより、最も近いだけでなく、ライン方向の次のポイントを取得できます。実際の次のノードを取得することは可能ですが、すべてのノードを反復処理し、それらがラインに沿って次にあるのか、ライン上の最も近いポイントの前にあるのかを調べるように促します。
dmitry.v.kiselev

こんにちはDmitry。あなたが私が意味することを知っていれば、これは境界を超えたポイントで機能しますか?たとえば、1cm高い場合、左上の一番赤い点。その場合、最も近いポイントとポイントは元の線と直角になりません。この場合、このアルゴリズムは機能しますか?
ジェニアイヴァノフ

3
ST_Azimuth(h.vec)-は擬似コードです。h.vecそしてh.segそれはのようなものでなければなりません正確には、ラインですST_Azimuth(ST_StartPoint(h.vec), ST_EndPoint(h.vec))
dmitry.v.kiselev

2
上記の解決策は、何らかの理由でラインが東西に正確に90度の方位を持つ場合には機能しないようです。
user7543032
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.