In questo post dettaglierò quanto ho avuto occasione di scrivere in questo articolo di Andrea
Domanda: “Come trasformare una raccolta di poligoni sovrapposti in una raccolta di poligoni non sovrapposti che conservano informazioni sui poligoni sovrapposti che li hanno formati?” In sintesi, come fare una OverlayUnion (molti a uno) con un solo layer e conservare gli attributi?

Nell’esempio di sopra, da un insieme di tre cerchi sovrapposti a un insieme di sette poligono non sovrapposti e con gli attributi di provenienza.
Costruiamo un esempio più complesso di quello di sopra, generiamo dei punti casuali all’interno di un Bbox di un poligono qualsiasi:
-- crea geotabella vuota che conterrà i punti casuali
CREATE TABLE punti
(id INTEGER PRIMARY KEY AUTOINCREMENT, cir_id INTEGER);
-- popola il campo ID della geotabella
INSERT INTO punti
WITH RECURSIVE
cnt (id) AS (SELECT 1 UNION ALL SELECT id + 1 FROM cnt LIMIT 100)
SELECT id, 0 FROM cnt;
SELECT AddGeometryColumn ('punti', 'geom', 4326, 'POINT', 'XY');
-- aggiorna la tabella con le coordinate random all''interno del bbox
UPDATE punti SET geom =
(SELECT makepoint (
CAST (
(select (0.5 - RANDOM ()/CAST(-9223372036854775808 AS REAL)/2)*(extent_max_x - extent_min_x) + extent_min_x
FROM "vector_layers_statistics" WHERE id = punti.id AND table_name = 'poly') AS REAL),
CAST (
(select (0.5 - RANDOM ()/CAST (-9223372036854775808 AS REAL)/2)*(extent_max_y - extent_min_y) + extent_min_y
FROM "vector_layers_statistics" WHERE id = punti.id AND table_name ='poly') AS REAL), 4326)
WHERE id = punti.id);
Ora generiamo dei cerchi centrati nei punti in modo che si verifichino delle sovrapposizioni:
CREATE TABLE cerchi AS
SELECT id, ST_Buffer(geom, 0.01) AS geom
FROM punti;
SELECT RecoverGeometryColumn ('cerchi', 'geom', 4326, 'POLYGON', 'XY');

Ora è il momento di smontare i poligoni. In questo caso prenderemo l’anello esterno dei cerchi, usando St_ExteriorRing . Una volta che abbiamo gli anelli, vogliamo assicurarci che ovunque gli anelli che attraversano le linee siano spezzati, in modo che non vi siano linee incrociate, si toccano solo nei punti finali. Lo facciamo con la funzione St_Union.
-- estrai i perimetri e li smonta
CREATE TABLE perimetri AS
SELECT ST_Union(ST_ExteriorRing(geom)) AS geom
FROM cerchi;
SELECT RecoverGeometryColumn ('perimetri', 'geom', 4326, 'MULTILINESTRING', 'XY');
Ora che abbiamo smontato i perimetri, possiamo inviarle a ST_Polygonize per generare poligoni. I poligoni escono come un grande poligono multiplo, quindi useremo la funzione di SpatiaLite ElementaryGeometries per convertirlo in una tabella con una riga per poligono.
-- crea geotabella polygonize
CREATE TABLE polygonize AS
SELECT St_Polygonize(geom) as geom
FROM perimetri;
SELECT RecoverGeometryColumn('polygonize','geom',4326,'MULTIPOLYGON','XY');
-- crea geotabella dalle componenti elementari della geotabella polygonize
SELECT DropGeoTable('elementi');
SELECT ElementaryGeometries( 'polygonize' ,
'geom' , 'elementi' ,'out_pk' , 'out_multi_id', 1 ) as num, 'poligoni splitted' as label;
Infine, associamo gli attributi
-- crea poligoni di output con attributi
SELECT DropGeoTable( "OUTPUT");
CREATE TABLE OUTPUT AS
SELECT Group_Concat(id) as id, e.geom
FROM cerchi p, elementi e
where st_intersects (ST_PointOnSurface(e.geom), p.geom) = 1
GROUP BY e.geom;
SELECT RecoverGeometryColumn('OUTPUT','geom',4326,'POLYGON','XY');
NOTE FINALI: Il presente problema è possibile affrontarlo con altri software GIS come QGIS o altri tool a riga di comando come mapshaper. (qui un bel articolo di Andrea)
RIFERIMENTI
- PostGIS Overlays : http://blog.cleverelephant.ca/2019/07/postgis-overlays.html
- SpatiaLite : https://www.gaia-gis.it/fossil/libspatialite/index
- Spatial SQL functions : http://www.gaia-gis.it/gaia-sins/spatialite-sql-5.0.0.html
- Immagine di copertina da una idea di Andrea Borruso
DATI
Se il blog post vi è piaciuto cliccate su ‘Mi piace’, grazie!!!
if you liked the blog post click on ‘Like’, thank you !!!
Grandioso!
Buon anno nuovo!
"Mi piace"Piace a 1 persona
Grazie Simone, ricambio
Buon 2020
"Mi piace""Mi piace"