Geometrie di pulizia in PostGIS?


12

Sto provando a fare qualche elaborazione su alcuni strati poligonali molto grandi. Tuttavia mi imbatto in vari errori geometrici come:

NOTICE:  Ring Self-intersection at or near point 470396.52017068537 141300.52235257279
CONTEXT:  PL/pgSQL function st_intersection(geometry,raster,integer) line 10 at RETURN QUERY
SQL function "st_intersection" statement 1
NOTICE:  Ring Self-intersection at or near point 504154.61769969884 140782.04115761846
CONTEXT:  PL/pgSQL function st_intersection(geometry,raster,integer) line 10 at RETURN QUERY
SQL function "st_intersection" statement 1
NOTICE:  Ring Self-intersection at or near point 505255.50242871145 140803.34860398644
CONTEXT:  PL/pgSQL function st_intersection(geometry,raster,integer) line 10 at RETURN QUERY
SQL function "st_intersection" statement 1
NOTICE:  Ring Self-intersection at or near point 510312.46970004693 141215.29256710084
CONTEXT:  PL/pgSQL function st_intersection(geometry,raster,integer) line 10 at RETURN QUERY
SQL function "st_intersection" statement 1
NOTICE:  Ring Self-intersection at or near point 510312.46970004693 141215.29256710084
CONTEXT:  PL/pgSQL function st_intersection(geometry,raster,integer) line 10 at RETURN QUERY
SQL function "st_intersection" statement 1
NOTICE:  Ring Self-intersection at or near point 511839.50335641927 141115.85781738357
CONTEXT:  PL/pgSQL function st_intersection(geometry,raster,integer) line 10 at RETURN QUERY
SQL function "st_intersection" statement 1
NOTICE:  Ring Self-intersection at or near point 515064.03024010791 140895.68087158105
CONTEXT:  PL/pgSQL function st_intersection(geometry,raster,integer) line 10 at RETURN QUERY
SQL function "st_intersection" statement 1
NOTICE:  Ring Self-intersection at or near point 519233.18724611058 140881.47590733573
CONTEXT:  PL/pgSQL function st_intersection(geometry,raster,integer) line 10 at RETURN QUERY
SQL function "st_intersection" statement 1
NOTICE:  Ring Self-intersection at or near point 521072.73011588014 141044.83299615697
CONTEXT:  PL/pgSQL function st_intersection(geometry,raster,integer) line 10 at RETURN QUERY
SQL function "st_intersection" statement 1
NOTICE:  Ring Self-intersection at or near point 523331.31943088671 141144.26774587421
CONTEXT:  PL/pgSQL function st_intersection(geometry,raster,integer) line 10 at RETURN QUERY
SQL function "st_intersection" statement 1
NOTICE:  Ring Self-intersection at or near point 523331.31943088671 141144.26774587424
CONTEXT:  PL/pgSQL function st_intersection(geometry,raster,integer) line 10 at RETURN QUERY
SQL function "st_intersection" statement 1
NOTICE:  Ring Self-intersection at or near point 523395.24176999065 140725.22130063715
CONTEXT:  PL/pgSQL function st_intersection(geometry,raster,integer) line 10 at RETURN QUERY
SQL function "st_intersection" statement 1
NOTICE:  Ring Self-intersection at or near point 524531.63890961662 140810.45108610913
CONTEXT:  PL/pgSQL function st_intersection(geometry,raster,integer) line 10 at RETURN QUERY
SQL function "st_intersection" statement 1

Ho provato la funzione suggerita qui: https://trac.osgeo.org/postgis/wiki/UsersWikiCleanPolygons

per la pulizia delle geometrie, il codice che ho usato è:

UPDATE public.mytable
SET geom=cleangeometry(geom);

Con il risultato:

ERROR:  GEOSisSimple: IllegalArgumentException: This method does not support GeometryCollection arguments

e anche

UPDATE public.valid_mytable
SET geom=ST_MakeValid(geom);

Questo funziona, ma solo se cambio prima la mia colonna geometrica in geometria

ALTER TABLE public.mytable  ALTER COLUMN geom SET DATA TYPE geometry;

Che poi mi lascia con un tavolo che non funziona più con le altre mie funzioni!

ERROR:  Relate Operation called with a LWGEOMCOLLECTION type.  This is unsupported.

