简体   繁体   English

修复 Shapely 中的无效多边形

[英]Fix invalid polygon in Shapely

Shapely defines a Polygon as invalid if any of its segments intersect, including segments that are colinear.如果多边形的任何线段相交,包括共线的线段,Shapely 将多边形定义为无效。 Many software packages will create a region or area with a "cutout" as shown here which has colinear segments:许多软件包将创建一个带有“切口”的区域或区域,如下所示,它具有共线段:

在此处输入图像描述

>>> pp = Polygon([(0,0), (0,3), (3,3), (3,0), (2,0), 
                  (2,2), (1,2), (1,1), (2,1), (2,0), (0,0)])
>>> pp.is_valid
WARNING:shapely.geos:Self-intersection at or near point 2 0
False

Naturally, the cutout can be implemented natively in Shapely, or this same geometry can be implemented as two valid polygons, but if I only have the list of points shown above, is there an easy to "fix" this (create valid geometry from this list of points)?自然地,切口可以在 Shapely 中本地实现,或者这个相同的几何可以实现为两个有效的多边形,但是如果我只有上面显示的点列表,是否有一个容易“修复”的方法(从这个创建有效的几何点列表)?

I found a solution that works for the specific case given:我找到了一个适用于特定情况的解决方案:

>>> pp2 = pp.buffer(0)
>>> pp2.is_valid
True
>>> pp2.exterior.coords[:]
[(0.0, 0.0), (0.0, 3.0), (3.0, 3.0), (3.0, 0.0), (2.0, 0.0), (0.0, 0.0)]
>>> pp2.interiors[0].coords[:]
[(2.0, 1.0), (2.0, 2.0), (1.0, 2.0), (1.0, 1.0), (2.0, 1.0)]

Shapely defines a Polygon as invalid if any of its segments intersect, including segments that are colinear.如果多边形的任何段(包括共线的段)相交,则将Shape定义为无效。 Many software packages will create a region or area with a "cutout" as shown here which has colinear segments:许多软件包都会创建带有“切口”的区域或区域,如下所示,该区域具有共线段:

在此处输入图片说明

>>> pp = Polygon([(0,0), (0,3), (3,3), (3,0), (2,0), 
                  (2,2), (1,2), (1,1), (2,1), (2,0), (0,0)])
>>> pp.is_valid
WARNING:shapely.geos:Self-intersection at or near point 2 0
False

Naturally, the cutout can be implemented natively in Shapely, or this same geometry can be implemented as two valid polygons, but if I only have the list of points shown above, is there an easy to "fix" this (create valid geometry from this list of points)?自然,可以在Shapely中本地实现切口,或者可以将相同的几何图形实现为两个有效的多边形,但是如果我只有上面显示的点列表,是否可以轻松地“修复”此问题(从此创建有效的几何图形)点列表)?

Untested, but it appears that Shapely have added a function to support this now.未经测试,但似乎 Shapely 现在已经添加了一个功能来支持这一点。

https://shapely.readthedocs.io/en/latest/manual.html#validation.make_valid https://shapely.readthedocs.io/en/latest/manual.html#validation.make_valid

Shapely implemented a solution for this matter.为这个问题完美地实施了一个解决方案。 Through pip you can use shapely 1.8a3 version and import this way:通过 pip 您可以使用匀称的 1.8a3 版本并以这种方式导入:

from shapely.validation import make_valid from shapely.validation 导入 make_valid

Unfortunately, if you have had to install other libraries via conda such as geopandas you will probably face a dependency problem because at this point conda only offers shapely 1.7.1 version.不幸的是,如果你不得不通过 conda 安装其他库,比如 geopandas,你可能会面临依赖问题,因为此时 conda 只提供 1.7.1 版本。 So you can use the shapely solution at your program as shown below:所以你可以在你的程序中使用匀称的解决方案,如下所示:

def make_valid(ob): def make_valid(ob):

from shapely.geometry.base import geom_factory
from shapely.geos import lgeos

if ob.is_valid:
    return ob
return geom_factory(lgeos.GEOSMakeValid(ob._geom))

I have used the .buffer(0) method a lot, but it gave different results on Windows and on Linux.我经常使用 .buffer(0) 方法,但它在 Windows 和 Linux 上给出了不同的结果。 Therefore if you encounter such a problem, remember that:因此,如果您遇到这样的问题,请记住:

Warning : The .buffer(0) function of shapely may behave different on different operating systems, ie Windows and Linux.警告:shapely 的 .buffer(0) 函数在不同的操作系统上可能会有不同的表现,例如 Windows 和 Linux。 I had examples, where on Linux an empty Polygon is returned while on Windows the correct non-empty Polygon is returned!我有一些例子,在 Linux 上返回一个空多边形,而在 Windows 上返回正确的非空多边形!

This problem took me days to solve, that's why I want to add that as an answer (my suggested edit to the accepted answer was sadly rejected).这个问题花了我几天的时间来解决,这就是为什么我想将其添加为答案(我对已接受答案的建议编辑被遗憾地拒绝了)。

simplest solution最简单的解决方案

new_polygon = pp.buffer(0)
new_polygon.is_valid

maybe it would be work.也许它会工作。

This is my first attempt at a fix geometry function.这是我第一次尝试修复几何 function。 I had to handle the special case where a polygons are converted to multipolygons, where make_valid doesn't work b/c len(make_valid(feature)) !=1 .我必须处理将多边形转换为多多边形的特殊情况,其中make_valid不起作用 b/c len(make_valid(feature)) !=1

from shapely.validation import make_valid

def fix_geom(in_feature):

    # avoid changing original geodf
    in_feature = in_feature.copy(deep=True)    
        
    # drop any missing geometries
    in_feature = in_feature[~(in_feature.is_empty)]
    
    # Repair broken geometries
    for index, row in in_feature.iterrows(): # Looping over all polygons
        if row['geometry'].is_valid:
            next
        else:
            fix = make_valid(row['geometry'])

            try:
                in_feature.loc[[index],'geometry'] =  fix # issue with Poly > Multipolygon
            except ValueError:
                in_feature.loc[[index],'geometry'] =  in_feature.loc[[index], 'geometry'].buffer(0)
    return in_feature

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM