Визначення, чи точка в лівій чи правій частині лінії в PostGIS?


16

У мене в postgis є таблиця рядків і таблиця точок.

Я знаю найближчу лінію до будь-якої точки. Що мені потрібно знати, на якій «стороні» цієї лінії є точка. Я думаю, що я повинен це зробити, створивши перпендикулярну пряму від заданої точки до прямої (найближчої точки на прямій), а потім порівняти координати, але я не знаю точно, як це зробити, і якщо це правильний шлях, оскільки лінія змінює свій напрямок.

Я зробив малюнок, щоб проілюструвати своє завдання.

введіть тут опис зображення

Сама лінія чорна, її напрямок показаний зеленими стрілками. Мені потрібно додати стовпчик "сторона" до таблиці точок, щоб червоні точки мали значення "право", а сині - "ліворуч".

Чи може хтось навести приклад 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

Привіт Дмитре. Чи буде це спрацьовувати за точку, яка знаходиться за межами, якщо ви знаєте, що я маю на увазі. Наприклад, у верхній лівій частині найбільше червону крапку, якби вона була на 1 см вище. У цьому випадку найближча точка і точка не будуть робити прямий кут з початковою лінією. Чи працюватиме цей алгоритм у такому випадку?
Єнія Іванова

3
ST_Azimuth(h.vec)- це псевдокод. h.vecі h.segце рядки, точніше, це має бути щось на кшталтST_Azimuth(ST_StartPoint(h.vec), ST_EndPoint(h.vec))
dmitry.v.kiselev

2
вищезазначене рішення, здається, не працює в тих випадках, коли лінія схід-захід має певну точку 90 градусів.
користувач7543032
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.