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

Python计算非均匀顶点密度多边形的面积与重心方法

核心问题说明

直接对边界点集取坐标平均计算重心,本质是计算离散点的质心,结果天然会向点密度更高的区域偏移,和你需要的城镇多边形面状重心不是同一个概念,完全不需要通过均衡点密度的方式绕路解决。
你之前写的重采样代码存在两个明确bug,才会出现局部点密度过高、部分区域留空白的问题:

  • 遍历原始边界点时步长设为j = j+2,直接跳过了一半相邻顶点构成的边界段,自然会出现点位空白
  • 重采样完成后又将原始x、y坐标列表整体追加到新点集中,相当于把原始所有点重复加入了一次,原本点密集的区域密度会进一步升高
  • 逐字符拆分读取坐标的逻辑鲁棒性极差,很容易因为空格、换行的格式问题出现坐标解析错误。
最优方案:直接使用多边形面状重心标准公式

计算几何中已有成熟的闭合多边形重心计算公式,只需要按轮廓顺序排列的多边形顶点即可计算,完全不依赖边界点密度,结果仅由多边形边的位置决定,不需要单独构建边数据库,计算复杂度为O(n),精度远高于点重采样后平均的方案。

公式原理

将多边形拆分为若干以坐标原点为公共顶点的三角形,分别计算每个三角形的面积与重心,再按面积加权平均即可得到整个多边形的重心,公式如下:
对于顶点按顺序排列的闭合多边形$(x_0,y_0), (x_1,y_1), ..., (x_{n-1},y_{n-1}), (x_0,y_0)$:

  1. 面积修正项 $A_i = x_i y_{i+1} - x_{i+1} y_i$
  2. 多边形总面积 $A = 0.5 * \sum_{i=0}^{n-1} A_i$
  3. 重心坐标 $C_x = \frac{1}{6A}\sum_{i=0}^{n-1} (x_i + x_{i+1})A_i$,$C_y = \frac{1}{6A}\sum_{i=0}^{n-1} (y_i + y_{i+1})A_i$

代码实现

纯numpy实现版本,无额外依赖:

import numpy as np

def polygon_centroid(vertices):
    """
    参数vertices: N行2列的numpy数组,每行为按轮廓顺序排列的多边形顶点(x,y)坐标,需闭合
    返回: (重心x坐标, 重心y坐标, 多边形面积)
    """
    x = vertices[:, 0]
    y = vertices[:, 1]
    area_term = x[:-1] * y[1:] - x[1:] * y[:-1]
    area = 0.5 * np.sum(area_term)
    cx = np.sum((x[:-1] + x[1:]) * area_term) / (6 * area)
    cy = np.sum((y[:-1] + y[1:]) * area_term) / (6 * area)
    return cx, cy, abs(area)

# 读取边界点示例
points = []
with open("borderpoints.txt", "r", encoding="utf8") as f:
    for line in f:
        line = line.strip()
        if not line:
            continue
        x_val, y_val = map(float, line.split())
        points.append((x_val, y_val))
# 补全闭合点
points.append(points[0])
vertices_arr = np.array(points)
cx, cy, poly_area = polygon_centroid(vertices_arr)
print(f"多边形重心坐标:x={cx:.6f}, y={cy:.6f}, 面积={poly_area:.2f}")

如果可以安装第三方空间计算库,直接用shapely的内置方法即可,鲁棒性更高,原生支持带内环(洞)的多边形:

from shapely.geometry import Polygon
poly = Polygon(points)
centroid = poly.centroid
print(f"重心坐标:x={centroid.x:.6f}, y={centroid.y:.6f}")

注意事项

  • 传入的顶点必须沿城镇轮廓按顺时针或逆时针连续排列,不能是乱序点,否则计算结果完全错误
  • 如果城镇轮廓包含不属于城镇范围的内环(如内部水域、绿地),只需要在构造多边形时传入内环顶点列表即可,上述shapely方案直接支持,手动实现公式时只需对内环的面积项取负加权即可。
备选:边界点等间隔重采样方法

如果后续其他场景必须使用沿边界均匀分布的点集,修正原有代码的逻辑即可:

  • 将遍历原始边界段的步长从j = j+2改为j += 1,逐段处理所有相邻顶点构成的边,不要跳段
  • 删除代码末尾newxs.append(x)、newys.append(y)两行,不要重复追加原始点集
  • 改为沿边界累计周长等间隔取点,避免每段单独插值导致的段首尾点重复
    注意:即便完成了完美的等间隔点重采样,对点集取平均得到的也只是边界线的质心,不是多边形面的重心,和你需要的城镇轮廓重心结果会存在固定偏差,不建议用这种方案计算重心。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 18:36:51