Ho provato a cambiare le colonne in geometria (MultiPolygon)

ALTER TABLE public.my_table ALTER COLUMN geom IMPOSTA TIPO DATI geometria (MultiPolygon);

Ma questo fallisce

ERROR:  Geometry type (GeometryCollection) does not match column type (MultiPolygon)

Ho provato a utilizzare PostGIS in Action (Second Ed) http://www.manning.com/obe/ ma riesco a trovare solo le funzioni per trovare geometrie non valide, ma il mio set di dati è così grande da risolvere manualmente, davvero bisogno di qualcosa che li risolva automaticamente.


Sono stato in grado di isolare i poligoni problema, quando provo ad eseguire ST_MakeValid () ottengo il risultato:

ERROR:  Geometry type (GeometryCollection) does not match column type      (MultiPolygon)
 ********** Error **********

 ERROR: Geometry type (GeometryCollection) does not match column type      (MultiPolygon)
SQL state: 22023

Ho fatto un controllo del tipo sulla mia colonna della geometria e ha detto che il tipo era "MULTIPOLYGON"


ST_MakeValid corregge il più possibile.
user30184

Vedo, grazie, ho effettivamente fatto un errore nella mia domanda in cui ho dimenticato di dire che è stato ST_Make_Valid a causare i problemi con le mie colonne. Ho usato ST_MakeValid ma devo cambiare la mia colonna geom con il tipo di dati della geometria per farlo funzionare, e una volta fatto non posso riportarlo su una geometria (MultiPolygon)
Mart

2
Puoi usare l'hack ST_Buffer (geom, 0) che gestirà molte geometrie non valide. Puoi anche usare ST_MakeValid. Infine, puoi provare a selezionare in una nuova tabella e a inserire ST_IsValid (geom) nella clausola where.
John Powell,

Grazie, ho già provato l'hacker del buffer, ma non ha funzionato, voleva un input di geometria anziché una geometria (MultiPolygon). Proverò solo a selezionare i poligoni validi e vedrò quanti vengono filtrati.
Mart

1
Ok. Questo deriva da punti di produzione st_makevalid e LineStrings insieme a poligoni che produrranno un GeometryCollection. C'è una soluzione per questo che scriverò tra un paio d'ore. Sto per fare surf :-)
John Powell il

Risposte:


15

Se si desidera solo poligoni o multipoligoni da ST_MakeValid, è possibile utilizzare ST_Dump per estrarre le geometrie costituenti e quindi verificare il tipo di geometria. A volte ST_MakeValid produce punti o LineStrings da cui proviene GeometryCollection. Prova qualcosa del tipo:

SELECT 
  g.geom, 
  row_number() over() AS gid,
FROM 
  (SELECT 
     (ST_DUMP(ST_MakeValid (geom))).geom FROM your_table
  ) AS g
WHERE ST_GeometryType(g.geom) = 'ST_MultiPolygon' 
   OR ST_GeometryType(g.geom) = 'ST_Polygon';

È possibile utilizzare una clausola IN anziché una condizione OR, sebbene il risultato e il piano di query siano uguali. Se vuoi solo Multipolygons puoi avvolgere ST_Dump nella funzione ST_Multi .

Row_number () over () restituirà semplicemente un ID univoco, a partire da uno, per ogni geometria restituita da ST_Dump. È inoltre possibile utilizzare l'elemento path restituito da ST_Dump, con lo stesso risultato.

Probabilmente vorrai combinare questo con un'istruzione di tipo CREATE TABLE clean_geoms AS SELECT ...., poiché è improbabile che un aggiornamento diretto funzioni poiché ST_MakeValid non genererà generalmente (o sempre) un mapping uno a uno da quello che ho messo in output.

Questo non è testato in quanto non ho mezzi, al momento, quindi potrebbe esserci una parentesi fuori posto, ma il principio generale è valido. Spero che sia di aiuto.


19

Puoi provare ST_CollectionExtract per estrarre [Multi] poligoni da GeometryCollections. Usa ST_Multi per forzarli come MuliPolygons.

UPDATE public.valid_lcmsouthshapefile
  SET geom=ST_Multi(ST_CollectionExtract(ST_MakeValid(geom), 3))
  WHERE NOT ST_IsValid(geom);

Al termine, utilizzare un vincolo CHECK per assicurarsi che rimangano validi. Vedi i dettagli qui .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.