PostGIS'te geometrileri temizleme?


12

Bazı çok büyük çokgen katmanlar üzerinde bazı işlemler yapmaya çalışıyorum. Ancak ben gibi çeşitli geometri hatalarıyla karşılaşıyorum:

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

Burada önerilen işlevi denedim: https://trac.osgeo.org/postgis/wiki/UsersWikiCleanPolygons

geometrileri temizlemek için kullandığım kod:

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

Sonuçla beraber:

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

ve ayrıca

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

Bu işe yarar, ama sadece geometri sütunumu ilk önce geometriye değiştirirsem

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

Bu da beni artık diğer işlevlerimle çalışmayan bir masaya bırakıyor!

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

Geometriye (MultiPolygon) geri sütunları değiştirmeyi denedim

ALTER TABLE public.my_table ALTER COLUMN geom SET VERİ TÜRÜ geometrisi (MultiPolygon);

Ama bu başarısız oluyor

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

PostGIS in Action (Second Ed) http://www.manning.com/obe/ üzerinden geçmeyi denedim ama sadece geçersiz geometrileri bulmak için işlevleri bulabilirim, ancak veri setim bunu manuel olarak düzeltmek için çok büyük, gerçekten Onları otomatik olarak düzelten bir şeye ihtiyacım var.


ST_MakeValid () çalışmayı denediğimde, sorun çokgenleri izole edebildim, sonucu alıyorum:

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

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

Geometri sütunumda tip kontrolü yaptım ve tipin "ÇOKOLOJİ" olduğunu söyledi.


ST_MakeValid olabildiğince düzeltir.
user30184

Görüyorum, teşekkürler, aslında benim sütunlarda sorunlara neden ST_Make_Valid olduğunu belirtmeyi unuttum sorum bir hata yapmıştı. Ben ST_MakeValid kullandım ama işe almak için geom sütun geometri veri türünü değiştirmek zorunda ve bunu bir kez bunu bir geometri (MultiPolygon) geri alamıyorum
Mart

2
Birçok geçersiz geometriyi ele alacak olan kesmek ST_Buffer (geom, 0) kullanabilirsiniz. ST_MakeValid'i de kullanabilirsiniz. Son olarak, yeni bir tablo seçip ST_IsValid'i (geom) where yan tümcesine yerleştirmeyi deneyebilirsiniz.
John Powell

Teşekkürler, zaten tampon kesmek denedim, ama işe yaramadı, bir geometri (MultiPolygon) yerine bir geometri girişi istedi. Sadece geçerli çokgenleri seçmeye çalışacağım ve kaç tanesinin filtrelendiğini göreceğim.
Mart

1
Tamam. Bu, GeometryCollection üretecek çokgenlerle birlikte st_makevalid üretim noktalarından ve LineStrings'ten gelir. Birkaç saat içinde yazacağım bunun için bir düzeltme var. Ben sörf gitmek üzereyim :-)
John Powell

Yanıtlar:


15

Yalnızca ST_MakeValid'den Çokgenler veya Çok Çokgenler istiyorsanız , bileşen geometrilerini çıkarmak ve ardından geometri türünü test etmek için ST_Dump kullanabilirsiniz . ST_MakeValid bazen GeometryCollection öğesinin geldiği Noktalar veya LineStrings üretir. Şuna benzer bir şey deneyin:

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

Sonuç ve sorgu planı aynı olsa da, OR koşulu yerine IN yan tümcesi kullanabilirsiniz. Yalnızca Multipolygons istiyorsanız sarar ST_Dump içinde ST_Multi fonksiyonu.

Row_umber () over (), ST_Dump öğesinden döndürülen her geometri için birinden başlayarak size benzersiz bir kimlik döndürür. Aynı sonuçla ST_Dump tarafından döndürülen yol öğesini de kullanabilirsiniz.

Muhtemelen bunu bir CREATE TABLE ile birleştirmek isteyeceksiniz.

Şu anda hiçbir imkanım olmadığı için bu test edilmemiştir, bu nedenle yanlış yerleştirilmiş bir parantez olabilir, ancak genel prensip sağlamdır. Bu yardımcı olur umarım.


19

GeometryCollections öğesinden [Çok] Çokgenler ayıklamak için ST_CollectionExtract'ı deneyebilirsiniz . Onları MuliPolygons olarak zorlamak için ST_Multi kullanın.

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

İşiniz bittikten sonra, geçerli kaldıklarından emin olmak için bir CHECK kısıtlaması kullanın. Ayrıntılar için buraya bakın .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.