Rilevare se il punto si trova sul lato sinistro o destro della linea in PostGIS?


16

Ho una tabella lineare e una tabella dei punti in postgis.

Conosco la linea più vicina a un determinato punto. Quello che devo sapere è su quale "lato" di quella linea è il punto. Immagino di doverlo fare creando una linea perpendicolare da un determinato punto alla linea (punto più vicino sulla linea) e quindi confrontare le coordinate, ma non so esattamente come farlo, e se è il modo corretto, poiché la linea cambia direzione.

Ho fatto una foto per illustrare il mio compito.

inserisci qui la descrizione dell'immagine

La linea stessa è nera, la sua direzione è indicata da frecce verdi. Devo aggiungere una colonna "laterale" alla tabella dei punti, in modo che i punti rossi abbiano valore "destro" e i punti blu dovrebbero avere valore "sinistro".

Qualcuno può dare un esempio di codice SQL per calcolare un valore "laterale" di un punto?

Risposte:


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

Quindi l'idea è di calcolare l'angolo tra il segmento di linea più vicino e il vettore dal punto più vicino della linea al punto.

ottenere un punto più vicino su una linea

select ST_ClosestPoint(line.geom, point.geom)

crea il vettore dal punto più vicino al punto

ST_MakeLine(cp.p, point.geom) vec

crea un vettore tra le tue linee

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

ottenere la differenza tra le direzioni

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

Quindi destra e sinistra saranno maggiori di zero e inferiori a zero.


Grazie, sembra una buona soluzione, ma non mi piace la parte * 1.01. È possibile selezionare il prossimo punto più vicino della linea per rendere più affidabile questa query?
mofoyoda,

Stavo pensando di ottenere il segmento più vicino, ma non ci è tale funzione. Ma questa è una soluzione più affidabile perché ST_LineInterpolate è diretto in modo da ottenere il punto successivo in poi la direzione della linea, non solo più vicina. È possibile ottenere il nodo successivo effettivo, ma ti esorta a scorrere su tutti i nodi e scoprire se sono i prossimi lungo la linea o prima del punto più vicino sulla linea.
dmitry.v.kiselev,

Ciao Dmitry. Funzionerà per un punto che va oltre la linea se sai cosa intendo. Ad esempio, il punto in alto a sinistra più rosso, se fosse 1 cm più alto. In tal caso, il punto più vicino e il punto non formeranno un angolo retto con la linea originale. Questo algoritmo funzionerà in quel caso?
Jenia Ivanov,

3
ST_Azimuth(h.vec)- è uno pseudocodice. h.vece h.segsono linee, quindi per essere precisi dovrebbe essere qualcosa di simileST_Azimuth(ST_StartPoint(h.vec), ST_EndPoint(h.vec))
dmitry.v.kiselev

2
la soluzione sopra non sembra funzionare nei casi in cui la linea è est-ovest con un rilevamento di esattamente 90 gradi per qualche motivo.
user7543032
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.