1、前言
我手里有个矢量数据,但内部有很多‘洞’,如下图所示现在需要根据洞的大小去修补,比如面积,把面积小于某个值,比如2000,的洞全部补上,而对于超过2000的洞则不用修补,希望最后得到的结果是如下所示
可以看到,比较小的洞已经消失了
2、思路
emmmmm我想了很久,结论是我不会补洞,但我会挖洞......
1、读取数据,使用geopandas.read_file(),获取到矢量数据的信息
2、获取整个矢量的外部边界,并将边界转成面,同时将原本的属性赋值给它,构建新的GeoDataFrame
3、获取到所有的洞,用列表存起来
4、根据筛选条件筛选出符合要求的洞,并构建成一个GeoDataFrame
5、利用裁剪进行“挖洞”
6、保存为新的矢量数据
3、代码
import geopandas
from geopandas import GeoSeries
from shapely.geometry import Polygon, MultiPolygon
def capHoles(file_path, out_path, area):
"""
根据面积条件修补shp数据的空洞
:param file_path: 输入数据
:param out_path: 输出数据
:param area: 筛选面积
:return:
"""
src_data = geopandas.read_file(file_path)
# 根据原数据构建无洞的多边形
# 获取多边形的外部边界
outer_boundary = src_data.exterior
# 转成面
polygon_boundary = GeoSeries([Polygon(outer_boundary[i]) for i in range(len(outer_boundary))])
polygon_dataframe = geopandas.GeoDataFrame(src_data, geometry=polygon_boundary, crs='EPSG:3857')
# 求洞
holes = polygon_dataframe.difference(src_data)
polyList = []
for i in range(len(holes)):
if holes[i].geom_type == 'MultiPolygon':
for j in range(len(holes[i])):
polyList.append(holes[i][j])
else:
polyList.append(holes[i])
holesSelect = []
for hole in polyList:
if hole.area < area:
holesSelect.append(hole)
holesPolygon = GeoSeries(holesSelect)
holesDataFrame = geopandas.GeoDataFrame(geometry=src_data.geometry.append(holesPolygon), crs='EPSG:3857')
# 裁剪
outShp = polygon_dataframe.clip(holesDataFrame)
outShp.to_file(out_path)
if __name__ == '__main__':
file_path = r'D:\test\test3857.shp'
out_path = r'D:\test\test.shp'
area = 2000
capHoles(file_path, out_path, area)
4、结果
基本满足要求,不过
“左上角这个正方形很拽啊!你很会打吗?你会打有个屁用啊?出来混要有势力,要有背景。你哪个道上的?”
“我叫阿杰,你不喜欢叫的话,你就叫我太子好了....”
“原来是小瘪三(小别扇)”
我是腰椎,see you!