Python应用指南:获取行政区最小外接矩形

有的时候我们用行政区的面层进行裁剪的时候,特别是在基于行政区裁剪的渔网,因为行政边界本身就是不规则的原因,在边界的渔网匹配数据会出现匹配不上的问题,其实如果周边有数据完全可以采用最近匹配的原则,但是就是因为行政区裁太可丁可卯了,会丢失一部分数据,这个时候可以通过形成一个最小外接矩形的形式,可以让数据裁剪保持一个微妙的范围,不至于太大,又不至于没有二次处理的空间,第二个方面就是比如我们需要行政区里面的POI,以高德为例,因为行政区本身不是规则的,我们通过建立外接矩阵,这样获取其中的数据就不会出现丢失的情况了;

行政区边界获取部分,这里采用了阿里云旗下的数据可视化平台,其数据源本身也是来着高德地图,数据质量还是比较可靠的;

全国行政区划边界GeoJSON数据下载平台阿里云:DataV.GeoAtlas地理小工具系列 (aliyun.com)

这里把下载到本地的geojson或者json的文件路径改成自己的即可;

完整代码#运行环境Python 3.11

import geopandas as gp

# 结果变量
resultMinLon = 99999.0  # 最小经度
resultMaxLon = -99999.0  # 最大经度
resultMinLat = 99999.0  # 最小纬度
resultMaxLat = -99999.0  # 最大纬度

# 读取厦门市边界数据
# 注意:请确保文件路径正确
loadGeoData = gp.read_file("D:\\data\\厦门市.json")

# 遍历每一行数据
for i in range(len(loadGeoData)):
    # 读取几何数据
    loadGeometry = loadGeoData.loc[i, "geometry"]

    # 检查几何数据类型,可能是单个多边形(Polygon)或多个多边形(MultiPolygon)
    if loadGeometry.geom_type == 'Polygon':
        # 单个多边形
        # 遍历多边形的所有顶点
        for z in range(len(loadGeometry.exterior.coords)):
            # 获取当前顶点的经度和纬度
            loadLon, loadLat = loadGeometry.exterior.coords[z]
            # 更新最小经度
            if loadLon < resultMinLon:
                resultMinLon = loadLon
            # 更新最大经度
            if loadLon > resultMaxLon:
                resultMaxLon = loadLon
            # 更新最小纬度
            if loadLat < resultMinLat:
                resultMinLat = loadLat
            # 更新最大纬度
            if loadLat > resultMaxLat:
                resultMaxLat = loadLat
    elif loadGeometry.geom_type == 'MultiPolygon':
        # 多个多边形
        # 遍历每个多边形
        for polygon in loadGeometry.geoms:
            # 遍历多边形的所有顶点
            for z in range(len(polygon.exterior.coords)):
                # 获取当前顶点的经度和纬度
                loadLon, loadLat = polygon.exterior.coords[z]
                # 更新最小经度
                if loadLon < resultMinLon:
                    resultMinLon = loadLon
                # 更新最大经度
                if loadLon > resultMaxLon:
                    resultMaxLon = loadLon
                # 更新最小纬度
                if loadLat < resultMinLat:
                    resultMinLat = loadLat
                # 更新最大纬度
                if loadLat > resultMaxLat:
                    resultMaxLat = loadLat

# 结果输出
print("厦门市最小经度:", resultMinLon)
print("厦门市最大经度:", resultMaxLon)
print("厦门市最小纬度:", resultMinLat)
print("厦门市最大纬度:", resultMaxLat)

这里会直接打印出来两个对角线坐标,另外,因为数据源是高德的,用的是(GCJ-02)坐标系,最好先转成WGS84地理坐标系或者CGCS2000地理坐标系。如果需要可视化的话,可以跑一下下面的代码,与上面的区别就是通过调用了matplotlib包,使得结果可视化;

完整代码#运行环境Python 3.11

import geopandas as gp
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle

# 配置 matplotlib 支持中文显示
plt.rcParams['font.family'] = ['SimHei']  # 使用黑体字体
plt.rcParams['axes.unicode_minus'] = False  # 正常显示负号

# 结果变量
resultMinLon = 99999.0  # 最小经度
resultMaxLon = -99999.0  # 最大经度
resultMinLat = 99999.0  # 最小纬度
resultMaxLat = -99999.0  # 最大纬度

# 读取厦门市边界数据
# 注意:请确保文件路径正确
loadGeoData = gp.read_file("D:\\data\\厦门市.json")

