Czyścić geometrie w PostGIS?


12

Próbuję wykonać przetwarzanie na bardzo dużych warstwach wielokąta. Jednak napotykam różne błędy geometrii, takie jak:

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

Wypróbowałem funkcję sugerowaną tutaj: https://trac.osgeo.org/postgis/wiki/UsersWikiCleanPolygons

do czyszczenia geometrii użyłem kodu:

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

Z rezultatem:

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

i również

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

Ten działa, ale tylko jeśli najpierw zmienię kolumnę geometrii na geometrię

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

Co następnie pozostawia mi stół, który nie działa już z moimi innymi funkcjami!

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

Próbowałem zmienić kolumny z powrotem na geometrię (MultiPolygon)

ALTER TABLE public.my_table ALTER COLUMN ZESTAW geom TYP DANYCH geometria (MultiPolygon);

Ale to się nie udaje

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

Próbowałem przejść przez PostGIS w akcji (wydanie drugie) http://www.manning.com/obe/, ale mogę znaleźć tylko funkcje wyszukiwania nieprawidłowych geometrii, ale mój zestaw danych jest tak duży, że mogę to naprawić ręcznie, naprawdę potrzebujesz czegoś, co naprawi je automatycznie.


Udało mi się wyizolować problematyczne wielokąty, gdy próbuję uruchomić ST_MakeValid (), otrzymuję wynik:

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

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

Sprawdziłem typ mojej kolumny geometrii i stwierdziłem, że typ to „MULTIPOLYGON”


ST_MakeValid poprawia jak najwięcej.
user30184,

Rozumiem, dziękuję, właściwie popełniłem błąd w swoim pytaniu, w którym zapomniałem wspomnieć, że to ST_Make_Valid powoduje problemy z moimi kolumnami. Użyłem ST_MakeValid ale muszę zmienić kolumnę geom na typ danych geometria aby zmusić go do pracy, a raz ja, że nie mogę dostać go z powrotem do geometrii (MultiPolygon)
Mart

2
Możesz użyć hacka ST_Buffer (geom, 0), który poradzi sobie z wieloma nieprawidłowymi geometriami. Możesz także użyć ST_MakeValid. Na koniec możesz spróbować wybrać nową tabelę i umieścić ST_IsValid (geom) w klauzuli where.
John Powell,

Dzięki, próbowałem już włamać się do bufora, ale to nie zadziałało, chciało raczej wprowadzenia geometrii niż geometrii (MultiPolygon). Spróbuję tylko wybrać prawidłowe wielokąty i zobaczę, ile jest odfiltrowanych.
Mart

1
Ok. Pochodzi od st_makevalid produkujących punkty i LineStrings wraz z wielokątami, które wytworzą GeometryCollection. Jest na to poprawka, którą napiszę za kilka godzin. Mam zamiar surfować :-)
John Powell,

Odpowiedzi:


15

Jeśli chcesz tylko wielokątów lub wieloboków od ST_MakeValid , możesz użyć ST_Dump do wyodrębnienia składowych geometrii, a następnie przetestować typ geometrii. ST_MakeValid czasami produkuje Points lub LineStrings, z których pochodzi GeometryCollection. Wypróbuj coś takiego:

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

Możesz użyć klauzuli IN zamiast warunku LUB, chociaż wynik i plan zapytań byłyby takie same. Jeśli chcesz tylko Multipolygons, możesz zawinąć ST_Dump w funkcję ST_Multi .

Row_number () over () po prostu zwróci ci unikalny identyfikator, zaczynając od jednego, dla każdej geometrii zwróconej z ST_Dump. Można również użyć elementu ścieżki zwróconego przez ST_Dump, z tym samym wynikiem.

Prawdopodobnie będziesz chciał połączyć to z instrukcją typu UTWÓRZ TABELĘ clean_geoms AS SELECT ...., ponieważ jest mało prawdopodobne, aby bezpośrednia aktualizacja działała, ponieważ ST_MakeValid nie będzie generalnie (lub zawsze) generował mapowania jeden do jednego z I umieszczonego na wyjściu.

Jest to niesprawdzone, ponieważ obecnie nie mam środków, więc może być źle umieszczony nawias, ale ogólna zasada jest rozsądna. Mam nadzieję że to pomoże.


19

Możesz wypróbować ST_CollectionExtract, aby wyodrębnić [Multi] wielokąty z GeometryCollections. Użyj ST_Multi, aby wymusić je jako MuliPolygons.

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

Po zakończeniu użyj ograniczenia CHECK, aby upewnić się, że zachowają ważność. Zobacz szczegóły tutaj .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.