You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用GeoPandas和Folium在Python中绘制区域多边形周长问题

问题:绘制区域外围多边形时出现乱线

我尝试基于场地的经纬度点绘制外围周长多边形,但结果是一团相互连接的乱线,不是预期的外围轮廓。我的代码如下:

#Import the source data and libraries
import pandas as pd
import geopandas as gpd
import folium
from shapely.geometry import Polygon
df = pd.read_csv('tacs.csv')
#Extract the lat long lists from the datasource
lat_point_list = df['magnet.latitude'].tolist()
lon_point_list = df['magnet.longitude'].tolist()
#Some wizardry
polygon_geom = Polygon(zip(lon_point_list, lat_point_list))
crs = {'init': 'epsg:4326'}
polygon = gpd.GeoDataFrame(index=[0], crs=crs, geometry=[polygon_geom])
#output to files
polygon.to_file(filename='polygon.geojson', driver='GeoJSON')
polygon.to_file(filename='polygon.shp', driver="ESRI Shapefile")
#plot on a map with central point being birmingham
m = folium.Map([51.509865, -0.118092], zoom_start=12, tiles='cartodbpositron')
folium.GeoJson(polygon).add_to(m)
folium.LatLngPopup().add_to(m)
m

解决方案

出现乱线的核心原因是:你传入Polygon的经纬度点没有按区域外围的顺时针/逆时针顺序排列。Shapely的Polygon会严格按照给定的点顺序依次连接,点顺序混乱的话就会出现交叉、重叠的线条。

根据你的数据类型,这里提供两种针对性的解决方法:

方法一:用凸包自动生成外围轮廓(适合散点数据)

如果你的CSV里的点是区域内的散点(比如采集的多个磁测点),而非预先按顺序排列的外围边界点,最简便的方法是使用Shapely的convex_hull生成所有点的外围凸多边形:

修改代码中的多边形生成部分:

# 新增导入MultiPoint
from shapely.geometry import Polygon, MultiPoint

#Extract the lat long lists from the datasource
lat_point_list = df['magnet.latitude'].tolist()
lon_point_list = df['magnet.longitude'].tolist()

# 先将点转为MultiPoint对象,再生成凸包(外围轮廓)
points = MultiPoint(zip(lon_point_list, lat_point_list))
polygon_geom = points.convex_hull  # 这一步替换原来的Polygon生成代码

# 后续代码保持不变
crs = {'init': 'epsg:4326'}
polygon = gpd.GeoDataFrame(index=[0], crs=crs, geometry=[polygon_geom])
...

凸包会自动计算所有点的最外围边界,避免点顺序混乱带来的交叉问题。

方法二:Delaunay三角剖分提取非凸区域边界(适合凹形区域)

如果你的场地是凹形的,凸包会忽略凹进去的部分,这时候可以用Delaunay三角剖分提取精准的外围边界。需要先安装scipy库:

pip install scipy

然后修改代码:

import pandas as pd
import geopandas as gpd
import folium
from shapely.geometry import Polygon
from scipy.spatial import Delaunay
import numpy as np

df = pd.read_csv('tacs.csv')
# 先清理空值
df = df.dropna(subset=['magnet.latitude', 'magnet.longitude'])
lat_point_list = df['magnet.latitude'].tolist()
lon_point_list = df['magnet.longitude'].tolist()

# 将经纬度转为numpy数组
points_np = np.array(list(zip(lon_point_list, lat_point_list)))
# 执行Delaunay三角剖分
tri = Delaunay(points_np)

# 提取只出现一次的边(即外围边界边)
edges = set()
for simplex in tri.simplices:
    for i in range(3):
        # 对边的两个点索引排序,避免重复记录
        edge = tuple(sorted((simplex[i], simplex[(i+1)%3])))
        if edge in edges:
            edges.remove(edge)
        else:
            edges.add(edge)

# 将边界点按顺序连接成闭合多边形
current_idx = next(iter(edges))[0]
ordered_indices = [current_idx]
while edges:
    # 找到包含当前点的边
    next_edge = next((e for e in edges if current_idx in e), None)
    if not next_edge:
        break
    # 切换到边的另一个端点
    current_idx = next_edge[0] if next_edge[1] == current_idx else next_edge[1]
    ordered_indices.append(current_idx)
    edges.remove(next_edge)
# 闭合多边形
ordered_indices.append(ordered_indices[0])

# 生成最终的多边形
polygon_geom = Polygon(points_np[ordered_indices])

# 后续代码保持不变
crs = {'init': 'epsg:4326'}
polygon = gpd.GeoDataFrame(index=[0], crs=crs, geometry=[polygon_geom])
...

额外检查建议

  • 先清理数据:用df.dropna(subset=['magnet.latitude', 'magnet.longitude'])移除空值或异常点,避免干扰边界计算。
  • 如果是手动采集的外围点:确保记录点时是按顺时针/逆时针的顺序依次采集的,这样直接用Polygon(zip(...))就能得到正确的轮廓。

内容的提问来源于stack exchange,提问作者kikee1222

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:48:29