首页 GIS基础理论 Python计算泰森多边形?Voronoi咋画?

Python计算泰森多边形?Voronoi咋画?

作者: GIS研习社 更新时间:2025-12-19 18:00:56 分类:GIS基础理论

为什么你的Voronoi图总画歪?别急,先搞懂“势力范围”怎么算

上周一个研究生私信我:“Dr. Gis,我用Python画泰森多边形,结果生成的图边界乱飞,跟点位完全对不上!”——这太常见了。很多人一上来就调scipy.spatial.Voronoi,却忽略了最根本的问题:你给的点坐标是地理坐标还是投影坐标?边界框设对了吗?我在参与某市15分钟生活圈评估项目时,就因为没统一投影,导致服务区划分错位300米,差点让整个分析报废。

Python计算泰森多边形?Voronoi咋画?

泰森多边形(Voronoi Diagram)本质是“势力范围”划分——每个点拥有离它最近的所有区域。就像奶茶店老板的地盘:顾客总会去最近的那家,于是城市就被无形划成了若干“奶茶势力区”。

剥开Voronoi的数学橘子皮:原理其实超直观

想象你在地图上撒了一把糖豆(点),然后往地上倒彩色墨水。每颗糖豆会“吸走”离自己最近的墨水,最终每颗糖豆都被一片专属颜色包围——这就是Voronoi图。数学上,它是通过计算“垂直平分线”的交点来划分边界的。但注意:这个算法默认在“无限平面”上运行,而你的研究区往往是有限的(比如一个省、一个市)。所以必须手动裁剪边界,否则你会得到延伸到天边的锯齿状多边形。

三步实战:从零画出带边界的泰森图(附避坑指南)

我们用真实案例:某城市10个地铁站的服务范围划分。数据是WGS84坐标(经纬度),目标输出是带行政边界的规范多边形。

import numpy as np
import geopandas as gpd
from scipy.spatial import Voronoi, voronoi_plot_2d
from shapely.geometry import Polygon, Point
import matplotlib.pyplot as plt

# 步骤1:准备点数据(假设df是包含geometry列的GeoDataFrame)
points = np.array([[pt.x, pt.y] for pt in df.geometry])

# 步骤2:生成原始Voronoi图(注意!此时无边界裁剪)
vor = Voronoi(points)

# 关键步骤3:用研究区边界裁剪(假设boundary是shapely.Polygon)
def clip_voronoi(vor, boundary):
    regions = []
    for region in vor.regions:
        if not -1 in region and len(region)>0:  # 排除无限区域
            polygon = Polygon([vor.vertices[i] for i in region])
            if polygon.is_valid and boundary.intersects(polygon):
                clipped = polygon.intersection(boundary)
                if not clipped.is_empty:
                    regions.append(clipped)
    return regions

clipped_polygons = clip_voronoi(vor, boundary)
# 转为GeoDataFrame便于导出
result_gdf = gpd.GeoDataFrame({'geometry': clipped_polygons}, crs=df.crs)

高频报错解决方案:

  • 报错“QH6214 qhull input error”:点坐标有重复或共线。用np.unique(points, axis=0)去重。
  • 图形显示不全:Voronoi默认只画有限区域。用voronoi_plot_2d(vor, show_vertices=False, line_colors='blue')可预览结构。
  • 投影变形严重:务必先转投影坐标系!WGS84直接算会导致距离失真。推荐用UTM或Albers等距投影。

进阶技巧:当点太密或边界太复杂时怎么办?

去年帮某国土局做基本农田保护单元划分,遇到2000+个监测点。直接跑Voronoi内存爆炸。我的解法:分块计算+缓冲区融合。先把研究区分成5km×5km网格,在每个网格内独立计算Voronoi,最后用unary_union合并。虽然边界处略有误差,但效率提升10倍,且肉眼不可辨。

方法对比适用场景精度损失
全局计算点数<1000,边界简单
分块计算点数>5000,复杂边界<2%

总结:画对Voronoi的三个铁律

记住我的血泪经验:1)坐标系统一(投影!投影!投影!);2)边界必须裁剪(否则结果无意义);3)大数据量要分治。现在轮到你了——把你遇到的Voronoi奇葩报错贴在评论区,我抽三个典型问题直播debug!

相关文章