extract.py
from pathlib import Path
from osgeo import ogr, osr, gdal
import os
import shutil
def buffer(inShp, fname, bdistance=0.02):
""":param inShp: 输出的矢量门路:param fname: 输入的矢量门路:param bdistance: 缓冲区间隔:return:"""ogr.UseExceptions()in_ds = ogr.Open(inShp)f = open(inShp.replace('.shp','.prj'))f_ = f.readline()in_lyr = in_ds.GetLayer()# 创立输入Buffer文件driver = ogr.GetDriverByName('ESRI Shapefile')if Path(fname).exists(): driver.DeleteDataSource(fname)# 新建DataSource,Layerout_ds = driver.CreateDataSource(fname)out_lyr = out_ds.CreateLayer(fname, in_lyr.GetSpatialRef(), ogr.wkbPolygon)def_feature = out_lyr.GetLayerDefn()# # 新建area字段# new_field = ogr.FieldDefn("Area", ogr.OFTReal)# new_field.SetWidth(40)# new_field.SetPrecision(20) # 设置面积精度,小数点后16位# out_lyr.CreateField(new_field)# 遍历原始的Shapefile文件给每个Geometry做Buffer操作for feature in in_lyr: geometry = feature.GetGeometryRef() buffer = geometry.Buffer(bdistance) out_feature = ogr.Feature(def_feature) out_feature.SetGeometry(buffer) out_lyr.CreateFeature(out_feature) out_feature = Noneout_ds.FlushCache()del in_ds, out_ds
def area(shpPath):
'''计算面积'''max_area = 0driver = ogr.GetDriverByName("ESRI Shapefile")dataSource = driver.Open(shpPath, 1)layer = dataSource.GetLayer()new_field = ogr.FieldDefn("Area", ogr.OFTReal)new_field.SetWidth(32)new_field.SetPrecision(16) # 设置面积精度,小数点后16位layer.CreateField(new_field)for feature in layer: geom = feature.GetGeometryRef() area = geom.GetArea() # 计算面积 if area > max_area: max_area = area feature.SetField("Area", area) # 将面积增加到属性表中 layer.SetFeature(feature)dataSource = Nonereturn max_area
def multipoly2poly(inputshp, outputshp):
""":param inputshp: 输出的矢量门路:param outputshp: 输入的矢量门路:return:"""gdal.UseExceptions()driver = ogr.GetDriverByName('ESRI Shapefile')in_ds = driver.Open(inputshp, 0)in_lyr = in_ds.GetLayer()if os.path.exists(outputshp): driver.DeleteDataSource(outputshp)out_ds = driver.CreateDataSource(outputshp)out_lyr = out_ds.CreateLayer('poly', geom_type=ogr.wkbPolygon)for in_feat in in_lyr: geom = in_feat.GetGeometryRef() if geom.GetGeometryName() == 'MULTIPOLYGON': for geom_part in geom: addPolygon(geom_part.ExportToWkb(), out_lyr) else: addPolygon(geom.ExportToWkb(), out_lyr)
def addPolygon(simplePolygon, out_lyr):
featureDefn = out_lyr.GetLayerDefn()polygon = ogr.CreateGeometryFromWkb(simplePolygon)out_feat = ogr.Feature(featureDefn)out_feat.SetGeometry(polygon)out_lyr.CreateFeature(out_feat)# print('Polygon added.')
def uni(shpPath, fname):
""":param shpPath: 输出的矢量门路:param fname: 输入的矢量门路:return:"""driver = ogr.GetDriverByName("ESRI Shapefile")dataSource = driver.Open(shpPath, 1)layer = dataSource.GetLayer()# 新建DataSource,Layerout_ds = driver.CreateDataSource(fname)out_lyr = out_ds.[PM](https://www.gendan5.com/wallet/PerfectMoney.html)CreateLayer(fname, layer.GetSpatialRef(), ogr.wkbPolygon)def_feature = out_lyr.GetLayerDefn()# 遍历原始的Shapefile文件给每个Geometry做Buffer操作# current_union = layer[0].Clone()print('the length of layer:', len(layer))if len(layer) == 0: returnfor i, feature in enumerate(layer): geometry = feature.GetGeometryRef() if i == 0: current_union = geometry.Clone() current_union = current_union.Union(geometry).Clone() if i == len(layer) - 1: out_feature = ogr.Feature(def_feature) out_feature.SetGeometry(current_union) out_lyr.ResetReading() out_lyr.CreateFeature(out_feature)
def remove_big_buffer(shpPath, outputShp, area_thresold):
'''计算面积'''driver = ogr.GetDriverByName("ESRI Shapefile")dataSource = driver.Open(shpPath, 1)layer = dataSource.GetLayer()new_field = ogr.FieldDefn("Area", ogr.OFTReal)new_field.SetWidth(32)new_field.SetPrecision(16) # 设置面积精度,小数点后16位layer.CreateField(new_field)# 新建DataSource,Layerout_ds = driver.CreateDataSource(outputShp)out_lyr = out_ds.CreateLayer(outputShp, layer.GetSpatialRef(), ogr.wkbPolygon)def_feature = out_lyr.GetLayerDefn()for feature in layer: geom = feature.GetGeometryRef() area = geom.GetArea() # 计算面积 if area > area_thresold * 1.2: continue feature.SetField("Area", area) # 将面积增加到属性表中 layer.SetFeature(feature) out_feature = ogr.Feature(def_feature) out_feature.SetGeometry(geom) out_lyr.CreateFeature(out_feature) out_feature = Noneout_ds.FlushCache()del dataSource, out_ds
def intersection(shp1, shp2, outshp):
""":param shp1: 缓冲区矢量门路:param shp2: 指标矢量门路:param outshp: 输入矢量门路:return:"""driver = ogr.GetDriverByName("ESRI Shapefile")dataSource1 = driver.Open(shp1, 1)layer1 = dataSource1.GetLayer()dataSource2 = driver.Open(shp2, 1)layer2 = dataSource2.GetLayer()spatialref = layer2.GetSpatialRef()# 新建DataSource,Layerout_ds = driver.CreateDataSource(outshp)out_lyr = out_ds.CreateLayer(outshp, spatialref, ogr.wkbPolygon)def_feature = out_lyr.GetLayerDefn()for feature in layer1: geom = feature.GetGeometryRef() for feature_ in layer2: geom_ = feature_.GetGeometryRef() if geom.Intersect(geom_) == 1: out_feature = ogr.Feature(def_feature) out_feature.SetGeometry(geom_) out_lyr.CreateFeature(out_feature)out_ds.FlushCache()del dataSource1, dataSource2
def mkdir(path):
if not os.path.exists(path): os.mkdir(path)
def mainfunc(inShp, outshp, bdistance):
temproot = './temp'mkdir(temproot)fname = f'{temproot}/buffer.shp'fname2 = f'{temproot}/buffer2.shp'buffer(inShp, fname, bdistance=bdistance)max_area = area(fname)uni(fname, fname2)multipoly2poly(fname2, fname)remove_big_buffer(fname, fname2, max_area)uni(fname2, fname)intersection(fname, inShp, outshp)# remove temporary directoryif os.path.exists(temproot): shutil.rmtree(temproot)
if name == '__main__':
f = open('config_order.txt')data = f.readlines()inShp = data[0].replace('\n', '')outshp = data[1].replace('\n', '')bdistance = float(data[2].replace('\n', ''))print(inShp, outshp)mainfunc(inShp, outshp, bdistance)
config_order.txt
./data/buildings.shp
isolated_buildings.shp
0.008