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

如何使用Python/Numpy在原点居中的八边形内均匀采样二维点

正多边形内均匀采样二维点(以八边形为例,可推广)

你的代码思路可行,但max_radii的计算有误,导致图形边缘出现弯曲。下面提供两种解决方案,第二种可直接推广至任意正多边形(如十六边形)。

方案一:修正极坐标法(针对八边形)

若要生成外接圆半径为1的正八边形(顶点到原点距离为1),正确的最大半径计算需先将角度映射到单个扇区,再计算相对于扇区对称轴的偏移,最终通过余弦关系推导半径。修正后的代码如下:

import numpy as np
import matplotlib.pyplot as plt

def sample_within_octagon(num_points):
    # 生成随机角度
    angles = np.random.uniform(0, 2 * np.pi, size=num_points)
    # 正八边形单个扇区的角度:2π/8 = π/4
    sector_angle = np.pi / 4
    # 将角度映射到首个扇区[0, π/4),再计算相对于扇区对称轴的偏移
    phi = angles % sector_angle - sector_angle / 2
    # 计算对应角度的最大半径
    max_radii = 1 / np.cos(phi)
    # 生成均匀分布的半径(用sqrt避免中心区域点过于密集)
    radii = np.sqrt(np.random.uniform(0, max_radii**2, size=num_points))
    # 极坐标转笛卡尔坐标
    x = radii * np.cos(angles)
    y = radii * np.sin(angles)
    return np.column_stack((x, y))

# 测试采样效果
num_points = 10000
points = sample_within_octagon(num_points)
plt.scatter(points[:, 0], points[:, 1], s=1)
plt.axis('equal')
plt.show()

方案二:通用正多边形采样法(支持任意边数)

该方法可直接适配正十六边形、正三角形等任意正多边形,核心逻辑是在单个等腰三角形扇区内均匀采样,再旋转复制到所有扇区:

import numpy as np
import matplotlib.pyplot as plt

def sample_regular_polygon(num_points, n_sides, radius=1):
    # 单个扇区的中心角
    sector_angle = 2 * np.pi / n_sides
    # 正多边形的内切圆半径(中心到边的距离)
    apothem = radius * np.cos(np.pi / n_sides)
    
    # 分配每个扇区的采样点数
    points_per_sector = num_points // n_sides
    remaining = num_points % n_sides
    total_points = points_per_sector * n_sides + remaining
    
    points = np.zeros((total_points, 2))
    
    # 生成单个扇区的采样点(利用对称性,先采一半再镜像)
    sample_count = points_per_sector + (1 if remaining > 0 else 0)
    # 沿对称轴方向采样x
    x = np.random.uniform(0, apothem, size=sample_count)
    # 垂直对称轴方向的y最大值由x决定,确保点在扇区内
    y = np.random.uniform(0, x * np.tan(np.pi / n_sides))
    # 生成对称点,组成完整扇区
    sector_points = np.vstack((np.column_stack((x, y)), np.column_stack((x, -y))))
    
    # 旋转复制到所有扇区
    idx = 0
    for k in range(n_sides):
        rot_angle = k * sector_angle
        # 旋转矩阵
        rot_matrix = np.array([
            [np.cos(rot_angle), -np.sin(rot_angle)],
            [np.sin(rot_angle), np.cos(rot_angle)]
        ])
        # 旋转并写入结果数组
        rotated_points = sector_points @ rot_matrix
        points[idx:idx+len(rotated_points)] = rotated_points
        idx += len(rotated_points)
    
    # 缩放至目标外接圆半径
    points *= radius / apothem
    
    return points

# 测试正八边形
num_points = 10000
octagon_points = sample_regular_polygon(num_points, n_sides=8, radius=1)
plt.scatter(octagon_points[:, 0], octagon_points[:, 1], s=1)
plt.axis('equal')
plt.show()

# 测试正十六边形
hexadecagon_points = sample_regular_polygon(num_points, n_sides=16, radius=1)
plt.scatter(hexadecagon_points[:, 0], hexadecagon_points[:, 1], s=1)
plt.axis('equal')
plt.show()

方案优势:

  • 完全通用,仅需修改n_sides参数即可生成任意正多边形内的均匀点;
  • 采样逻辑直观,避免极坐标下的角度计算误差;
  • 点分布均匀,不会出现边缘弯曲问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 14:33:20