Query ricorsive PostGIS basate sulla connettività di linea


9

Sto riscontrando difficoltà con una query. Ho una rete di linestring, ognuno con un valore nella colonna n_type. Questa può essere una delle poche opzioni. Vorrei generare una nuova tabella che raggruppa tutte le stringhe dello stesso tipo e che formano una linea continua.

Prima:

inserisci qui la descrizione dell'immagine

Dopo:

inserisci qui la descrizione dell'immagine

Ecco cosa ho finora. Restituisce risultati ma non hanno alcun senso: i tipi non corrispondono e restituisce troppe funzionalità.

Si noti inoltre che ho definito "continuo" come qualsiasi linea entro 5 piedi dal suo vicino e che si incontrano con un angolo inferiore a 30 gradi.

WITH RECURSIVE all_links (i, pk_uid, n_type, geom) AS (
    SELECT  1 AS i,
            pk_uid,
            n_type,
            geom
    FROM    network
    WHERE   n_type != 'none'

    UNION ALL

    SELECT  a.i + 1,
            b.pk_uid,
            b.n_type,
            b.geom
    FROM    network b, all_links a
    WHERE   b.n_type = a.n_type
    AND     b.geom <#> a.geom <= 5  --lines are continuous if within 5 feet of neighbor
    AND     ABS( DEGREES( 3*pi() - st_azimuth(st_startpoint(a.geom),st_endpoint(a.geom)) + st_azimuth(st_startpoint(b.geom),st_endpoint(b.geom)))::int % 360 - 180) <= 30 )  --only take links within 30 degrees of the same angle

SELECT i, n_type, ST_Union(the_geom) FROM all_links GROUP BY i, n_type

Ho assunto che una query ricorsiva sia la strada da percorrere, ma sono felice di essermi smentito. I ricorsivi sono un po 'difficili da stimolare.

Modifica: dovrei anche aggiungere che ho già provato ad aggregare usando ST_Union e ST_Linemerge e quindi a scaricare il risultato. Questo tipo di funzionamento funziona, ma non tiene conto di incroci> 30 gradi e inoltre non può rispettare la tolleranza di cinque piedi per la connettività.


Senza scavare fino in fondo, un paio di osservazioni. Dovrai unire a.geom e b.geom nella tua clausola select. Probabilmente dovresti assicurarti di non provare a unirti a una linea con se stessaa.pk_uid != b.pk_uid
MickyT

@MickyT grazie. Avrei dovuto menzionare che posso fare l'unione nell'ultima clausola SELECT ma per il momento ho appena selezionato * in modo da poter vedere tutti i risultati. Modificherò il mio frammento di codice per mostrare come dovrebbe apparire alla fine.
spencerrecneps,

Le query ricorsive sono difficili da elaborare. Lol e +1
John Powell,

Una rapida occhiata suggerisce che potresti avere problemi con la tua query base / anchor. Devi selezionare il punto iniziale per ogni riga, A, B, C ecc., Che poi crei nella parte ricorsiva. Probabilmente è necessario aggiungere un tipo di ordinamento alla query di ancoraggio (forse in x o y, direzione - difficile da sapere senza vedere i dati). Lo analizzerei e mi assicurerei di ottenere prima i punti di partenza ragionevoli, prima di continuare con la parte ricorsiva. Di recente ho usato una query ricorsiva per trovare le strisce nelle serie storiche e una volta identificati correttamente i punti di ancoraggio, il resto è stato facile (ish)
John Powell,

@dbaston. Buon punto, ma puoi farlo anche con una query ricorsiva, e non tutti l'hanno ancora installato.
John Powell,

Risposte:


1

Almeno nella tua soluzione manca un preordine dei componenti della linea, come ha affermato John Barça.

Le domande ricorsive sono molto, molto difficili da elaborare, direi.

È necessario provare a replicare il comportamento ST_Linemerge in una nuova funzione di database. Proverei prima a guardare la fonte di un'implementazione ST_Linemerge e replicarla, alterandola per produrre la contrazione dell'angolo di 30 gradi.

Per scartare dall'aggregazione i segmenti che non hanno un angolo di <30 gradi, è necessario confrontarli all'interno di un ciclo di aggregazione.

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.