Phát hiện nếu điểm nằm ở bên trái hoặc bên phải của dòng trong PostGIS?


16

Tôi có một bảng linestring và một bảng điểm trong postgis.

Tôi biết đường gần nhất với bất kỳ điểm nào. Những gì tôi cần biết là "bên" của dòng đó là điểm. Tôi đoán tôi phải làm điều đó bằng cách tạo một đường vuông góc từ điểm đã cho đến đường thẳng (điểm gần nhất trên đường thẳng) và sau đó so sánh tọa độ, nhưng tôi không biết chính xác làm thế nào và nếu đó là cách thích hợp, kể từ khi dòng thay đổi hướng của nó.

Tôi đã tạo một bức tranh để minh họa cho nhiệm vụ của mình.

nhập mô tả hình ảnh ở đây

Bản thân dòng màu đen, hướng của nó được hiển thị bằng mũi tên màu xanh lá cây. Tôi cần thêm một cột "bên" vào bảng điểm, để các điểm đỏ phải có giá trị "bên phải" và các điểm màu xanh sẽ có giá trị "bên trái".

Ai đó có thể đưa ra một ví dụ mã SQL về tính toán giá trị "bên" của một điểm không?

Câu trả lời:


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

Vì vậy, ý tưởng là tính góc giữa đoạn thẳng gần nhất và vectơ từ điểm gần nhất trên đường đến điểm của bạn.

có được điểm gần nhất trên một dòng

select ST_ClosestPoint(line.geom, point.geom)

tạo vector từ điểm gần nhất đến điểm của bạn

ST_MakeLine(cp.p, point.geom) vec

tạo một vectơ giữa dòng của bạn

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

có được sự khác biệt giữa các hướng

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

Vì vậy, phải và trái sẽ lớn hơn 0 và thấp hơn 0.


Cảm ơn, có vẻ như là một giải pháp tốt, nhưng tôi không thích phần * 1.01. Điểm gần nhất tiếp theo của dòng có thể được chọn để làm cho truy vấn này đáng tin cậy hơn không?
mofoyoda

Tôi đã suy nghĩ về việc có được phân khúc gần nhất nhưng ở đó chúng tôi không có chức năng như vậy. Nhưng đây là giải pháp đáng tin cậy hơn vì ST_LineInterpolate được định hướng nên bạn sẽ nhận được điểm tiếp theo trở đi theo hướng đường, không chỉ gần nhất. Có thể có được nút tiếp theo thực tế, nhưng nó sẽ thôi thúc bạn lặp đi lặp lại trên tất cả các nút và tìm ra chúng tiếp theo dọc theo dòng hoặc trước điểm gần nhất trên dòng.
dmitry.v.kiselev

Xin chào Dmitry. Điều này sẽ làm việc cho một điểm nằm ngoài giới hạn nếu bạn hiểu ý tôi. Ví dụ, trên cùng bên trái hầu hết các chấm đỏ, nếu nó cao hơn 1cm. Trong trường hợp đó, điểm gần nhất và điểm sẽ không tạo góc vuông với đường ban đầu. Thuật toán này sẽ làm việc trong trường hợp đó?
Jenia Ivanov

3
ST_Azimuth(h.vec)- là một mã giả. h.vech.seglà các dòng, vì vậy để chính xác, nó phải giống nhưST_Azimuth(ST_StartPoint(h.vec), ST_EndPoint(h.vec))
dmitry.v.kiselev

2
giải pháp trên dường như không hoạt động trong trường hợp đường dây đông tây có khả năng chịu chính xác 90 độ vì một số lý do.
dùng7543032
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.