如何用P5.js的p5Vector方法实现向量运算跟踪点关系?
用P5.js p5Vector实现网格点比例映射的向量运算优化
问题背景
当前通过标量运算跟踪点之间的比例关系,虽能实现功能,但希望改用更简洁高效的向量运算。现需将拆解向量的标量计算逻辑,替换为直接使用p5Vector内置方法的实现方式。
优化后的代码
let r, g, b; // 绿色网格顶点 let p0, p1, p2, p3; // 红色网格顶点 let p00, p10, p20, p30; // 网格边距 let marginx = 10, marginy = 10; // 参考点 let refp; let green_grid = [], red_grid = []; let newbase = 30; function setup() { createCanvas(400, 400); // 定义颜色 g = color(40, 220, 40); r = color(255, 40, 40); b = color(40, 40, 220); // 初始化绿色网格向量 p0 = createVector(marginx, marginy); p3 = createVector(width - marginx, height - marginy); p1 = p0.copy().setX(p3.x); p2 = p0.copy().setY(p3.y); // 初始化红色网格向量 p00 = p0.copy(); p30 = createVector(width - marginx - newbase, height - marginy - newbase); p10 = p00.copy().setX(p30.x); p20 = p00.copy().setY(p30.y); // 初始化参考点 refp = createVector(100, 200); // 存储网格顶点 green_grid = [p0, p1, p2, p3]; red_grid = [p00, p10, p20, p30]; // ---------- 核心向量运算部分 ---------- // 计算绿色网格的尺寸向量(宽高) const greenSize = p3.copy().sub(p0); // 计算参考点相对于绿色网格原点的偏移向量 const refOffset = refp.copy().sub(p0); // 计算x、y方向的比例向量 const ratio = refOffset.copy().div(greenSize); // 计算红色网格的尺寸向量 const redSize = p30.copy().sub(p00); // 根据比例计算红色网格中对应的映射点 const proppoint = redSize.copy().mult(ratio).add(p00); // ------------------------------------- // ---------- 辅助向量(用于绘制) ---------- const xax = refp.copy().setY(p0.y); const yax = refp.copy().setX(p0.x); const xaxis = proppoint.copy().setY(p0.y); const yaxis = proppoint.copy().setX(p0.x); // ---------------------------------------- // 绘制逻辑(与原代码一致) background(121); points_D(green_grid, r); points_D([refp], r); points_D(red_grid, r); // 绘制绿色网格 push(); stroke(40, 255, 40); strokeWeight(2.5); pvline(p0, p1); pvline(p1, p3); pvline(p2, p3); pvline(p0, p2); pop(); // 绘制红色网格 push(); stroke(255, 40, 40); pvline(p00, p10); pvline(p10, p30); pvline(p20, p30); pvline(p00, p20); pop(); // 绘制参考点到绿色网格顶点的连线 push(); stroke(40, 40, 220); pvline(p3, refp); pvline(p1, refp); pop(); // 绘制参考点到坐标轴的垂线 push(); stroke('black'); pvline(refp, xax); pvline(refp, yax); pop(); // 绘制映射点及相关连线 push(); points_D([proppoint], 'white'); stroke('white'); pvline(proppoint, p10); pvline(proppoint, p30); stroke('black'); pvline(proppoint, xaxis); pvline(proppoint, yaxis); pop(); // 输出调试信息 console.log(`原始x比例= ${ratio.x} 映射点x坐标= ${proppoint.x} 映射点x/红色网格宽度= ${(proppoint.x - p00.x)/redSize.x} 原始y比例= ${ratio.y} 映射点y坐标= ${proppoint.y} 映射点y/红色网格高度= ${(proppoint.y - p00.y)/redSize.y}`); // 绘制文本说明 push() noStroke(); text(`原始x比例= ${ratio.x.toFixed(3)} 映射点x坐标= ${proppoint.x.toFixed(1)} 映射点x/红网格宽= ${((proppoint.x - p00.x)/redSize.x).toFixed(3)} 原始y比例= ${ratio.y.toFixed(3)} 映射点y坐标= ${proppoint.y.toFixed(1)} 映射点y/红网格高= ${((proppoint.y - p00.y)/redSize.y).toFixed(3)}`, 180, 100); text('黑色线段分别对应绿色和红色网格的比例关系', refp.x - 80, refp.y + 40); stroke(0); fill(255,50); rect(180, 90, 195, 90); rect(refp.x - 82, refp.y + 30, 195, 31); ellipse(refp.x - 40, refp.y -4,4); line(refp.x - 40, refp.y -4, refp.x - 80,refp.y + 30); pop(); } // 批量绘制向量点 function points_D(p5vs, c) { push(); noFill(); stroke(c); for (const p5v of p5vs) { ellipse(p5v.x, p5v.y, 7); } pop(); } // 通过向量绘制线段 function pvline(pv1, pv2) { line(pv1.x, pv1.y, pv2.x, pv2.y); }
关键向量运算解析
sub():向量减法,用于计算两点间的偏移量或网格的尺寸向量(如greenSize = p3.copy().sub(p0)直接得到绿色网格的宽高向量)div():向量除法,将参考点的偏移向量除以网格尺寸向量,一次性得到x、y方向的比例,替代原代码中单独计算rx、ry的标量逻辑mult():向量乘法,将比例向量与红色网格尺寸向量相乘,得到映射点相对于红色网格原点的偏移量add():向量加法,将偏移量加上红色网格原点坐标,直接得到最终的映射点copy()/setX()/setY():复用已有向量创建新顶点,避免重复编写坐标值,简化代码结构
效果展示

内容的提问来源于stack exchange,提问作者v.k.
相关产品推荐
相关产品推荐

