Individuazione degli incroci stradali tramite PostGIS


17

Sto cercando di identificare dove si intersecano le strade e di stabilire un punto a questo incrocio, con il numero di strade che formano l'incrocio elencato.

inserisci qui la descrizione dell'immagine

Mi chiedevo se ci fosse un modo per usare ST_NumPoints per raggiungere questo obiettivo, ma non riesco proprio a capire cosa dovrei fare. Quello che ho fatto è creare una tabella di punti in cui le linee si intersecano usando il seguente codice:

CREATE TABLE test_points as
SELECT      
    ST_Intersection(a.geom, b.geom),
    a.gid
FROM
    roads as a,
    roads as b
WHERE
    ST_Touches(a.geom, b.geom);

Se eseguo questo su un campione di strade ottengo la seguente griglia di punti (le strade sono mostrate a scopo illustrativo):

inserisci qui la descrizione dell'immagine

Se ispeziono uno dei punti, vedo che ci sono molti punti uno sopra l'altro:

inserisci qui la descrizione dell'immagine

Il GID qui è l'ID della strada, ma non capisco perché ci siano alcuni punti. Riesco a capire che 4 punti vengono contati per un incrocio stradale centrale, ma ci sono 12 punti elencati qui. Esiste un modo migliore per eseguire questo calcolo in PostGIS?

Risposte:


21

Se raggruppi, dovresti ottenere solo punti unici.

CREATE TABLE test_points as
SELECT      
    ST_Intersection(a.geom, b.geom),
    Count(Distinct a.gid)
FROM
    roads as a,
    roads as b
WHERE
    ST_Touches(a.geom, b.geom)
    AND a.gid != b.gid
GROUP BY
    ST_Intersection(a.geom, b.geom)
;

Solo un avviso, il raggruppamento per geometria comporta il raggruppamento per la bbox della geometria, non per la geometria stessa. Non importa quando si tratta di punti. Be 'quasi. Bboxes ha meno precisione del punto stesso che in teoria può portare a raggruppare due punti che non sono identici.
Nicklas Avén,

Grazie @ NicklasAvén. Quanto è preciso il confronto Bbox? Mi aspetto che sia sufficiente per questo caso d'uso.
underdark

1
Grazie @underdark. Sai come posso contare il numero di linee che si intersecano? Ho provato alcune combinazioni di COUNT()come COUNT(ST_Touches(..))e COUNT(ST_Intersection(..))ma questo non sembra funzionare come lo sono tutti i valori 12.
djq

@underdark, sì, è assolutamente sufficiente, ecco perché ho scritto "in teoria". Il riquadro è in float4 e le coordinate del punto sono in doppia precisione. Quindi la scatola avrà lo stesso aspetto per ST_Point (1.000001,1.0) e ST_Point (1.000002,1.0) (almeno nel mio sistema, ho appena provato. Raggruppa i punti). Questa differenza tra la scatola e la geometria reale è stata per qualche tempo una discussione su dev-list.
Nicklas Avén,

Vedi la modifica suggerita da @AlexOs gis.stackexchange.com/a/151277/3195
Martin F

6

Questo è un po 'più complicato di quanto ci si possa aspettare. Questo perché non esiste un buon modo per analizzare le relazioni per più di coppie. Non è possibile inserire tre linee in una funzione e chiedere se si intersecano tutte.

Ma almeno un approccio potrebbe essere quello di trovare prima gli incroci, quindi controllare quante strade toccano ad ogni incrocio (tutto può essere fatto nella stessa query).

Se le tue strade si collegano perfettamente tra loro e non ci sono strade che passano da un incrocio, allora potresti fare qualcosa del genere (non testato):
modificato con clausola di gruppo dimenticata (ancora non testata):

SELECT distinct_crosspoints.geom as crossing, array_agg(roads.gid), count(*) FROM
  (SELECT DISTINCT (geom) geom FROM 
    (SELECT ST_Intersection(a.geom, b.geom) geom 
     FROM roads a, roads b 
     WHERE ST_Intersects(a.geom, b.geom)
    ) all_crosspoints
   ) distinct_crosspoints
   ,roads 
 WHERE ST_Intersects(distinct_crosspoints.geom, roads.geom)
 GROUP BY distinct_crosspoints.geom;

Se le strade non sono collegate correttamente e / o alcune strade attraversano un incrocio, è più complicato.

HTH

Nicklas


Ciao @Nicklas, non riesco a farlo funzionare. Le due clausole interne funzionano bene; dovrei sostituire il distinct_crosspoints ,roadscon il mio nome tabella ( roads_test)? Ci ho provato, ma poi ho avuto un errore geomnell'essere ambiguo.
djq

1
@celenius, mi spiace di aver dimenticato la clausola di gruppo. Vedo anche che non è necessario mettere distinti su un livello aggiuntivo. Puoi semplicemente inserirlo direttamente sull'intersezione. Si noti che Distinto ha lo stesso comportamento del gruppo in base alla discussione alla voce Sottotitoli.
Nicklas Avén,

Ho aggiunto distinto_crosspoints.geom alla risposta Nicklas per far funzionare la query. Funziona ora per me.
Frank,

1
 CREATE TABLE test_points as
    SELECT      
        ST_Intersection(a.geom, b.geom),
        Count(Distinct a.gid)
    FROM
        roads as a,
        roads as b
    WHERE
        ST_Touches(a.geom, b.geom)
        AND a.gid < b.gid   /* !!! Changed "!=" for "<"  */
    GROUP BY
        ST_Intersection(a.geom, b.geom)
    ;

Se la linea A (id 1) attraversa la linea B (id 2) è un punto di intersezione di cui abbiamo bisogno. Ma la linea B incrocia anche la linea A nello stesso punto. Ma non abbiamo bisogno di questo punto due volte. Ecco perché sto usando a.gid < b.gid invece dia.gid != b.gid

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.