python建立等面积缓冲区

python建立等面积缓冲区

在GIS软件里面,缓冲区的建立只能通过输入距离的方式来完成,但是我有个作业要求给特定要素生成的缓冲区面积等于原要素的面积,于是就有了下面代码,通过不断迭代来完成:

一种直观但是不太优雅的写法

python库准备

import os
import geopandas as gpd
import pandas as pd
from shapely.geometry import Polygon

定义输入和输出路径

input_folder = r'F:\UHI\提取建成区\result\input'  #输入路径
output_folder = r'F:\UHI\提取建成区\result\三倍缓冲区\total'  #输出路径

定义函数

# 遍历输入文件夹中的所有shp文件
for filename in os.listdir(input_folder):
    if filename.endswith('.shp'):
        # 读取输入文件
        input_file = gpd.read_file(os.path.join(input_folder, filename))
        print(f"~-~-~-~-~-~-~-~-~-~正在计算{filename}~-~-~-~-~-~-~-~--~")

        # 创建一个空的 GeoDataFrame 对象,用于存储所有要素的缓冲区结果
        output_gdf = gpd.GeoDataFrame()

        # 遍历所有要素
        for index, row in input_file.iterrows():
            print(f"---正在遍历第—{index}一个要素---")
            # 获取当前要素的几何图形
            geom = row['geometry']
            # 计算当前要素的面积
            area = geom.area
            # 计算需要缓冲的距离
            buffer_distance = 100   #起始距离,可以用gis简单计算一下,提高计算速度
            while Polygon(geom.buffer(buffer_distance)).area < area * 4:
                print(f"-当前第{index}个要素的缓冲区距离为{buffer_distance}-继续迭代-")
                buffer_distance += 10  #按照10m的步长进行迭代,如果你的电脑受得了的话可以改成1,精度会更高一点
            # 生成缓冲区
            buffered_geom = geom.buffer(buffer_distance)
            # 将当前要素的缓冲区转换为GeoDataFrame,并添加到输出 GeoDataFrame 对象中
            buffered_gdf = gpd.GeoDataFrame(geometry=[buffered_geom])
            output_gdf = pd.concat([output_gdf, buffered_gdf], ignore_index=True)

        # 将输出文件保存到指定路径
        output_gdf.to_file(os.path.join(output_folder, filename))

# 打印运行结束信息
print("All files processed.")

上面代码中我的输出文件和输入文件共用了一个名字,因为上面代码中输出的shp文件没有prj(投影)文件,我就简单暴力的把输入文件的prj给粘过来了

一种优雅且高效的写法

如果你不止生成一倍距离的缓冲区,还要生成不同倍数面积的缓冲区,那这样的话总不能一次一次的运行吧,更不能直接把代码复制一遍往下粘了改改路径倍数吧,所以就有了下面代码


import os
import geopandas as gpd
from shapely.geometry import Polygon

def calculate_buffer_distance(geom, factor):
    area = geom.area
    buffer_distance = 100
    while Polygon(geom.buffer(buffer_distance)).area < area * factor:
        buffer_distance += 10
    return buffer_distance

def calculate_buffer_area(input_path, output_path, factor):
    input_folder = os.path.abspath(input_path)
    output_folder = os.path.abspath(output_path)

    # 遍历输入文件夹中的所有shp文件
    for filename in (f for f in os.listdir(input_folder) if f.endswith('.shp')):
        # 读取输入文件
        input_file = gpd.read_file(os.path.join(input_folder, filename))
        print(f"正在计算{filename}...")
        # 计算缓冲区
        output_gdf = gpd.GeoDataFrame(geometry=input_file.geometry.apply(lambda geom: geom.buffer(calculate_buffer_distance(geom, factor))))

        # 将输出文件保存到指定路径
        output_gdf.to_file(os.path.join(output_folder, filename))
    # 打印运行结束信息
    print("All files processed.")

if __name__ == "__main__":
    input_path = r'F:\UHI\提取建成区\result\input'
    output_path = r'F:\UHI\提取建成区\result\三倍缓冲区\total'
    calculate_buffer_area(input_path, output_path, 4)

    input_path = r'F:\UHI\提取建成区\result\input'
    output_path = r'F:\UHI\提取建成区\result\一倍缓冲区\total'
    calculate_buffer_area(input_path, output_path, 2)

这样的话就可以一次性的生成多种倍数下的缓冲区咯,当然,直接迭代的方法有点笨,本着能让机器动手就不让自己动脑的原则,我觉得这玩意儿也能用,大家有什么好的方法的话也可以自己改写,比如二分法迭代。

你可能感兴趣的:(python,python,开发语言,numpy)