在PostGIS中清洗几何?


12

我正在尝试在一些非常大的多边形图层上进行一些处理。但是我遇到了各种几何错误,例如:

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

我已经尝试过此处建议的功能:https : //trac.osgeo.org/postgis/wiki/UsersWikiCleanPolygons

对于清洁几何体,我使用的代码是:

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

结果:

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

并且

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

这是可行的,但前提是我必须先将“几何”列更改为“几何”

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

这样就给我留下了一个不能再与其他功能一起使用的表!

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

我尝试将列更改回几何(MultiPolygon)

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

但这失败了

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

我曾尝试过PostGIS in Action(第二版)http://www.manning.com/obe/,但是我只能找到用于查找无效几何的函数,但是我的数据集太大,无法手动修复,我真的需要可以自动修复的内容。


当我尝试运行ST_MakeValid()时,我已经能够隔离出问题多边形:

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

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

我在几何列上进行了类型检查,结果显示类型为“ MULTIPOLYGON”


ST_MakeValid会尽可能多地进行纠正。
user30184 2015年

我知道,谢谢,我实际上在我的问题中犯了一个错误,我忘了提到是ST_Make_Valid引起了我的列问题。我使用过ST_MakeValid,但必须将geom列更改为geometry数据类型才能正常工作,一旦这样做,我就无法将其恢复为geometry(MultiPolygon)
Mart

2
您可以使用hack ST_Buffer(geom,0)来处理许多无效的几何。您也可以使用ST_MakeValid。最后,您可以尝试选择一个新表并将ST_IsValid(geom)放在where子句中。
约翰·鲍威尔,

谢谢,我已经尝试了缓冲区修改,但是没有用,它需要一个几何输入而不是geometry(MultiPolygon)。我将尝试仅选择有效的多边形,看看有多少被滤除。
集市2015年

1
好。这来自于st_makevalid生产点和LineStrings,以及将产生GeometryCollection的多边形。有一个修复程序,我将在几个小时内写下。我将要去冲浪:-)
约翰·鲍威尔

Answers:


15

如果只需要ST_MakeValid中的 Polygons或Multipolygons,可以使用ST_Dump提取组成的几何图形,然后测试几何图形类型。ST_MakeValid有时会产生Point或LineStrings,这是GeometryCollection的来源。尝试类似的东西:

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

您可以使用IN子句代替OR条件,尽管结果和查询计划是相同的。如果只希望使用Multipolygons,则可以将ST_Dump包装在ST_Multi函数中。

对于从ST_Dump返回的每个几何图形,row_number()over()都将简单地返回一个唯一的ID(从1开始)。您也可以使用ST_Dump返回的path元素,结果相同。

您可能想将其与CREATE TABLE cleaned_geoms AS SELECT ....类型语句结合使用,因为直接更新不太可能正常工作,因为ST_MakeValid通常(或始终)会产生一个从我到输出的一对一映射。

这是未经测试的,因为我目前没有任何方法,因此可能放置了错误的括号,但是总体原理是合理的。希望这可以帮助。


19

您可以尝试ST_CollectionExtract从GeometryCollections中提取[Multi]多边形。使用ST_Multi将其强制为MuliPolygons。

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

完成后,使用CHECK约束来确保它们保持有效。在这里查看详细信息。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.