Geometrien in PostGIS reinigen?

12

Ich versuche, einige sehr große Polygonebenen zu verarbeiten. Ich stoße jedoch auf verschiedene Geometriefehler wie:

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

Ich habe die hier vorgeschlagene Funktion ausprobiert: https://trac.osgeo.org/postgis/wiki/UsersWikiCleanPolygons

Für die Reinigung von Geometrien habe ich folgenden Code verwendet:

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

Mit dem Ergebnis:

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

und auch

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

Dieser funktioniert, aber nur, wenn ich zuerst meine Geometriespalte in Geometrie ändere

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

Was mir dann eine Tabelle hinterlässt, die mit meinen anderen Funktionen nicht mehr funktioniert!

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

Ich habe versucht, die Spalten wieder in Geometrie zu ändern (MultiPolygon).

ALTER TABLE public.my_table ALTER COLUMN Geom SET DATA TYPE Geometrie (MultiPolygon);

Das scheitert aber

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

Ich habe versucht, PostGIS in Aktion (Second Ed) http://www.manning.com/obe/ durchzugehen, aber ich kann nur Funktionen zum Auffinden ungültiger Geometrien finden, aber mein Datensatz ist so groß, dass dies manuell behoben werden kann brauche etwas, das sie automatisch repariert.


Ich konnte die Problempolygone isolieren. Wenn ich versuche, ST_MakeValid () auszuführen, erhalte ich das folgende Ergebnis:

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

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

Ich habe meine Geometriespalte einer Typprüfung unterzogen und festgestellt, dass der Typ "MULTIPOLYGON" ist.

Mart
quelle
ST_MakeValid korrigiert so viel wie möglich.
user30184
Ich sehe, danke, ich hatte tatsächlich einen Fehler in meiner Frage gemacht, bei dem ich vergessen habe zu erwähnen, dass es ST_Make_Valid war, das die Probleme mit meinen Spalten verursacht. Ich habe ST_MakeValid verwendet, aber ich muss meine Geom-Spalte in den Geometriedatentyp ändern, damit sie funktioniert, und wenn ich das mache, kann ich sie nicht mehr auf eine Geometrie (MultiPolygon) zurücksetzen
Mart
2
Sie können den Hack ST_Buffer (geom, 0) verwenden, der viele ungültige Geometrien behandelt. Sie können auch ST_MakeValid verwenden. Schließlich können Sie versuchen, eine neue Tabelle auszuwählen und ST_IsValid (geom) in die where-Klausel einzufügen.
John Powell
Danke, ich habe den Buffer-Hack bereits ausprobiert, aber er hat nicht funktioniert. Er wollte eher eine Geometrieeingabe als eine Geometrie (MultiPolygon). Ich werde versuchen, nur die gültigen Polygone auszuwählen und zu sehen, wie viele herausgefiltert werden.
Mart
1
Okay. Dies kommt von st_makevalid, das Punkte und LineStrings zusammen mit Polygonen erzeugt, die eine GeometryCollection erzeugen. Es gibt eine Lösung dafür, die ich in ein paar Stunden aufschreiben werde. Ich bin im Begriff zu surfen :-)
John Powell

Antworten:

15

Wenn Sie nur Polygone oder Multipolygone aus ST_MakeValid möchten , können Sie mit ST_Dump die konstituierenden Geometrien extrahieren und dann auf den Geometrietyp testen. ST_MakeValid erzeugt manchmal Punkte oder Linienzeichenfolgen, von denen die GeometryCollection stammt. Versuchen Sie etwas wie:

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

Sie könnten eine IN-Klausel anstelle einer ODER-Bedingung verwenden, obwohl das Ergebnis und der Abfrageplan identisch wären. Wenn Sie nur Multipolygone möchten, können Sie ST_Dump in die ST_Multi- Funktion einschließen .

Die row_number () over () gibt Ihnen einfach eine eindeutige ID zurück, beginnend mit einer, für jede von ST_Dump zurückgegebene Geometrie. Sie können auch das von ST_Dump zurückgegebene Pfadelement mit demselben Ergebnis verwenden.

Vermutlich möchten Sie dies mit einer Anweisung vom Typ CREATE TABLE bereinigte_geoms AS SELECT .... kombinieren, da eine direkte Aktualisierung wahrscheinlich nicht funktioniert, da ST_MakeValid im Allgemeinen (oder immer) keine Eins-zu-Eins-Zuordnung von I zur Ausgabe erzeugt.

Dies ist ungetestet, da ich derzeit keine Mittel habe, so dass es möglicherweise eine falsch platzierte Klammer gibt, aber das allgemeine Prinzip ist solide. Hoffe das hilft.

John Powell
quelle
19

Sie können ST_CollectionExtract ausprobieren , um [Multi] -Polygone aus GeometryCollections zu extrahieren. Verwenden Sie ST_Multi, um sie als MuliPolygons zu erzwingen.

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

Verwenden Sie anschließend eine CHECK-Einschränkung, um sicherzustellen, dass sie gültig bleiben. Details finden Sie hier .

Mike T.
quelle