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

如何沿大圆周排布无重叠子圆 并实现对应TypeScript功能

实现思路
  • 每个子圆的圆心到大圆圆心的固定距离为大圆圆半径 - 当前子圆半径,保证子圆外边缘贴合大圆圆周
  • 用余弦定理计算相邻子圆圆心的夹角:相邻两子圆圆心距离为两者半径之和,结合两者到大圆圆心的距离,可求出两者的中心夹角
  • 对所有夹角做等比例缩放,使总夹角刚好等于2π(一整圈),保证子圆均匀分布且无重叠
  • 从初始角度开始累加缩放后的夹角,用三角函数计算每个子圆的x、y坐标
完整实现代码
interface Circle {
  radius: number;
  x: number;
  y: number;
}

const childRadii = [1, 3, 2, 5, 1, 2];
const largeCircle = { radius: 10, x: 0, y: 0 };
const arrangedCircles = positionCirclesOnCircle(largeCircle, childRadii);

function positionCirclesOnCircle(
  largeCircle: Circle,
  radii: number[]
): Circle[] {
  const arrangedCircles: Circle[] = [];
  const count = radii.length;
  if (count === 0) return arrangedCircles;

  // 每个子圆圆心到大圆圆心的距离
  const d = radii.map(r => largeCircle.radius - r);
  // 存储相邻子圆的基础夹角
  const thetas: number[] = [];

  for (let i = 0; i < count; i++) {
    const nextI = (i + 1) % count;
    const a = d[i];
    const b = d[nextI];
    const c = radii[i] + radii[nextI];
    // 余弦定理计算夹角,限制cos值范围避免浮点数精度导致的计算错误
    let cosTheta = (a * a + b * b - c * c) / (2 * a * b);
    cosTheta = Math.min(Math.max(cosTheta, -1), 1);
    thetas.push(Math.acos(cosTheta));
  }

  // 计算缩放系数,让总夹角刚好为2π
  const sumTheta = thetas.reduce((sum, t) => sum + t, 0);
  const scale = (2 * Math.PI) / sumTheta;

  // 计算每个子圆坐标,currentAngle可自行调整起始偏移,比如- Math.PI / 2表示从正上方开始排布
  let currentAngle = 0;
  for (let i = 0; i < count; i++) {
    const x = largeCircle.x + d[i] * Math.cos(currentAngle);
    const y = largeCircle.y + d[i] * Math.sin(currentAngle);
    arrangedCircles.push({
      radius: radii[i],
      x,
      y
    });
    currentAngle += thetas[i] * scale;
  }

  return arrangedCircles;
}

可选调整:如果需要所有子圆的圆心都在同一个圆周上,可将d的计算改为const fixedD = largeCircle.radius - Math.max(...radii),所有子圆统一用fixedD计算坐标即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 12:06:00