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

为何调用smallestRectColEdge后P5.js随机向量生成器出现NaN?

问题:P5.js调用最小外接矩形函数后点向量变为NaN

我正在用P5.js开发随机点云生成算法,当取消setup()中smallestRectColEdge(hull)的注释时,generatePoints()生成的部分点向量x、y值会变成NaN;注释该函数则一切正常。已排查drawConvexHull()无问题,问题大概率出在smallestRectColEdge()中。

相关代码

点生成函数generatePoints

function generatePoints(amount) {
  function generatePoints(amount) {
  let points = []
  for(let i = 0; i < amount; i++) {
    let px = int(random(-width/4, width/4))
    let py = int(random(-height/4, height/4))
    print(px, py)
    let myPoint = createVector(px, py)
    print(myPoint)
    circle(px, py, 3)
    points.push(myPoint)
  }
  }
  return points
}

setup()函数

function setup() {
  createCanvas(400, 400);
  translate(offsetX,offsetY)
  background(220)
  let points = generatePoints(10)
  let hull = drawConvexHull(points)
  print(hull)
  //smallestRectColEdge(hull)
}

smallestRectColEdge()函数

function smallestRectColEdge(hull){
  print(hull)
  angleMode(DEGREES)
  let angles = []
  let rotatedHulls = []
  let OBBs = []
  let smallestOBB
  
  // 获取凸包边的旋转角度
  for(let i = 0; i < hull.length; i++) {
    let angle = 0
    let diff = 0
    if(i < hull.length-1) {
      diff = p5.Vector.sub(hull[i+1], hull[i])
    } else {
      diff = p5.Vector.sub(hull[i], hull[0])
    }
    diff.normalize()
    angle = atan2(diff)
    
    let rotations = {
      rotAngle: angle,
      locAx: [diff, createVector(-diff.y, diff.x)]
    }
    
    angles.push(rotations)
  }
  
  // 旋转凸包并生成外接矩形
  for(i = 0; i < angles.length; i++) {
    let minX = 400
    let minY = 400
    let maxX = -400
    let maxY= -400
    let rotatedHull = [...hull]
    
    // 旋转凸包点
    rotatedHull.forEach((myPoint)=>{
      myPoint.rotate(angles[i].rotAngle)
    })
    
    // 计算轴对齐包围盒的极值
    rotatedHull.forEach((myPoint)=>{
      if(minX > myPoint.x) {minX = myPoint.x}
      else if(maxX < myPoint.x) {maxX = myPoint.x}
      if(minY > myPoint.Y) {minY = myPoint.Y}
      else if(maxY < myPoint.y) {maxY = myPoint.y}
    })
    
    // 存储外接矩形信息
    let OBB = {
      mins: createVector(minX, minY),
      maxes: createVector(maxX, maxY),
      u: maxX-minX,
      v: maxY-minY,
      locAx: angles[i].locAx,
      area: (maxX-minX) * (maxY-minY)
    }
    
    OBBs.push(OBB)
  }
}

问题根源与修复方案

1. generatePoints函数嵌套错误

内层同名函数未被调用,外层直接返回未定义的points变量,导致逻辑混乱。修复后移除嵌套:

function generatePoints(amount) {
  let points = []
  for(let i = 0; i < amount; i++) {
    let px = int(random(-width/4, width/4))
    let py = int(random(-height/4, height/4))
    print(px, py)
    let myPoint = createVector(px, py)
    print(myPoint)
    circle(px, py, 3)
    points.push(myPoint)
  }
  return points
}

2. atan2参数错误

P5.js的atan2()需要传入y和x两个参数,直接传入向量会导致角度计算为NaN,进而让旋转后的点变为NaN。修复:

angle = atan2(diff.y, diff.x);

3. 属性大小写错误

计算minY/maxY时误用myPoint.Y(大写Y),而p5.Vector的属性是小写y,导致极值计算失效。修复:

if(minY > myPoint.y) {minY = myPoint.y}
else if(maxY < myPoint.y) {maxY = myPoint.y}

4. 浅拷贝导致原向量被修改

rotatedHull = [...hull]是浅拷贝,旋转时直接修改原hull中的向量引用,进而污染原始点数组。修复为创建向量副本再旋转:

let rotatedHull = hull.map(myPoint => {
  let copy = myPoint.copy();
  copy.rotate(angles[i].rotAngle);
  return copy;
});

5. 循环变量未声明

第二个for循环的i未用let声明,会成为全局变量引发潜在问题。修复:

for(let i = 0; i < angles.length; i++) {
  // 原有代码
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 05:42:03