Python 形状中的多边形相交错误:“;shapely.geos.TopologicalError:操作';地理交叉口';生成了一个空几何体“;

Python 形状中的多边形相交错误:“;shapely.geos.TopologicalError:操作';地理交叉口';生成了一个空几何体“;,python,exception,polygon,intersection,shapely,Python,Exception,Polygon,Intersection,Shapely,我一直试图调试这个问题,但无法这样做。我试图找到两个多边形对象的交点。它大部分时间都有效,但对于以下情况,它会引发以下异常: P1 area: 13.125721955 P2 area: 1.0 Traceback (most recent call last): File "geom2d.py", line 235, in <module> print p1.intersection(p2) File "/usr/local/lib/python2.7/dist-packages/

我一直试图调试这个问题,但无法这样做。我试图找到两个
多边形
对象的交点。它大部分时间都有效,但对于以下情况,它会引发以下异常:

P1 area: 13.125721955
P2 area: 1.0
Traceback (most recent call last):
File "geom2d.py", line 235, in <module>
print p1.intersection(p2)
File "/usr/local/lib/python2.7/dist-packages/shapely/geometry/base.py", line 334, in     intersection
return geom_factory(self.impl['intersection'](self, other))
  File "/usr/local/lib/python2.7/dist-packages/shapely/topology.py", line 47, in __call__
    "The operation '%s' produced a null geometry. Likely cause is invalidity of the geometry %s" % (self.fn.__name__, repr(this)))
shapely.geos.TopologicalError: The operation 'GEOSIntersection_r' produced a null     geometry. Likely cause is invalidity of the geometry <shapely.geometry.polygon.Polygon      object at 0x8e5ad6c>
因为它打印了两个多边形的区域,所以我假设多边形的形状是正确的。我还(不知何故)打印了第一个多边形,以确保它确实是一个简单的多边形

谁能解释一下我为什么会得到这个例外

编辑:我打印的p1.0是有效的,结果是错误的。有一些解释。搜索字符串
是否有效
。上面说

有效多边形不能具有任何重叠的外环或内环

请有人解释一下这意味着什么,是否有可能的解决办法?
顺便说一句,我还注意到,如果我从
poly1
中删除最后一个坐标,整个过程都会正常工作。可能整个坐标列表使多边形变得复杂,因为
p1
不是有效的多边形,所以出现此异常

>>> p1.is_valid
False
>>> p2.is_valid
True
报告说:

有效多边形不能具有任何重叠的外部或内部 戒指

请记住,由于多边形的第一个点和最后一个点不同,shapely将把第一个点附加到列表的末尾

>>> list(p1.exterior.coords)
[(35.004100000000001, -88.195499999999996), (34.991799999999998, -85.606800000000007), (32.840400000000002, -85.175600000000003), (32.259300000000003, -84.892700000000005), (32.153500000000001, -85.034199999999998), (31.794699999999999, -85.135800000000003), (31.52, -85.043800000000005), (31.3384, -85.083600000000004), (31.209299999999999, -85.106999999999999), (31.002300000000002, -84.994399999999999), (30.9953, -87.600899999999996), (30.942299999999999, -87.592600000000004), (30.853899999999999, -87.625600000000006), (30.674499999999998, -87.407200000000003), (30.4404, -87.368799999999993), (30.1463, -87.524000000000001), (30.154599999999999, -88.386399999999995), (31.893899999999999, -88.474299999999999), (34.893799999999999, -88.102099999999993), (34.947899999999997, -88.1721), (34.910699999999999, -88.146100000000004), (35.004100000000001, -88.195499999999996)]
多边形的外部是一个线性环,它似乎也是无效的:

>>> p1.exterior.type
'LinearRing'
>>> p1.exterior.is_valid
False
您还可以看到,如果要将多边形的外部转换为线字符串,则会很复杂:

>>> l1 = LineString(p1.exterior.coords)
>>> l1.is_simple
False
不知何故,多边形的外部与自身相交或接触

进一步挖掘数据,我们可以在地图上看到它:

>>> import cgpolyencode
>>> encoder = cgpolyencode.GPolyEncoder()
>>> encoder.encode((y, x) for x, y in p1.exterior.coords)
{'points': 'svstEzthyOzkAkrxNfecL_fsAznpBcgv@ftSjsZnaeA~yRzst@_~P~mb@vwFzeXfqCvlg@w~Tvj@ra|NfjI{r@ngPfmEf`b@_ti@bvl@_oFbmx@~h]{r@~lgDsurIjdPk|hQgugAaqIntLlgFoaDwfQvsH', 'numLevels': 18, 'zoomFactor': 2, 'levels': 'PPLMKMKGKPNIKLMNPLLKJP'}

如果你把它插进去,你可以看到那是阿拉巴马州。如果你放大阿拉巴马州的左上部分,你可以看到两条线相互交叉。要解决此问题,您需要删除最后一个点或将最后一个点与第二个点交换到最后一个点。

如前所述,
p1
无效。在绘制时,我注意到右下角有一个小蝴蝶结。我假设在多边形中不需要这个;如果没有,您可以尝试Shapely的
缓冲区(0)
技巧(记录在Shapely手册中)来修复:

In [382]: p1.is_valid
Out[382]: False

In [383]: p1 = p1.buffer(0)

In [384]: p1.is_valid
Out[384]: True
缓冲区(0)
具有以下效果:

之前:

之后:

现在您可以这样做:

print p1.intersection(p2)
POLYGON ((34.9396324323625151 -88.1614025927056559, 34.8937999999999988 -88.1020999999999930, 34.7998910000000024 -88.1137513649788247, 34.7998910000000024 -87.2202139999999986, 34.9994660069532983 -87.2202139999999986, 35.0041000000000011 -88.1954999999999956, 34.9396324323625151 -88.1614025927056559))

请注意,我曾经有过这样的例子(有些地方看起来更像“鸟巢”,而不是简单的蝴蝶结),但这不起作用;检查以确保返回单个
多边形
对象,而不是
多多边形
对象。

是否有方法处理复杂多边形?理想情况下,您应该首先正确定义所有多边形。因为这是一个美国州的问题,而不是什么线索,我认为解决这个问题是更好的办法。但是,如果这不可能,您可以始终使用
p1.convertic_hull
而不是
p1
凸包始终有效,从不复杂。
print p1.intersection(p2)
POLYGON ((34.9396324323625151 -88.1614025927056559, 34.8937999999999988 -88.1020999999999930, 34.7998910000000024 -88.1137513649788247, 34.7998910000000024 -87.2202139999999986, 34.9994660069532983 -87.2202139999999986, 35.0041000000000011 -88.1954999999999956, 34.9396324323625151 -88.1614025927056559))