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

如何用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.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 06:30:54