2012-10-25 6 views
2

이 문제를 디버깅하려했지만 그렇게 할 수 없었습니다. 나는 두 개의 Polygon 객체의 교차를 찾으려고합니다. 대부분의 경우 작동하지만 다음과 같은 경우 예외가 발생합니다.다각형 교차 오류 | Python 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/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> 

코드는 다음과 같습니다.

from shapely.geometry import Point,Polygon,MultiPolygon 

poly1 = [(35.0041000000000011, -88.1954999999999956), (34.9917999999999978,   -85.6068000000000069), (32.8404000000000025, -85.1756000000000029), (32.2593000000000032, -84.8927000000000049), (32.1535000000000011, -85.0341999999999985), (31.7946999999999989, -85.1358000000000033), (31.5199999999999996, -85.0438000000000045), (31.3384000000000000, -85.0836000000000041), (31.2092999999999989, -85.1069999999999993), (31.0023000000000017, -84.9943999999999988), (30.9953000000000003, -87.6008999999999958), (30.9422999999999995, -87.5926000000000045), (30.8538999999999994, -87.6256000000000057), (30.6744999999999983, -87.4072000000000031), (30.4404000000000003, -87.3687999999999931), (30.1463000000000001, -87.5240000000000009), (30.1545999999999985, -88.3863999999999947), (31.8938999999999986, -88.4742999999999995), (34.8937999999999988, -88.1020999999999930), (34.9478999999999971, -88.1721000000000004), (34.9106999999999985, -88.1461000000000041)] 
poly2 = [(34.7998910000000024, -88.2202139999999986), (34.7998910000000024, -87.2202139999999986), (35.7998910000000024, -87.2202139999999986), (35.7998910000000024, -88.2202139999999986)] 

p1 = Polygon(poly1) 
p2 = Polygon(poly2) 
print 'P1 area:',p1.area 
print 'P2 area:',p2.area 
print p1.intersection(p2) 

두 개의 다각형의 영역을 인쇄하므로 다각형이 올바르게 형성되었다고 가정합니다. 나도 (어떻게 든) 첫 번째 다각형을 인쇄하여 실제로 그것이 단순한 다각형인지 확인했다.

아무도 왜이 예외가 발생하는지 설명해주세요.

편집 : 나는 p1.is_valid를 인쇄했으며 False로 판명되었습니다. 약간의 설명은 here입니다. 문자열 is_valid을 검색하십시오. 그것은 말합니다

유효한 폴리곤은 외부 또는 내부 링이 겹쳐져 있지 않을 수 있습니다.

누군가가 이것이 의미하는 바를 설명해 주실 수 있습니까? 나는 또한 poly1에서 마지막 좌표를 제거하면 모든 것이 작동한다는 것을 알았습니다. 좌표의 전체 목록은 다각형 으로 만듭니다.

답변

5

p1이 유효한 다각형이 아니기 때문에이 예외가 발생합니다.

유효한 다각형이 겹치는 외부 또는 내부 링을 소유하지 않을 수 있습니다

>>> p1.is_valid 
False 
>>> p2.is_valid 
True 

documentation는 말한다.

다각형의 첫 번째 점과 마지막 점이 매끄럽게 다르기 때문에 첫 번째 점을 목록의 끝에 추가합니다.

>>> 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': '[email protected][email protected][email protected]@[email protected]|NfjI{[email protected]`[email protected][email protected]@[email protected]~h]{[email protected]~lgDsurIjdPk|hQgugAaqIntLlgFoaDwfQvsH', 'numLevels': 18, 'zoomFactor': 2, 'levels': 'PPLMKMKGKPNIKLMNPLLKJP'} 

당신이 Google's Polyline Encoder에 당신이 알라바마의 상태라고 볼 수 연결합니다. 알라바마의 왼쪽 상단 부분을 확대하면 두 선이 서로 교차하는 것을 볼 수 있습니다.이 문제를 해결하려면 마지막 점을 제거하거나 마지막 점을 마지막 점과 마지막 점을 교환해야합니다.

+0

_complex_ 폴리곤을 처리하는 방법은 무엇입니까? – Nik

+1

처음에는 모든 다각형을 올바르게 정의해야합니다. 이것은 미국의 상태를 다루고 있기 때문에 어떤 종류의 흔적이 아니라고 생각합니다. 그걸 수정하는 것이 더 나은 방법이라고 생각합니다. 그러나 이것이 가능하지 않으면'p1' 대신'p1.convex_hull'을 사용하여 항상 작업 할 수 있습니다. 'convex_hull'은 항상 유효하고 결코 복잡하지 않습니다. –

9

이전에 지적한대로 p1은 유효하지 않습니다. 플로팅을 할 때, 나는 오른쪽 하단에있는 작은 bowtie를 발견했다. 나는 당신이 당신의 다각형 안에 이것을 필요로하지 않는다고 가정한다. 그렇지 않으면, 당신이 그 문제를 해결하기 위해 (맵시 매뉴얼에 설명) 매끈한의 buffer(0) 트릭을 시도 할 수 있습니다 :

하기 전에 :

enter image description here

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

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

In [384]: p1.is_valid 
Out[384]: True 

buffer(0)하면 다음과 같은 효과가 있습니다 :

enter image description here

(210)

그리고 지금이 작업을 수행 할 수 있습니다

나는이 작동하지 않은 경우 (더 간단 나비 넥타이보다는 "새 둥지"처럼 보였다 영역에) 어떤 경우에는이 있었다
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)) 

참고; 하나의 Polygon 개체를 다시 가져오고 MultiPolygon 개체가 아닌지 확인하십시오.