10 votos

¿Cómo recorrer recursivamente las intersecciones de polígonos principales para obtener polígonos más pequeños (secundarios) sin superposiciones?

Yo estoy luchando con un problema por un par de días y me di cuenta que muchas personas que también se bloquea cuando el tema es intersecciones en PostGIS (v2.5). Es por eso que me decidí a pedir una más detallada y genérico, común de la pregunta.

Tengo la siguiente tabla:

DROP TABLE IF EXISTS tbl_foo;
CREATE TABLE tbl_foo (
    id bigint NOT NULL,
    geom public.geometry(MultiPolygon, 4326),
    att_category character varying(15),
    att_value integer
);
INSERT INTO tbl_foo (id, geom, att_category, att_value) VALUES 
    (1, ST_SetSRID('MULTIPOLYGON (((0 6, 0 12, 8 9, 0 6)))'::geometry,4326) , 'cat1', 2 );
INSERT INTO tbl_foo (id, geom, att_category, att_value) VALUES 
    (2, ST_SetSRID('MULTIPOLYGON (((5 0, 5 12, 9 12, 9 0, 5 0)))'::geometry,4326), 'cat1', 1 );
INSERT INTO tbl_foo (id, geom, att_category, att_value) VALUES 
    (3, ST_SetSRID('MULTIPOLYGON (((4 4, 3 8, 4 12, 7 14,10 12, 11 8, 10 4, 4 4)))'::geometry,4326) , 'cat2', 5 );

Se parece a esto:

start

Quiero recibir todo lo que el niño polígonos en función de la intersección de los padres de los polígonos. Para el resultado, que sería esperado:

  • El niño polígonos con ningún solapamiento entre ellos.
  • Una columna que contiene la suma de los valores de sus padres polígonos,
  • Una columna que contiene el recuento de los padres de los polígonos de una categoría
  • Una columna que contiene el recuento de otra categoría
  • Una columna que contiene la categoría de el niño polígono, con base en la siguiente regla: -Si TODOS los padres de los polígonos que son de una clase, el niño polígono de esta clase. Otra cosa, la categoría del niño polígono es una tercera categoría.

Así que me parece que:

output

Así que, al final, la tabla de salida generada (para este ejemplo) tiene 7 filas (todos los 7, que no se superponen, hijo de polígonos), que contiene las columnas de category, sum_value, ct_overlap_cat1, ct_overlap_cat2

El código siguiente empecé, me da el individuo intersecciones, la comparación de uno de los padres con el otro.

SELECT
(ST_Dump(
    ST_SymDifference(a.geom, b.geom) 
)).geom
FROM tbl_foo a, tbl_foo b
WHERE a.ID < b.ID AND ST_INTERSECTS(a.geom, b.geom)
UNION ALL
SELECT
ST_Intersection(a.geom, b.geom) as geom
FROM tbl_foo a, tbl_foo b
WHERE a.ID < b.ID AND ST_INTERSECTS(a.geom, b.geom);

¿Cómo se forma recursiva bucle a través del resultado de este mencionado código, que, independientemente de la cantidad de superposición de polígonos siempre consigo su 'más pequeño' (niño) polígonos (Fig. 2)?

9voto

Gary Peck Puntos 151

Prueba esto:

Descargue los complementos de PostGIS desde este enlace: https://github.com/pedrogit/postgisaddons

Instale ejecutando el archivo postgis_addons.sql para obtener la función ST_SplitAgg ().

Pruebe ejecutando el archivo postgis_addons_test.sql.

Aquí está su consulta:

 WITH  result_table AS (
    WITH  parts AS (
      SELECT a.att_value val,
             CASE WHEN a.att_category = 'cat1' THEN 1 ELSE 0 END cat1,
             CASE WHEN a.att_category = 'cat2' THEN 1 ELSE 0 END cat2,
             unnest(ST_SplitAgg(a.geom, b.geom, 0.00001)) geom
      FROM tbl_foo a,
           tbl_foo b
      WHERE ST_Equals(a.geom, b.geom) OR
            ST_Contains(a.geom, b.geom) OR
            ST_Contains(b.geom, a.geom) OR
            ST_Overlaps(a.geom, b.geom)
      GROUP BY a.id, a.att_category , ST_AsEWKB(a.geom), val
    )
    SELECT CASE WHEN sum(cat2) = 0 THEN 'cat1'
                WHEN sum(cat1) = 0 THEN 'cat2'
                ELSE 'cat3'
           END category, 
           sum(val*1.0) sum_value, 
           sum(cat1) ct_overlap_cat1, 
           sum(cat2) ct_overlap_cat2, 
           ST_Union(geom) geom
    FROM parts
    GROUP BY ST_Area(geom)
)
SELECT category, sum_value, ct_overlap_cat1, ct_overlap_cat2,
(ST_Dump(result_table.geom)).geom as geom
FROM result_table
 

1voto

Cyril Puntos 141

Supongo que si utiliza un tipo de geometría poligonal en lugar de MultiPolygon, todo encajará en su lugar:

 DROP TABLE IF EXISTS tbl_foo;
CREATE TABLE tbl_foo (
    id bigint NOT NULL,
    geom public.geometry(Polygon, 4326),
    att_category character varying(15),
    att_value integer
);

INSERT INTO tbl_foo (id, geom, att_category, att_value) VALUES 
    (1, ST_SetSRID('POLYGON ((0 6, 0 12, 8 9, 0 6))'::geometry,4326) , 'cat1', 2 );
INSERT INTO tbl_foo (id, geom, att_category, att_value) VALUES 
    (2, ST_SetSRID('POLYGON ((5 0, 5 12, 9 12, 9 0, 5 0))'::geometry,4326), 'cat1', 1 );
INSERT INTO tbl_foo (id, geom, att_category, att_value) VALUES 
    (3, ST_SetSRID('POLYGON ((4 4, 3 8, 4 12, 7 14,10 12, 11 8, 10 4, 4 4))'::geometry,4326) , 'cat2', 5 );
 

El resultado son 9 entradas que corresponden a las diferentes opciones de intersección en el ejemplo dado por usted.

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