# 遍历每一行数据
for i in range(len(loadGeoData)):
    # 读取几何数据
    loadGeometry = loadGeoData.loc[i, "geometry"]

    # 检查几何数据类型,可能是单个多边形(Polygon)或多个多边形(MultiPolygon)
    if loadGeometry.geom_type == 'Polygon':
        # 单个多边形
        # 遍历多边形的所有顶点
        for z in range(len(loadGeometry.exterior.coords)):
            # 获取当前顶点的经度和纬度
            loadLon, loadLat = loadGeometry.exterior.coords[z]
            # 更新最小经度
            if loadLon < resultMinLon:
                resultMinLon = loadLon
            # 更新最大经度
            if loadLon > resultMaxLon:
                resultMaxLon = loadLon
            # 更新最小纬度
            if loadLat < resultMinLat:
                resultMinLat = loadLat
            # 更新最大纬度
            if loadLat > resultMaxLat:
                resultMaxLat = loadLat
    elif loadGeometry.geom_type == 'MultiPolygon':
        # 多个多边形
        # 遍历每个多边形
        for polygon in loadGeometry.geoms:
            # 遍历多边形的所有顶点
            for z in range(len(polygon.exterior.coords)):
                # 获取当前顶点的经度和纬度
                loadLon, loadLat = polygon.exterior.coords[z]
                # 更新最小经度
                if loadLon < resultMinLon:
                    resultMinLon = loadLon
                # 更新最大经度
                if loadLon > resultMaxLon:
                    resultMaxLon = loadLon
                # 更新最小纬度
                if loadLat < resultMinLat:
                    resultMinLat = loadLat
                # 更新最大纬度
                if loadLat > resultMaxLat:
                    resultMaxLat = loadLat

# 结果输出
print("厦门最小经度:", resultMinLon)
print("厦门最大经度:", resultMaxLon)
print("厦门最小纬度:", resultMinLat)
print("厦门最大纬度:", resultMaxLat)

# 可视化
fig, ax = plt.subplots(figsize=(10, 10))

# 绘制厦门市的边界
loadGeoData.plot(ax=ax, edgecolor='black', facecolor='lightblue')

# 绘制最小外接矩形
min_rect = Rectangle((resultMinLon, resultMinLat), resultMaxLon - resultMinLon, resultMaxLat - resultMinLat,
                     linewidth=2, edgecolor='red', facecolor='none', linestyle='--')
ax.add_patch(min_rect)

# 标注最小和最大经度与纬度点
ax.scatter(resultMinLon, resultMinLat, color='red', label='最小边界')
ax.scatter(resultMaxLon, resultMaxLat, color='green', label='最大边界')
ax.annotate(f'({resultMinLon:.6f}, {resultMinLat:.6f})', (resultMinLon, resultMinLat), textcoords="offset points",
            xytext=(0, 10), ha='center')
ax.annotate(f'({resultMaxLon:.6f}, {resultMaxLat:.6f})', (resultMaxLon, resultMaxLat), textcoords="offset points",
            xytext=(0, 10), ha='center')

# 添加图例
ax.legend()

# 设置坐标轴范围
ax.set_xlim(resultMinLon - 0.01, resultMaxLon + 0.01)
ax.set_ylim(resultMinLat - 0.01, resultMaxLat + 0.01)

# 显示图形
plt.title('厦门市边界及最小外接矩形')
plt.xlabel('经度')
plt.ylabel('纬度')
plt.grid(True)
plt.show()

下面这部分代码增加了一个功能:就是把这个矩形导出来,这里是把这个矩形导出来形成shp文件,修改文件路径的基础上再改一下保存位置路径即可;

完整代码#运行环境Python 3.11

import geopandas as gp
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from shapely.geometry import box

# 配置 matplotlib 支持中文显示
plt.rcParams['font.family'] = ['SimHei']  # 使用黑体字体
plt.rcParams['axes.unicode_minus'] = False  # 正常显示负号

# 结果变量
resultMinLon = 99999.0  # 最小经度
resultMaxLon = -99999.0  # 最大经度
resultMinLat = 99999.0  # 最小纬度
resultMaxLat = -99999.0  # 最大纬度

# 读取厦门市边界数据
# 注意:请确保文件路径正确
loadGeoData = gp.read_file("D:\\data\\厦门市.json")

