在Python 3.6中计算polygon和shapefile之间的重叠

时间:2018-05-16 13:22:11

标签: python cartopy

我想计算shapefile和多边形之间的重叠百分比。我使用了Cartopy和Matplotlib并创建了这里显示的地图:

enter image description here

显示欧洲的一部分(使用shapefile下载here)和任意矩形。让我们说我想计算矩形覆盖的比利时百分比。我该怎么做?下面显示了到目前为止的代码。

import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.io.shapereader as shapereader
from shapely.geometry import Polygon
from descartes import PolygonPatch

#create figure
fig1 = plt.figure(figsize=(10,10))  
PLT = plt.axes(projection=ccrs.PlateCarree())
PLT.set_extent([-10,10,45,55])
PLT.gridlines()

#import and display shapefile
fname = r'C:\Users\Me\ne_50m_admin_0_countries.shp'
adm1_shapes = list(shapereader.Reader(fname).geometries())
PLT.add_geometries(adm1_shapes, ccrs.PlateCarree(),
              edgecolor='black', facecolor='gray', alpha=0.5)

#create arbitrary polygon
x3 = 4
x4 = 5
y3 = 50
y4 = 52

poly = Polygon([(x3,y3),(x3,y4),(x4,y4),(x4,y3)])
PLT.add_patch(PolygonPatch(poly,  fc='#cc00cc', ec='#555555', alpha=0.5, 
zorder=5))

4 个答案:

答案 0 :(得分:2)

嗯,您需要某种方式来获取整个地图的区域以及该国家/地区的区域。多边形的区域可能是最简单的部分。

我建议从更基本的东西开始,也许只是一个网格和两个简单​​的形状,这可以帮助你设想如何在更复杂的层面上完成它。

答案 1 :(得分:2)

如果你有两个多边形的形状。您可以执行以下操作:

from shapely.geometry import Polygon
p1=Polygon([(0,0),(1,1),(1,0)])
p2=Polygon([(0,1),(1,0),(1,1)])
p3=p1.intersection(p2)
print(p3) # result: POLYGON ((0.5 0.5, 1 1, 1 0, 0.5 0.5))
print(p3.area) # result: 0.25

当然,我过分简化问题,结果很可能是欧几里得地区,这可能不是你需要的。如上所述,对于球体表面上的多边形区域,您可以验证following reference中的代码。为了获得灵感,您还可以验证matlab函数areaint n。我不知道它是否直接存在于python中的类似函数。

答案 2 :(得分:2)

基于其他人发布的所有答案/评论,最终我在最后添加这些行时起作用了。没有受访者的帮助,我无法做到:

#find the Belgium polygon. 
for country in shapereader.Reader(fname).records(): 
    if country.attributes['SOV_A3'] == 'BEL': 
        Belgium = country.geometry 
        break 
PLT.add_patch(PolygonPatch(poly.intersection(Belgium), fc='#009900', alpha=1)) 

#calculate coverage 
x = poly.intersection(Belgium) 
print ('Coverage: ', x.area/Belgium.area*100,'%')

答案 3 :(得分:0)

我正在利用给出的答案来找到两个旋转的矩形的交集(请找到原始答案here)。如果您觉得它有用,请不要回答这个答案,但请继续投票给原始海报。我不赞成这一点。此外,这个答案必须适应您的具体情况。

TL:DR答案涉及使用shapely

    import shapely.geometry
    import shapely.affinity

    class RotatedRect:
        def __init__(self, cx, cy, w, h, angle):
            self.cx = cx
            self.cy = cy
            self.w = w
            self.h = h
            self.angle = angle

        def get_contour(self):
            w = self.w
            h = self.h
            c = shapely.geometry.box(-w/2.0, -h/2.0, w/2.0, h/2.0)
            rc = shapely.affinity.rotate(c, self.angle)
            return shapely.affinity.translate(rc, self.cx, self.cy)

        def intersection(self, other):
            return self.get_contour().intersection(other.get_contour())


    r1 = RotatedRect(10, 15, 15, 10, 30)
    r2 = RotatedRect(15, 15, 20, 10, 0)

    from matplotlib import pyplot
    from descartes import PolygonPatch

    fig = pyplot.figure(1, figsize=(10, 4))
    ax = fig.add_subplot(121)
    ax.set_xlim(0, 30)
    ax.set_ylim(0, 30)

    ax.add_patch(PolygonPatch(r1.get_contour(), fc='#990000', alpha=0.7))
    ax.add_patch(PolygonPatch(r2.get_contour(), fc='#000099', alpha=0.7))
    ax.add_patch(PolygonPatch(r1.intersection(r2), fc='#009900', alpha=1))

    pyplot.show()