如何提取列表中满足元素对双条件的numpy数组对
问题根源
代码没有剔除任何点、返回10000个点的原因有三点:
- 判断条件缺失:你写的
conditions函数仅校验了点是否在外接矩形范围内,而生成kx时x已经被限制在[-1/√3, 1/√3],ky也已经被限制在[-2/3, 2/3],所有候选点天然满足你写的判断规则,自然掩码全为True。你完全漏掉了正六边形斜边的约束条件。 - 点生成逻辑错误:用列表推导式对
kx、ky做笛卡尔积生成的是规则网格点,不是独立随机分布的点集。 - API使用错误:
np.extract会将数组扁平化后提取元素,最终无法得到N行2列的点坐标结构。
你当前外接矩形对应的是左右边竖直、上下为顶点的正六边形,它的完整边界约束有三个:
- 左右竖直边:
|x| ≤ 1/√3 - 上下顶点边界:
|y| ≤ 2/3 - 四条斜边约束:
|x|/√3 + |y| ≤ 2/3(这是裁掉矩形四个角多余点的核心判断,也是你之前漏掉的逻辑)
修正后的拒绝采样实现
拒绝采样是实现这个需求最简单的方案,因为外接矩形内点的有效率为75%,采样效率很高:
import numpy as np from scipy import stats as sps target_count = 100 # 目标生成的六边形内点数量 valid_points = [] while len(valid_points) < target_count: # 每批生成2倍剩余所需量的候选点,减少循环次数 batch_size = (target_count - len(valid_points)) * 2 # 独立生成外接矩形内的随机x、y坐标,按下标一一配对为点 kx = 1 / np.sqrt(3) * sps.uniform.rvs(loc=-1, scale=2, size=batch_size) ky = 2 / 3 * sps.uniform.rvs(loc=-1, scale=2, size=batch_size) # 应用完整六边形约束生成掩码 mask = ( (np.abs(kx) <= 1 / np.sqrt(3)) & (np.abs(ky) <= 2 / 3) & (np.abs(kx) / np.sqrt(3) + np.abs(ky) <= 2 / 3) ) # 收集符合条件的点 valid_points.extend(zip(kx[mask], ky[mask])) # 截取刚好目标数量的点,转为numpy坐标数组 hex_points = np.array(valid_points[:target_count]) print(f"生成六边形内随机点数量:{len(hex_points)}")
其他可选方案
如果不想用拒绝采样,可以将正六边形拆分为6个以原点为公共顶点的等边三角形,先按三角形面积权重随机选择目标三角形,再在三角形内生成均匀随机点,这种方案没有点浪费,但需要额外写三角形采样逻辑,对于小规模点集场景,拒绝采样的实现成本和运行效率已经足够优。
内容的提问来源于stack exchange,提问作者goroshek
相关产品推荐
相关产品推荐

