Detectando se o ponto está no lado esquerdo ou direito da linha no PostGIS?


16

Eu tenho uma tabela de cadeia de linhas e uma tabela de pontos no postgis.

Eu sei a linha mais próxima de qualquer ponto. O que eu preciso saber é de qual "lado" dessa linha é o ponto. Acho que tenho que fazer isso criando uma linha perpendicular de um ponto a outro (ponto mais próximo da linha) e depois comparando as coordenadas, mas não sei exatamente como fazer isso, e se for da maneira correta, já que a linha muda de direção.

Eu fiz uma foto para ilustrar minha tarefa.

insira a descrição da imagem aqui

A linha em si é preta, sua direção é mostrada com setas verdes. Eu preciso adicionar uma coluna "lateral" à tabela de pontos, para que os pontos vermelhos tenham valor "right" e os pontos azuis tenham valor "left".

Alguém pode dar um exemplo de código SQL para calcular o valor "lateral" de um ponto?

Respostas:


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

Portanto, a idéia é calcular o ângulo entre o segmento de linha mais próximo e o vetor do ponto mais próximo da linha ao seu ponto.

obter um ponto mais próximo em uma linha

select ST_ClosestPoint(line.geom, point.geom)

crie o vetor do ponto mais próximo ao seu ponto

ST_MakeLine(cp.p, point.geom) vec

crie um vetor entre sua linha

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

obtenha a diferença entre as direções

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

Então, direita e esquerda serão maiores que zero e menores que zero.


Obrigado, parece uma boa solução, mas não gosto da parte * 1.01. O próximo ponto mais próximo da linha pode ser selecionado para tornar essa consulta mais confiável?
— Mofoyoda 31/07/2015

Eu estava pensando em obter o segmento mais próximo, mas não existe essa função. Mas essa é uma solução mais confiável, porque ST_LineInterpolate é direcionado para que você obtenha o próximo ponto na direção da linha, e não apenas o mais próximo. É possível obter o próximo nó real, mas recomendamos que você repita todos os nós e descubra se eles são os próximos ao longo da linha ou antes do ponto mais próximo da linha.
— 31415 Dmitry.v.kiselev

Oi Dmitry. Isso funcionará para um ponto que está além da linha, se você entende o que quero dizer. Por exemplo, o ponto superior esquerdo mais vermelho, se fosse 1 cm mais alto. Nesse caso, o ponto mais próximo e o ponto não farão um ângulo reto com a linha original. Esse algoritmo funcionará nesse caso?
— Jenia Ivanov

3
ST_Azimuth(h.vec)- é um pseudocódigo. h.vece h.segsão linhas, por isso para ser mais preciso, deve ser algo comoST_Azimuth(ST_StartPoint(h.vec), ST_EndPoint(h.vec))
— dmitry.v.kiselev

2
a solução acima parece não funcionar nos casos em que a linha é leste-oeste, tendo um rumo de exatamente 90 graus por algum motivo.
— user7543032
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.