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

JavaScript实现矩形内随机点生成及分区概率分析面试题求解

矩形内随机点生成与区域概率分析(JavaScript实现)

核心思路

针对问题需求,我们分两种常见场景处理:轴对齐矩形(边平行于坐标轴)和旋转矩形(任意角度)。核心逻辑是:

  1. 生成均匀分布的随机点;
  2. 将矩形等分为4个面积相等的区域;
  3. 统计各区域的点数量,计算落入概率。

一、轴对齐矩形实现

1. 步骤解析

  • 获取矩形边界:从4个顶点中提取最小/最大x、y值,确定矩形范围;
  • 生成随机点:在x和y的范围内生成均匀随机数,得到矩形内的点;
  • 划分区域:通过x和y的中点将矩形分为4个象限区域;
  • 统计概率:计数各区域的点数量,除以总点数得到概率。

2. 代码实现

// 获取矩形的边界范围
function getRectangleBounds(vertices) {
  const xs = vertices.map(v => v.x);
  const ys = vertices.map(v => v.y);
  return {
    minX: Math.min(...xs),
    maxX: Math.max(...xs),
    minY: Math.min(...ys),
    maxY: Math.max(...ys)
  };
}

// 生成N个矩形内的随机点
function generateRandomPoints(vertices, n) {
  const { minX, maxX, minY, maxY } = getRectangleBounds(vertices);
  const points = [];
  for (let i = 0; i < n; i++) {
    const x = minX + Math.random() * (maxX - minX);
    const y = minY + Math.random() * (maxY - minY);
    points.push({ x, y });
  }
  return points;
}

// 分析随机点在各区域的分布概率
function analyzePointRegions(points, vertices) {
  const { minX, maxX, minY, maxY } = getRectangleBounds(vertices);
  const midX = (minX + maxX) / 2;
  const midY = (minY + maxY) / 2;
  
  const counts = { p1: 0, p2: 0, p3: 0, p4: 0 };
  
  points.forEach(point => {
    if (point.x <= midX && point.y <= midY) counts.p1++;
    else if (point.x > midX && point.y <= midY) counts.p2++;
    else if (point.x <= midX && point.y > midY) counts.p3++;
    else counts.p4++;
  });
  
  const total = points.length;
  return {
    counts,
    probabilities: {
      p1: counts.p1 / total,
      p2: counts.p2 / total,
      p3: counts.p3 / total,
      p4: counts.p4 / total
    }
  };
}

// 示例使用
const axisAlignedVertices = [
  { x: 0, y: 0 }, // A
  { x: 4, y: 0 }, // B
  { x: 4, y: 2 }, // C
  { x: 0, y: 2 }  // D
];
const N = 10000;

const randomPoints = generateRandomPoints(axisAlignedVertices, N);
const result = analyzePointRegions(randomPoints, axisAlignedVertices);

console.log("各区域点数量:", result.counts);
console.log("各区域落入概率:", result.probabilities);

二、旋转矩形实现

1. 步骤解析

  • 计算矩形中心:取4个顶点坐标的平均值;
  • 生成随机点:通过仿射变换,将旋转矩形映射为单位正方形,生成随机点后再变换回原矩形;
  • 划分区域:通过矩形中心绘制两条平行于矩形边的中线,将矩形分为4个全等区域;
  • 统计概率:利用向量点积判断点位于中线的哪一侧,计数后计算概率。

2. 代码实现

// 生成旋转矩形内的随机点
function generateRotatedRectanglePoints(vertices, n) {
  // 计算矩形中心
  const center = {
    x: vertices.reduce((sum, v) => sum + v.x, 0) / 4,
    y: vertices.reduce((sum, v) => sum + v.y, 0) / 4
  };
  
  // 获取相邻顶点的边向量
  const A = vertices[0];
  const B = vertices[1];
  const D = vertices[3];
  const vecAB = { x: B.x - A.x, y: B.y - A.y };
  const vecAD = { x: D.x - A.x, y: D.y - A.y };
  
  // 计算边的半长和单位向量
  const halfLengthAB = Math.hypot(vecAB.x, vecAB.y) / 2;
  const halfLengthAD = Math.hypot(vecAD.x, vecAD.y) / 2;
  const normAB = { x: vecAB.x / (2 * halfLengthAB), y: vecAB.y / (2 * halfLengthAB) };
  const normAD = { x: vecAD.x / (2 * halfLengthAD), y: vecAD.y / (2 * halfLengthAD) };
  
  const points = [];
  for (let i = 0; i < n; i++) {
    // 生成[-1,1]范围内的随机系数
    const u = Math.random() * 2 - 1;
    const v = Math.random() * 2 - 1;
    // 计算点坐标
    const x = center.x + u * halfLengthAB * normAB.x + v * halfLengthAD * normAD.x;
    const y = center.y + u * halfLengthAB * normAB.y + v * halfLengthAD * normAD.y;
    points.push({ x, y });
  }
  return points;
}

// 分析旋转矩形内各区域的点分布概率
function analyzeRotatedRectangleRegions(points, vertices) {
  const center = {
    x: vertices.reduce((sum, v) => sum + v.x, 0) / 4,
    y: vertices.reduce((sum, v) => sum + v.y, 0) / 4
  };
  
  const A = vertices[0];
  const B = vertices[1];
  const D = vertices[3];
  const vecAB = { x: B.x - A.x, y: B.y - A.y };
  const vecAD = { x: D.x - A.x, y: D.y - A.y };
  
  // 边的法向量,用于判断点的位置
  const normalAB = { x: -vecAB.y, y: vecAB.x };
  const normalAD = { x: -vecAD.y, y: vecAD.x };
  
  const counts = { p1: 0, p2: 0, p3: 0, p4: 0 };
  
  points.forEach(point => {
    const delta = { x: point.x - center.x, y: point.y - center.y };
    const dotAB = delta.x * normalAB.x + delta.y * normalAB.y;
    const dotAD = delta.x * normalAD.x + delta.y * normalAD.y;
    
    if (dotAB <= 0 && dotAD <= 0) counts.p1++;
    else if (dotAB > 0 && dotAD <= 0) counts.p2++;
    else if (dotAB <= 0 && dotAD > 0) counts.p3++;
    else counts.p4++;
  });
  
  const total = points.length;
  return {
    counts,
    probabilities: {
      p1: counts.p1 / total,
      p2: counts.p2 / total,
      p3: counts.p3 / total,
      p4: counts.p4 / total
    }
  };
}

// 示例使用
const rotatedVertices = [
  { x: 1, y: 0 }, // A
  { x: 3, y: 2 }, // B
  { x: 1, y: 4 }, // C
  { x: -1, y: 2 } // D
];
const rotatedPoints = generateRotatedRectanglePoints(rotatedVertices, N);
const rotatedResult = analyzeRotatedRectangleRegions(rotatedPoints, rotatedVertices);

console.log("旋转矩形各区域点数量:", rotatedResult.counts);
console.log("旋转矩形各区域落入概率:", rotatedResult.probabilities);

关键说明

  • 当N足够大时,各区域的落入概率会趋近于0.25,因为每个区域面积相等且点是均匀分布的;
  • 轴对齐矩形的实现更简单高效,适合大多数常见场景;旋转矩形的实现通过向量运算保证了点严格在矩形内部。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 12:35:31