20 votos

Identificación de intersecciones de carreteras mediante PostGIS

Estoy tratando de identificar dónde se cruzan las carreteras, y hacer un punto en esta intersección, con el número de carreteras que forman la intersección enumerados.

enter image description here

Me preguntaba si habría alguna forma de utilizar ST_NumPoints para conseguirlo, pero no acabo de entender qué debo hacer. Lo que he hecho es crear una tabla de puntos donde se cruzan las líneas utilizando el siguiente código:

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);

Si lo ejecuto en una muestra de carreteras, obtengo la siguiente cuadrícula de puntos (las carreteras se muestran a título ilustrativo):

enter image description here

Si inspecciono uno de los puntos, veo que hay muchos puntos apilados unos encima de otros:

enter image description here

El GID aquí es la identificación de la carretera, pero no entiendo por qué hay tantos puntos. Puedo entender que se cuenten 4 puntos para una intersección central de carreteras, pero aquí aparecen 12 puntos. ¿Hay una mejor manera de realizar este cálculo en PostGIS?

23voto

tobes Puntos 19

Si se agrupan, deberían obtener sólo puntos únicos.

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)
;

6voto

Lars Mæhlum Puntos 4569

Esto es un poco más complicado de lo que cabría esperar. Esto se debe a que no hay una buena forma de analizar relaciones para más de pares. No puedes poner tres líneas en una función y preguntar si todas ellas se cruzan.

Pero, al menos un enfoque podría ser encontrar primero los cruces y luego comprobar cuántas carreteras se tocan en cada cruce (todo se puede hacer en la misma consulta).

Si tus carreteras conectan perfectamente entre sí, y no hay carreteras que pasen por un cruce, entonces podrías hacer algo como esto (no probado):
editado con cláusula de grupo olvidado (aún sin probar):

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;

Si las carreteras no están bien conectadas y/o algunas carreteras pasan por un cruce es más complicado.

HTH

Nicklas

1voto

Jerry Puntos 1382
 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)
    ;

Si la línea A (id 1) cruza la línea B (id 2) es un punto de intersección que necesitamos. Pero la recta B también cruza a la recta A en el mismo punto. Pero no necesitamos este punto dos veces. Por eso utilizo a.gid < b.gid en lugar de a.gid != b.gid

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X