Processing math: 100%

11 votos

Crear un buffer disuelto a partir de una multi-geometría (Unión por atributo compartido e intersección espacial)

Tengo que crear buffers disueltos a partir de características de entrada multipunto. En el ejemplo siguiente, la tabla de entrada contiene 4 características. Característica #2 consiste en dos geometrías puntuales. Después de crear un buffer, obtengo 4 geometrías de polígonos:

enter image description here

¿Hay alguna forma de agrupar el resultado? Los topes de los puntos #1 y #2 se disuelven y deben ser una única característica multipoligonal ( a ).

Lo que he hecho hasta ahora:

-- collect all buffers to a single multi-polygon feature
-- dissolve overlapping polygon geometries
CREATE TABLE public.pg_multibuffer AS SELECT
    row_number() over() AS gid,
    sub_qry.*
FROM (SELECT
    ST_Union(ST_Buffer(geom, 1000, 8))::geometry(MultiPolygon, /*SRID*/) AS geom
FROM
public.multipoints)
AS sub_qry;

0 votos

Utilizas demasiado las subconsultas. Esto elimina su capacidad de agrupar por el atributo en el que desea agrupar.

0 votos

Así que hay que hacer una unión espacial y luego también una unión basada en el número de característica, por lo que se esperan 3 multipolígonos del diagrama anterior. Sospecho que esto requerirá un proceso de dos pasos, pero sólo quería ser claro en la pregunta, antes de ofrecer una respuesta.

0 votos

Sí, quiero unir los polígonos del buffer y recoger el resultado basado en el número de las características de entrada.

8voto

Patrick Puntos 20392

Partiendo de algunos puntos aleatorios, en un intento de imitar los de la imagen del OP, donde los dos primeros se cruzan espacialmente, luego el 2º y el 3º tienen el mismo atributo id (2), con un par de otros puntos que ni se cruzan espacialmente ni tienen el mismo atributo, la siguiente consulta produce 3 clusters:

WITH 
  temp (id, geom) AS 
     (VALUES (1, ST_Buffer(ST_Makepoint(0, 0), 2)),
        (2, ST_Buffer(ST_MakePoint(-0.7,0.5), 2)),
        (2, ST_Buffer(ST_MakePoint(10, 10), 2)), 
        (3, ST_Buffer(ST_MakePoint(-2, 12), 2)), 
        (4, ST_Buffer(ST_MakePoint(5, -6), 2))),
 unions(geoms) AS 
      (SELECT ST_Union(geom) FROM temp GROUP BY id),
 clusters(geoms) AS 
      (SELECT ST_CollectionExtract(unnest(ST_ClusterIntersecting(geoms)), 3) 
         FROM unions),
 multis(id, geoms) AS 
      (SELECT row_number() over() as id, geoms FROM clusters)
 SELECT ST_UNION(d.geom) FROM 
      (SELECT id, (ST_DUMP(geoms)).geom FROM multis) d GROUP BY id;

Aquí hay varios pasos:

  1. utilice ST_Union agrupando por id, para agrupar primero por atributo
  2. utilice ST_ClusterIntersecting para combinar los del mismo grupo que se cruzan espacialmente
  3. añadir un id a cada uno de los clusters (tabla multis) -- intentar hacerlo directamente en el ClusterIntersecting lleva a que todas las geometrías tengan un id de 1
  4. Unión de las geometrías volcadas desde el paso 2, agrupando por el id del paso 3 -- esta es la disolver parte. Esto hace que los dos polígonos superpuestos en su cluster A, se unan, en lugar de estar superpuestos, como lo están al final del paso 2.

Bastante largo, pero funciona (y, estoy seguro de que hay una forma más corta).

Usando la herramienta WKT en QGIS, (y descubriendo lo horrible que soy con las herramientas de edición) produce clusters como el siguiente, donde se puede ver que el cluster etiquetado como a, está todo junto -- es decir, de un solo color.

enter image description here

Si pones un ST_AsText alrededor del final, ST_UNION(d.geom), entonces puedes ver los resultados directamente.

0 votos

Siento haber tardado tanto en contestarle. Tengo algunos problemas para visualizar las geometrías del buffer en QGIS. He tratado de modificar su consulta utilizando ST_SetSRID , ST_Multi y ::geometry(Multipolygon, /*SRID*/) pero por el momento no funciona.

0 votos

Bien, si puedes publicar tu código, e incluso mejor algunos datos, podría ayudarte.

0 votos

He añadido algo de SQL para crear puntos de muestra.

3voto

MBCook Puntos 8316

Una forma de hacerlo es ST_Union todos los topes juntos, ST_Dump el resultado para obtener los componentes del polígono resultante, y unir con ST_Intersects a los puntos de entrada para saber cuántos/qué puntos componen cada clúster.

Esto puede hacerse sin necesidad de una unión agrupando los puntos antes de llamando a ST_Buffer . Para que dos puntos se encuentren dentro del mismo buffer disuelto, deben ser alcanzables por saltos entre puntos de una distancia menor a eps . Se trata simplemente de un problema de agrupación de enlace mínimo, que puede resolverse mediante ST_ClusterDBSCAN :

SELECT
  cluster_id,
  ST_Union(ST_Buffer(geom, 1000)) AS geom,
  count(*)                        AS num_points,
  array_agg(point_id)             AS point_ids
FROM (
  SELECT
    point_id,
    ST_ClusterDBSCAN(geom, eps := 2000, minpoints := 1) OVER() AS cluster_id ,
    geom
  FROM points) sq
 GROUP BY cluster_id;

Tenga en cuenta que esto no producirá exactamente el mismo resultado que el método buffer-first, porque los buffers de PostGIS no son círculos perfectos y dos puntos separados por 1000m pueden no estar conectados por dos buffers de 500m.

0 votos

Parece que tuvimos una idea similar. No he probado la tuya, pero seguro que funciona, y de forma más limpia que la mía.

0 votos

Parece que PostGIS 2.2.1 no soporta ST_ClusterDBSCAN. He instalado PostGIS 2.3.2, pero las nuevas extensiones postgis en pgAdmin siguen siendo la versión 2.2.1.

0voto

Ricardo Reyes Puntos 3428

Según esta respuesta quieres hacer ST_DUMP dentro de tu subconsulta.

Algo así:

-- collect all buffers to a single multi-polygon feature
-- dissolve overlapping polygon geometries
CREATE TABLE public.pg_multibuffer AS SELECT
    row_number() over() AS gid,
    sub_qry.*
FROM (SELECT
    ST_Dump(ST_Union(ST_Buffer(geom, 1000, 8))::geometry(MultiPolygon, /*SRID*/)) AS geom
FROM
public.multipoints)
AS sub_qry;

La razón es que ST_UNION devuelve un multipolígono disuelto de todas las características, y ST_DUMP lo descompone en las características individuales de los polígonos (que se disolvieron).

1 votos

En realidad, esto no funcionará, porque se habrán perdido todos los atributos necesarios para agrupar el polígono multiparte deseado.

0 votos

He intentado ST_Multi((ST_Dump(ST_Union(ST_Buffer(geom, 1000, 8)))).geom)::geometry(MultiPolygon, /*SRID*/) AS geom pero esto crea 4 características en lugar de 3.

0 votos

Ah, claro, ¿quieres agrupar por el número? Tendrás que GROUP_BY antes de que ST_UNION .

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