# 遍历每一行数据
for i in range(len(loadGeoData)):
    # 读取几何数据
    loadGeometry = loadGeoData.loc[i, "geometry"]

    # 检查几何数据类型,可能是单个多边形(Polygon)或多个多边形(MultiPolygon)
    if loadGeometry.geom_type == 'Polygon':
        # 单个多边形
        # 遍历多边形的所有顶点
        for z in range(len(loadGeometry.exterior.coords)):
            # 获取当前顶点的经度和纬度
            loadLon, loadLat = loadGeometry.exterior.coords[z]
            # 更新最小经度
            if loadLon < resultMinLon:
                resultMinLon = loadLon
            # 更新最大经度
            if loadLon > resultMaxLon:
                resultMaxLon = loadLon
            # 更新最小纬度
            if loadLat < resultMinLat:
                resultMinLat = loadLat
            # 更新最大纬度
            if loadLat > resultMaxLat:
                resultMaxLat = loadLat
    elif loadGeometry.geom_type == 'MultiPolygon':
        # 多个多边形
        # 遍历每个多边形
        for polygon in loadGeometry.geoms:
            # 遍历多边形的所有顶点
            for z in range(len(polygon.exterior.coords)):
                # 获取当前顶点的经度和纬度
                loadLon, loadLat = polygon.exterior.coords[z]
                # 更新最小经度
                if loadLon < resultMinLon:
                    resultMinLon = loadLon
                # 更新最大经度
                if loadLon > resultMaxLon:
                    resultMaxLon = loadLon
                # 更新最小纬度
                if loadLat < resultMinLat:
                    resultMinLat = loadLat
                # 更新最大纬度
                if loadLat > resultMaxLat:
                    resultMaxLat = loadLat

# 结果输出
print("厦门最小经度:", resultMinLon)
print("厦门最大经度:", resultMaxLon)
print("厦门最小纬度:", resultMinLat)
print("厦门最大纬度:", resultMaxLat)

# 创建最小外接矩形的几何对象
bounding_box = box(resultMinLon, resultMinLat, resultMaxLon, resultMaxLat)

# 创建 GeoDataFrame
bbox_gdf = gp.GeoDataFrame(geometry=[bounding_box], crs=loadGeoData.crs)

# 保存为 Shapefile
output_path = "D:\\data\\厦门最小外接矩形.shp"
bbox_gdf.to_file(output_path)

# 可视化
fig, ax = plt.subplots(figsize=(10, 10))

# 绘制厦门市的边界
loadGeoData.plot(ax=ax, edgecolor='black', facecolor='lightblue')

# 绘制最小外接矩形
min_rect = Rectangle((resultMinLon, resultMinLat), resultMaxLon - resultMinLon, resultMaxLat - resultMinLat,
                     linewidth=2, edgecolor='red', facecolor='none', linestyle='--')
ax.add_patch(min_rect)

# 标注最小和最大经度与纬度点
ax.scatter(resultMinLon, resultMinLat, color='red', label='最小边界')
ax.scatter(resultMaxLon, resultMaxLat, color='green', label='最大边界')
ax.annotate(f'({resultMinLon:.6f}, {resultMinLat:.6f})', (resultMinLon, resultMinLat), textcoords="offset points",
            xytext=(0, 10), ha='center')
ax.annotate(f'({resultMaxLon:.6f}, {resultMaxLat:.6f})', (resultMaxLon, resultMaxLat), textcoords="offset points",
            xytext=(0, 10), ha='center')

# 添加图例
ax.legend()

# 设置坐标轴范围
ax.set_xlim(resultMinLon - 0.01, resultMaxLon + 0.01)
ax.set_ylim(resultMinLat - 0.01, resultMaxLat + 0.01)

# 显示图形
plt.title('厦门市边界及最小外接矩形')
plt.xlabel('经度')
plt.ylabel('纬度')
plt.grid(True)
plt.show()

忽然发现arcgis/arcgispro也可以生成这个最小外接矩形,直接检索【最小边界几何】,几何类型选择【按面积矩形】或者【按宽度矩形】都可,看需求,组选型选【ALL】这样会基于全部结果形成最外层的矩形;

结果如下;

文章仅用于分享个人学习成果与个人存档之用,分享知识,如有侵权,请联系作者进行删除。所有信息均基于作者的个人理解和经验,不代表任何官方立场或权威解读。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图说交通

买猫粮,楼下的流浪猫在等我

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值