PostGIS教程十六:几何图形的有效性

 在90%的情况下,"为什么我的查询给了我一个'TopologyException'错误"的问题的答案是"一个或多个输入的几何图形是无效的",这就引出了这样一个问题:几何图形"无效"是什么意思?我们为什么要关心它?

一、什么是有效性

    对于定义有界区域并需要大量结构的多边形来说,它的几何图形有效性是最重要的。线串非常简单,不会无效,点也不会无效。

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

  • 多边形的环必须闭合
  • 定义孔洞的环应该是在外部边界的环内
  • 环不能自相交(它们不能相互接触,也不能交叉)
  • 环不能与其他环接触,除非在某个点接触

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

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

    这里有一个解释为什么几何图形的结构重要的例子。首先这个多边形是无效的

POLYGON((0 0, 0 1, 2 1, 2 2, 1 2, 1 0, 0 0));

    在此图中,你可以更清楚地看到无效的原因:

_images/figure_eight.png

    这个多边形的外环实际上是一个数字8的形状,中间有一个自交点。图形程序成功地渲染了多边形填充,使其在视觉上看起来是一个"区域":两个一个单位的正方形,因此多边形总面积为两个单位的面积。

    让我们看看PostGIS数据库认为多边形的面积是多少:

 
  1. SELECT ST_Area(ST_GeometryFromText(

  2. 'POLYGON((0 0, 0 1, 1 1, 2 1, 2 2, 1 2, 1 1, 1 0, 0 0))'

  3. ));

    这里发生了什么?计算面积的算法假设环不自相交程序始终计算位于边界线的一侧的区域的面积

然而,在我们的(表现不佳)的数字8中,对于一个叶部分,图形区域位于边界线的右侧,而对于另一个叶部分,图形区域在边界线的左侧。这将导致为每个叶部分计算的面积互相抵消(一个为1,另一个为-1),因此结果为"0面积"。

 

二、检测有效性

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

 
  1. SELECT ST_IsValid(ST_GeometryFromText(

  2. 'POLYGON((0 0, 0 1, 1 1, 2 1, 2 2, 1 2, 1 1, 1 0, 0 0))'

  3. ));

     现在我们知道这个图形是无效的,但是我们不知道为什么无效。我们可以使用ST_IsValidReason(geometry)函数来查找无效的原因:

 
  1. SELECT ST_IsValidReason(ST_GeometryFromText(

  2. 'POLYGON((0 0, 0 1, 1 1, 2 1, 2 2, 1 2, 1 1, 1 0, 0 0))'

  3. ));

    请注意,除了原因(自相交),图形自相交的坐标(coordinate(1 1))也被返回了。

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

 
  1. -- Find all the invalid polygons and what their problem is

  2. SELECT name, boroname, ST_IsValidReason(geom)

  3. FROM nyc_neighborhoods

  4. WHERE NOT ST_IsValid(geom);

 

三、修复无效的图形

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

    下面是SQL的一个示例,它将无效的几何图形从原表转移到另一张表中(注意,同时要:

 
  1. -- Side table of invalids

  2. CREATE TABLE nyc_neighborhoods_invalid AS

  3. SELECT * FROM nyc_neighborhoods

  4. WHERE NOT ST_IsValid(geom);

  5.  
  6. -- Remove them from the main table

  7. DELETE FROM nyc_neighborhoods

  8. WHERE NOT ST_IsValid(geom);

    在视觉上修复无效几何图形的一个好工具是OpenJump(http://openjump.org),它在Tools->QA->Validate Selected Layers.下包含一个验证程序。

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

  • ST_MakeValid函数
  • ST_Buffer函数

3.1、ST_MakeValid

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

 
  1. -- Fix the invalid figure-8 polygon

  2. SELECT ST_AsText(ST_MakeValid(

  3. 'POLYGON((0 0, 0 1, 1 1, 2 1, 2 2, 1 2, 1 1, 1 0, 0 0))'

  4. ));

    ST_MakeValid成功地将几何图形"8"转换为表示相同面积的multi-polygon。

3.2、ST_Buffer

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

    例如,这里有一个典型的无效现象——"香蕉多边形" —— 一个环,它包围着一个区域,但弯曲着接触自己,留下一个"孔洞(hole)",实际上并不是一个孔洞。

POLYGON((0 0, 2 0, 1 1, 2 2, 3 1, 2 0, 4 0, 4 4, 0 4, 0 0))

_images/banana.png

    在多边形上计算零偏移缓冲区将返回有效的OGC多边形,该多边形由在一点接触的外环和内环组成。

 
  1. SELECT ST_AsText(

  2. ST_Buffer(

  3. ST_GeometryFromText('POLYGON((0 0, 2 0, 1 1, 2 2, 3 1, 2 0, 4 0, 4 4, 0 4, 0 0))'),

  4. 0.0

  5. )

  6. );

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值