geopandas学习(七) 空间计算
1. 基于geopandas的矢量计算
geopandas中的矢量计算根据性质的不同可分为以下几类:
1.1 构造型方法
geopandas中的构造型方法(Constructive Methods)指的是从单个GeoSeries或GeoDataFrame中创建新的矢量数据的过程。
譬如早在系列第一篇文章数据结构篇中就介绍过的bounds、exterior、interiors、boundary、centroid、convex_hull、envelope等属性,就基于GeoSeries计算出对应的边界、内外轮廓线、重心等新的矢量数据,这些本文不再赘述,下面我们来学习geopandas中常用的其他构造方法。
- buffer()
geopandas中的buffer()方法源于shapely,用于缓冲区的创建,这里给非GIS专业的读者朋友解释一下什么是空间意义上的缓冲区:
缓冲区用于表示点、线、面等矢量数据的影响范围或服务范围,思想很简单,即为矢量数据拓展出一定宽度的边,图1展示了点、线以及面分别对应的缓冲区的示意:
而创建缓冲区时也需要遵循一定的参数,从而决定怎样向几何对象外进行缓冲,geopandas中buffer()和shapely中的buffer()方法参数一致,主要参数如下:
- distance:用于指定向外缓冲的距离,单位与矢量数据自带单位保持一致,在常见的投影坐标系如Web Mercator(EPSG:3857)下就是以米为单位,因此需要注意一定要先将矢量数据转换为合适的投影坐标系之后,再进行缓冲区分析才是合理有效的
- resolution:因为在创建缓冲区时,对于构成矢量对象的每一个点,都会以对应点为中心向外创建半径=缓冲区距离的圆,而Polygon类型始终是由有限个点所构成的,因此需要近似拼接出圆形的轮廓,resolution参数就用于决定每个四分之一圆弧上使用多少段连续的线段来近似拼接以表示圆的形状,默认参数值为16,足以近似模拟圆面积的99.8%
下面我们分别对点、线以及面绘制不同resolution参数取值下缓冲前后的对比图:
fig, axes = plt.subplots(3, 3, figsize=(9, 9))
axes = axes.flatten()
pt = shapely.geometry.Point([0, 0])
ls = shapely.geometry.LineString([(0, 0), (1, 0), (1, 1)])
polygon = shapely.geometry.Polygon([(0, 0), (1, 0), (1, 1), (0, 1)])
axes[0] = gpd.GeoSeries([pt,
pt.buffer(distance=0.2, resolution=1)]) \
.plot(ax=axes[0],
alpha=0.2)
axes[0].axis('off')
axes[0].set_title('点:resolution=3')
axes[1] = gpd.GeoSeries([pt,
pt.buffer(distance=0.2, resolution=4)]) \
.plot(ax=axes[1],
alpha=0.2)
axes[1].axis('off')
axes[1].set_title('点:resolution=16')
axes[2] = gpd.GeoSeries([pt,
pt.buffer(distance=0.2, resolution=16)]) \
.plot(ax=axes[2],
alpha=0.2)
axes[2].axis('off')
axes[2].set_title('点:resolution=16')
axes[3] = gpd.GeoSeries([ls,
ls.buffer(distance=0.2, resolution=1)]) \
.plot(ax=axes[3],
alpha=0.2)
axes[3].axis('off')
axes[3].set_title('线:resolution=1')
axes[4] = gpd.GeoSeries([ls,
ls.buffer(distance=0.2, resolution=4)]) \
.plot(ax=axes[4],
alpha=0.2)
axes[4].axis('off')
axes[4].set_title('线:resolution=4')
axes[5] = gpd.GeoSeries([ls,
ls.buffer(distance=0.2, resolution=16)]) \
.plot(ax=axes[5],
alpha=0.2)
axes[5].axis('off')
axes[5].set_title('线:resolution=16')
axes[6] = gpd.GeoSeries([polygon,
polygon.buffer(distance=0.2, resolution=1)]) \
.plot(ax=axes[6],
alpha=0.2)
axes[6].axis('off')
axes[6].set_title('面:resolution=1')
axes[7] = gpd.GeoSeries([polygon,
polygon.buffer(distance=0.2, resolution=4)]) \
.plot(ax=axes[7],
alpha=0.2)
axes[7].axis('off')
axes[7].set_title('面:resolution=4')
axes[8] = gpd.GeoSeries([polygon,
polygon.buffer(distance=0.2, resolution=16)]) \
.plot(ax=axes[8],
alpha=0.2)
axes[8].axis('off')
axes[8].set_title('面:resolution=16')
plt.savefig('图2.png', dpi=300, bbox_inches='tight', pad_inches=0)
可以看出,resolution参数对最终形成的缓冲区形态影响较大,但默认16的参数下已经可以较准确地逼近圆形,且缓冲距离还可以设置为负数,即几何对象向内收缩:
# 分别绘制多边形、多边形正向缓冲区、多边形负向缓冲区
ax = gpd.GeoSeries([polygon,
polygon.buffer(distance=1),
polygon.buffer(distance=-0.25)]) \
.plot(alpha=0.2)
ax.axis('off')
plt.savefig('图3.png', dpi=300, bbox_inches&