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

在p5.js中计算圆/椭圆弦长时出现异常结果的问题

在p5.js中计算圆/椭圆的弦长

嘿,我来帮你梳理一下在p5.js里计算圆或椭圆范围内弦长的具体实现思路,刚好之前做图形相关项目时折腾过类似的需求!

核心参数与基础原理

先明确你提到的两个关键参数:

  • values:HSB颜色三元组,这个主要用来后续绘图上色,和弦长计算逻辑关联不大,咱们重点看size
  • size:图形的宽高,如果是正圆,那宽高相等,半径r = size / 2;如果是椭圆,那size可以拆成[width, height],对应长半轴a = size[0]/2,短半轴b = size[1]/2

弦长的计算核心是几何定理:

  • 对于正圆:已知当前纵坐标y(相对于圆心的偏移量),半弦长halfChord = sqrt(r² - y²),完整弦长就是2 * halfChord
  • 对于椭圆:半弦长公式是halfChord = (a/b) * sqrt(b² - y²),完整弦长同样是2 * halfChord

p5.js代码实现示例

下面给你写个可直接运行的示例,包含正圆和椭圆两种情况的弦长计算:

function setup() {
  createCanvas(600, 400);
  colorMode(HSB);
  // 示例参数:HSB颜色 + 圆/椭圆尺寸
  const values = [200, 80, 70]; // 蓝紫色调
  const circleSize = 300; // 正圆尺寸
  const ellipseSize = [400, 200]; // 椭圆尺寸(宽,高)
}

function draw() {
  background(20);
  const values = [200, 80, 70];
  const circleSize = 300;
  const ellipseSize = [400, 200];

  // 绘制正圆并计算每一行的弦长
  drawShapeWithChords('circle', circleSize, values, 100, 200);
  // 绘制椭圆并计算每一行的弦长
  drawShapeWithChords('ellipse', ellipseSize, values, 400, 200);
}

// 通用绘制函数:根据图形类型计算弦长并可视化
function drawShapeWithChords(type, size, hsb, centerX, centerY) {
  fill(hsb[0], hsb[1], hsb[2], 30);
  stroke(hsb[0], hsb[1], hsb[2]);
  strokeWeight(1);

  // 绘制基础图形
  if (type === 'circle') {
    ellipse(centerX, centerY, size, size);
  } else if (type === 'ellipse') {
    ellipse(centerX, centerY, size[0], size[1]);
  }

  // 遍历y轴方向的每个点,计算对应弦长
  strokeWeight(2);
  const step = 5; // 遍历步长,越小越精细
  let radius, a, b;
  if (type === 'circle') {
    radius = size / 2;
  } else {
    a = size[0] / 2;
    b = size[1] / 2;
  }

  for (let y = centerY - (type === 'circle' ? radius : b); y <= centerY + (type === 'circle' ? radius : b); y += step) {
    // 计算当前y相对于圆心的偏移量
    const yOffset = y - centerY;
    let halfChord = 0;

    // 核心弦长计算逻辑,避免根号内出现负数
    if (type === 'circle') {
      if (Math.abs(yOffset) <= radius) {
        halfChord = Math.sqrt(radius * radius - yOffset * yOffset);
      }
    } else {
      if (Math.abs(yOffset) <= b) {
        halfChord = (a / b) * Math.sqrt(b * b - yOffset * yOffset);
      }
    }

    // 绘制当前弦
    stroke(hsb[0], hsb[1], hsb[2], 80);
    line(centerX - halfChord, y, centerX + halfChord, y);
    
    // 可选:在弦上标注弦长数值
    fill(255);
    noStroke();
    text(Math.round(halfChord * 2), centerX, y);
    stroke(hsb[0], hsb[1], hsb[2], 80);
  }
}

关键细节提醒

  • 边界判断:一定要加Math.abs(yOffset) <= 半径/短半轴的判断,否则当y超出图形范围时,根号内会出现负数,导致NaN错误
  • 椭圆适配:椭圆的弦长公式和圆不同,需要用长半轴和短半轴的比例来修正,别直接套用圆的公式
  • 步长控制:step参数决定了遍历的精细度,数值越小弦越多越密集,根据你的需求调整就行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:14:52