4 votos

Fusión de líneas cuyos extremos no están conectados pero sí cercanos en PostGIS

Tengo una red de ejemplo como la que se muestra a continuación.

CREATE TABLE sample (id integer, geom geometry(MultiLineString, 4326));
INSERT INTO sample (id, geom)
VALUES  (1, ST_GeomFromText('MULTILINESTRING((136.6047267616309 36.58881962722421,136.60472407895327 36.588929462324984))', 4326)),
        (2, ST_GeomFromText('MULTILINESTRING((136.60423725884255 36.58906837160822,136.60424396418773 36.58891438698953))', 4326)),
        (3, ST_GeomFromText('MULTILINESTRING((136.60424396418773 36.58891438698953,136.60424798685528 36.58878839916548),(136.60424798685528 36.58878839916548,136.6040039063554 36.588896081289306))', 4326)),
        (4, ST_GeomFromText('MULTILINESTRING((136.60463154321133 36.588421203276084,136.60473346697609 36.5885762652826),(136.60473346697609 36.5885762652826,136.6047267616309 36.58881962722421))', 4326)),
        (5, ST_GeomFromText('MULTILINESTRING((136.60463154321133 36.588421203276084,136.60528197878045 36.5881638415882))', 4326)),
        (6, ST_GeomFromText('MULTILINESTRING((136.60442098943724 36.58891977123062,136.60424396418773 36.58891438698953))', 4326)),
        (7, ST_GeomFromText('MULTILINESTRING((136.6047053038069 36.589643388231934,136.60439684983498 36.58964231174343))', 4326)),
        (8, ST_GeomFromText('MULTILINESTRING((136.6047267616309 36.58881962722421,136.60507142500649 36.58882608795375))', 4326)),
        (9, ST_GeomFromText('MULTILINESTRING((136.60455241815976 36.588284446070475,136.60463154321133 36.588421203276084))', 4326)),
        (10,ST_GeomFromText('MULTILINESTRING((136.6042198236861 36.58963692750234,136.60423859973173 36.58906837160822))', 4326)),
        (11,ST_GeomFromText('MULTILINESTRING((136.6037987170373 36.58982644523445,136.6038201748613 36.58906837160822),(136.6038201748613 36.58906837160822,136.60382419842824 36.58897468833135))', 4326)),
        (12,ST_GeomFromText('MULTILINESTRING((136.6047053038069 36.589643388231934,136.60472005628571 36.58906837160822))', 4326)),
        (13,ST_GeomFromText('MULTILINESTRING((136.60472407895327 36.588929462324984,136.60442098943724 36.58891977123062))', 4326)),
        (14,ST_GeomFromText('MULTILINESTRING((136.6040039063554 36.58889715777775,136.60382419842824 36.58897468833135))', 4326)),
        (15,ST_GeomFromText('MULTILINESTRING((136.60439684983498 36.58964231174343,136.60441562498124 36.58906837160822),(136.60441562498124 36.58906837160822,136.60442098943724 36.58891977123062))', 4326)),
        (16,ST_GeomFromText('MULTILINESTRING((136.6042198236861 36.58963692750234,136.60421580101854 36.58983505984031),(136.60421580101854 36.58983505984031,136.6040039063554 36.58983075208772),(136.6040039063554 36.58983075208772,136.6037987170373 36.58982644523445))', 4326)),
        (17,ST_GeomFromText('MULTILINESTRING((136.60439684983498 36.58964231174343,136.6042198236861 36.58963692750234))', 4326)),
        (18,ST_GeomFromText('MULTILINESTRING((136.60471871539653 36.58906837160822,136.60472407895327 36.588929462324984))', 4326))
;

La red se ilustra a continuación. Cada segmento de línea está coloreado de forma diferente. Esta red contiene algunos colgantes (puntos rojos). Hay tres rectángulos rojos en los que las aristas de los enlaces no están topológicamente conectadas (por lo que se detectan como colgantes).

¿Hay alguien que pueda tener la amabilidad de proporcionar consultas o funciones (o puestos relacionados) que puedan conectar y fusionar estos enlaces en uno solo en PostGIS? Por lo que he comprobado, la distancia entre los nodos son menos de 20 cm por lo que puede ser utilizado como un umbral en el proceso.

Creo que debería haber funciones apropiadas en PostGIS, pero lo que pude encontrar fueron los posts relacionados con la búsqueda de islas hasta ahora.

enter image description here

3voto

S.Lott Puntos 207588

Lo siguiente hará lo que se requiere.
Los pasos son los siguientes:

  1. Encontrar nodos a menos de 1 metro de otros nodos que no se tocan (unidad EPSG)
  2. Agrupa estos nodos y obtén el punto central (un punto al que encajar las líneas)
  3. Encaja las líneas con 2 metros de un punto central al punto.
  4. Eliminar las líneas que se han movido de la salida

DROP TABLE IF EXISTS public.ge_snappedlines;
CREATE TABLE public.ge_snappedlines AS
SELECT DISTINCT
    l.id ,
    ST_TRANSFORM(ST_Snap(ST_TRANSFORM(l.geom,3857), ST_TRANSFORM(p.geom,3857), 2),4326) geom
FROM
    public.ge_linestosnap l,
    (
    SELECT 
    row_number() over (ORDER BY unnest(ST_ClusterWithin(ST_TRANSFORM(geom,3857), 1))) AS id, 
    ST_Centroid(unnest(ST_ClusterWithin(ST_TRANSFORM(geom,3857), 1))) geom
    FROM (
        SELECT DISTINCT p.*
        FROM public.ge_linestosnap l, 
        (SELECT id, (ST_DumpPoints(geom)).geom FROM public.ge_linestosnap) as p
        WHERE ST_DWithin(ST_TRANSFORM(l.geom,3857), ST_TRANSFORM(p.geom,3857), 1) AND NOT ST_TOUCHES(l.geom, p.geom) AND l.id != p.id
        )AS nodes) AS p

Ahora a borrar los geoms que fueron movidos:

DELETE FROM public.ge_snappedlines sl
USING 
(
SELECT DISTINCT l.* 
FROM ge_snappedlines l, 
    sample s,
    (SELECT id FROM(
    SELECT id, ROW_NUMBER() OVER(PARTITION BY id ORDER BY geom asc) AS Row, geom 
    FROM ONLY ge_snappedlines l
    ) dups WHERE row > 1) ids
WHERE l.id = ids.id AND ST_EQUALS(ST_Snap(ST_TRANSFORM(s.geom,3857),ST_TRANSFORM(l.geom,3857),0.001), ST_TRANSFORM(l.geom,3857))
) as dels
WHERE sl.geom = dels.geom

Input Output Images

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