为何调用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
相关产品推荐
相关产品推荐

