一、什么是有效性?

对于多边形来说,有效性是最重要的,因为多边形定义了有界区域,需要很好的结构。线串非常简单,不会无效,点也不会无效。

多边形有效性的一些规则很明显,而另一些规则是任意的(事实上,是任意的)。

  • 多边形的环必须闭合

  • 内环必须位于外环的内部

  • 环不能自相交(它们不能相互接触,也不能交叉)

  • 除了在某个点接触,环不能与其他环接触

最后两条规则属于任意类别。定义多边形的其他规则也是自洽合理的,但是上面的规则是PostGIS所遵循的OGC SFSQL标准所定义的多边形有效性的规则。

规则之所以重要,是因为几何图形的计算依赖于输入的几何图形的结构。可以构建没有结构假设的算法,但这些程序往往非常慢,因为任何无结构程序的第一步都是分析输入并在其中构建结构。

二、检测有效性

在前面的示例中,我们可以轻易发现一个多边形是无效的。然而我们如何在一个包含数百万个几何图形的表中检测无效?答案是使用ST_IsValid(geometry)函数:

SELECT ST_IsValid(ST_GeometryFromText(
         'POLYGON((0 0, 0 1, 1 1, 2 1, 2 2, 1 2, 1 1, 1 0, 0 0))'
));

使用ST_IsValidReason(geometry)函数来查找无效的原因

也可以使用ST_IsValid(geometry)函数来测试数据表

三、修复无效的图形

首先,坏消息是:没有100%确定的方法来修复无效的几何图形。最坏的情况是使用ST_IsValid(geometry)函数识别它们,然后将单独它们移动到另一张表,导出该表,然后在外部(比如说桌面端GIS软件)修复它们。

下面是SQL的一个示例,它将无效的几何图形从原表转移到另一张表中。

-- Side table of invalids
CREATE TABLE nyc_neighborhoods_invalid AS
SELECT * FROM nyc_neighborhoods
WHERE NOT ST_IsValid(geom);
 
-- Remove them from the main table
DELETE FROM nyc_neighborhoods
WHERE NOT ST_IsValid(geom);

可以使用以下任何一种方法在数据库中修复很大一部分的缺陷:

  • ST_MakeValid函数

  • ST_Buffer函数

ST_MakeValid函数

ST_MakeValid函数尝试在不对输入几何图形进行更改的情况下修复缺陷。不会删除或移动任何顶点,只需重新排列对象的结构即可。对于清晰但无效的数据来说,这个函数非常适用,对于杂乱无章且无效的数据来说,这个函数可能并不适用。

ST_Buffer

使用缓冲区技巧清理时,可以利用缓冲区的生成方式来达到修复几何图形的目的:缓冲区几何图形是全新的几何图形,由关于原始图形的偏移线构建。如果不偏移原始线(零),则新几何图形在结构上将与原始几何图形相同,但由于它是使用OGC拓扑规则构建的,因此它将是有效的。