Consulta recursiva PostGIS basada en la conectividad de línea

9

Estoy teniendo dificultades con una consulta. Tengo una red de cadenas lineales, cada una con un valor en la columna n_type. Esta puede ser una de las pocas opciones. Me gustaría generar una nueva tabla que agrupe las cadenas lineales que sean del mismo tipo y que formen una línea continua.

Antes de:

ingrese la descripción de la imagen aquí

Después:

ingrese la descripción de la imagen aquí

Esto es lo que tengo hasta ahora. Devuelve resultados, pero no tienen ningún sentido: los tipos no coinciden y devuelve demasiadas características.

Tenga en cuenta también que he definido "continuo" como cualquier línea dentro de los 5 pies de su vecino y que se encuentra en un ángulo de menos de 30 grados.

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

He asumido que una consulta recursiva es el camino a seguir, pero estoy feliz de que me demuestren lo contrario. Los recursivos son un poco difíciles de asimilar.

Editar: también debo agregar que ya he intentado agregar usando ST_Union y ST_Linemerge, y luego volcar el resultado. Esto funciona un poco, pero no tiene en cuenta las intersecciones de> 30 grados y tampoco puede cumplir con la tolerancia de cinco pies para la conectividad.

spencerrecneps
fuente
Sin profundizar en esto, un par de observaciones. Deberá unir a.geom y b.geom en su cláusula select. Probablemente debería asegurarse de que no lo intentas y unirse a una línea en sí, así como cona.pk_uid != b.pk_uid
MickyT
@MickyT gracias. Debería haber mencionado que puedo hacer la unión en la última cláusula SELECT, pero por el momento solo he seleccionado * para poder ver todos los resultados. Modificaré mi fragmento de código para mostrar cómo debería verse finalmente.
spencerrecneps
Las consultas recursivas son difíciles de asimilar. Lol y +1
John Powell
Un vistazo rápido sugiere que podría tener problemas con su consulta base / ancla. Debe seleccionar el punto de inicio para cada línea, A, B, C, etc., que luego construye en la parte recursiva. Posiblemente necesite agregar algún tipo de orden a la consulta de anclaje (tal vez en x o y, dirección, difícil de conocer sin ver los datos). Desglosaría esto y me aseguraría de obtener primero puntos de inicio sensatos, antes de continuar con la parte recursiva. Utilicé una consulta recursiva para encontrar rayas en series de tiempo recientemente, y una vez que identifiqué correctamente los puntos de anclaje, el resto fue fácil (ish)
John Powell
@dbaston. Buen punto, pero puedes hacer esto con una consulta recursiva también, y no todos tienen eso instalado todavía.
John Powell

Respuestas:

1

Su solución es, al menos, perder un pedido previo de componentes de línea como dijo John Barça.

Diría que las consultas recursivas son muy, muy difíciles de asimilar.

Debe intentar replicar el comportamiento de ST_Linemerge en una nueva función de base de datos. Primero intentaría mirar la fuente de una implementación ST_Linemerge y replicarla, alterándola para producir la contracción del ángulo de 30 grados.

Para descartar de la agregación los segmentos que no están en un ángulo de <30 grados, debe compararlos DENTRO de un ciclo de agregación.

rpcavaco
fuente