17 votos

¿Limpieza de geometrías en PostGIS?

Estoy tratando de procesar algunas capas de polígonos muy grandes. Sin embargo, me encuentro con varios errores de geometría como:

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

He probado la función sugerida aquí: https://trac.osgeo.org/postgis/wiki/UsersWikiCleanPolygons

para limpiar las geometrías, siendo el código que he utilizado

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

Con el resultado:

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

y también

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

Este funciona, pero sólo si primero cambio mi columna de geometría a geometría

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

¡Lo que me deja con una tabla que ya no funciona con mis otras funciones!

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

He intentado cambiar las columnas de nuevo a geometría (MultiPolygon)

ALTER TABLE public.my_table ALTER COLUMN geom SET DATA TYPE geometry(MultiPolygon);

Pero esto falla

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

He intentado revisar PostGIS in Action (Second Ed) http://www.manning.com/obe/ pero sólo puedo encontrar funciones para encontrar geometrías inválidas, pero mi conjunto de datos es tan grande para arreglar esto manualmente, realmente necesito algo que los arregle automáticamente.


He podido aislar los polígonos problemáticos, cuando intento ejecutar ST_MakeValid() obtengo el resultado:

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

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

Hice una comprobación de tipo en mi columna de geometría, y dijo que el tipo era "MULTIPOLYGON"

22voto

hernan43 Puntos 566

Puedes probar ST_CollectionExtract para extraer [Multi]Polígonos de GeometryCollections. Utilice ST_Multi para forzarlos como MuliPolígonos.

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

Una vez que haya terminado, utilice una restricción CHECK para asegurarse de que siguen siendo válidos. Ver detalles aquí .

17voto

Patrick Puntos 20392

Si sólo quiere polígonos o multipolígonos de ST_MakeValid puede utilizar ST_Dump para extraer las geometrías constituyentes y luego comprobar el tipo de geometría. ST_MakeValid a veces producirá Puntos o LineStrings que es de donde viene la GeometryCollection. Pruebe algo como:

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';

Podría utilizar una cláusula IN en lugar de la condición OR, aunque el resultado y el plan de consulta serían los mismos. Si sólo quieres Multipolígonos puedes envolver ST_Dump en el ST_Multi función.

La función row_number() over() simplemente le devolverá un identificador único, empezando por uno, para cada geometría devuelta por ST_Dump. También puede utilizar el elemento de ruta devuelto por ST_Dump, con el mismo resultado.

Es de suponer que querrá combinar esto con una sentencia CREATE TABLE cleaned_geoms AS SELECT .... type, ya que una actualización directa es poco probable que funcione ya que ST_MakeValid no producirá generalmente (o siempre) un mapeo uno a uno de I put a output.

Esto no está probado, ya que no tengo medios, actualmente, por lo que podría haber un paréntesis mal colocado, pero el principio general es sólido. Espero que esto ayude.

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