JavaScript生成圆内随机点时如何排除指定点位
圆内随机点排除指定点位的调整方案
实际业务场景中我们一般默认排除的是指定点位为中心的固定半径范围内的所有点,纯数学意义上的单个离散点被随机命中的概率为0,如果你需要排除精确点位,只需将下面的排除半径设置为极小值(如1e-6)即可。
实现方案:拒绝采样法(最易实现,适合绝大多数场景)
该方案逻辑简单,直接在原有生成逻辑基础上增加合规校验,只要排除区域占大圆总面积比例不超过30%,性能完全可以满足普通需求,修改后的代码如下:
// 新增参数 excludedPoints:要排除的区域数组,每项格式为 {x: 排除点x坐标, y: 排除点y坐标, radius: 排除范围半径} function randomCirclePoint(circleRadius, circleX, circleY, excludedPoints = []) { let x, y; // 循环采样直到生成符合要求的点 while (true) { const ang = Math.random() * 2 * Math.PI, hyp = Math.sqrt(Math.random()) * circleRadius, adj = Math.cos(ang) * hyp, opp = Math.sin(ang) * hyp; x = circleX + adj; y = circleY + opp; // 校验生成的点是否在所有排除区域外 let isValid = true; for (const exclude of excludedPoints) { const dx = x - exclude.x; const dy = y - exclude.y; // 用距离平方对比避免开方运算,性能更优 if (dx*dx + dy*dy < exclude.radius * exclude.radius) { isValid = false; break; } } if (isValid) break; } return {x, y} } // 调用示例:在圆心(0,0)半径200的圆内生成点,同时排除(100,100)半径5的区域、(200,200)半径3的区域 const position = randomCirclePoint(200, 0, 0, [ {x: 100, y: 100, radius: 5}, {x: 200, y: 200, radius: 3} ]); const x = position.x; const y = position.y;
如果你需要排除的区域占大圆总面积比例超过40%,拒绝采样可能出现多次无效循环,这时可以改用权重映射法:先计算大圆可用区域的总面积,把随机值映射到可用区域上生成点位,避免无效循环。
内容的提问来源于stack exchange,提问作者DarePhoenix
相关产品推荐
相关产品推荐

