简体   繁体   English

p5.js:如何使用小椭圆而不是 line() 函数在两点之间画一条线?

[英]p5.js: how can I draw a line between two points using tiny ellipses instead of the line() function?

How can I connect two points using a string of tiny ellipses instead of the stock line() function in p5.js?我如何使用一串小椭圆而不是 p5.js 中的 stock line()函数连接两点?

I am trying to create a more 'artistic' function to replace the stock line() function in p5.js.我正在尝试创建一个更“艺术”的函数来替换 p5.js 中的 stock line()函数。 To achieve this, I want to write a function where given two points (x, y) and (x1, y1), tiny circles are densely & consistently drawn along the line connecting the two points.为实现这一点,我想编写一个函数,其中给定两个点 (x, y) 和 (x1, y1),沿连接两点的直线密集且一致地绘制小圆圈。

I tried writing a function that first finds all possible x & y points and then use a conditional to only draw an ellipse if the slope between i and j and (x1, y1) matches the slope given by (x, y) and (x1, y1).我尝试编写一个函数,首先找到所有可能的 x 和 y 点,然后使用条件仅在ij和 (x1, y1) 之间的斜率与 (x, y) 和 (x1) 给出的斜率匹配时绘制椭圆, y1).

This only gives my desired result if (x, y) and (x1, y1) have a slope of 0, 1, or undefined;如果 (x, y) 和 (x1, y1) 的斜率为 0、1 或未定义,这只会给出我想要的结果; the dot spacings change dramatically with any other slope.点间距随任何其他斜率而显着变化。 I can't figure out how to get consistently placed dots along any line I input.我无法弄清楚如何沿着我输入的任何行获得一致放置的点。

My function is as follows:我的功能如下:

function customLine(x, y, x1, y1) {
  for (var i = x; i >= x && i <= x1; i ++) { 
   for (var j = y; j >= y && j <= y1; j ++) {
    if ((j - y) / (i - x) == (y1 - y) / (x1 - x)) {
     fill(0);
     circle(i, j, 5);
   }
  }
 }
}

I've also attached an image showing that I get my desired effect for slope values of 0, undefined, or 1, but not when the slope is a fraction: output of above code, illustrating issue我还附上了一张图片,显示我对 0、未定义或 1 的斜率值得到了我想要的效果,但当斜率是分数时却没有:上面代码的输出,说明问题

How can I fix my function?我该如何修复我的功能? Or is there any entirely easier way to do this?或者有没有更简单的方法来做到这一点? Thanks so much!非常感谢!

I think you're looking for lerp (linear interpolation) between two points.我认为您正在寻找两点之间的lerp (线性插值)。 For example,例如,

 let anchor; function setup() { createCanvas(innerWidth, innerHeight); noLoop(); anchor = createVector(innerWidth / 2, innerHeight / 2); } function draw() { drawDottedLine(anchor, createVector(mouseX, mouseY)); } function mouseMoved() { clear(); drawDottedLine(anchor, createVector(mouseX, mouseY)); } const drawDottedLine = (p1, p2) => lerpLine(p1, p2).forEach(({x, y}) => circle(x, y, 10)); const lerpLine = (p1, p2, steps = 10) => [...Array(steps)].map((_, i) => p5.Vector.lerp(p1, p2, norm(i, 0, steps)));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>

If you're looking for the spacing to remain consistent and use a variable number of points, you can pass the distance between the two points as the number of steps:如果您希望间距保持一致并使用可变数量的点,则可以将两点之间的距离作为步数传递:

 let anchor; let mouse; function setup() { createCanvas(innerWidth, innerHeight); noLoop(); anchor = createVector(innerWidth / 2, innerHeight / 2); mouse = createVector(0, 0); } function draw() { drawDottedLine(anchor, mouse, anchor.dist(mouse) / 16); } function mouseMoved() { clear(); mouse.x = mouseX; mouse.y = mouseY; drawDottedLine(anchor, mouse, floor(anchor.dist(mouse) / 16)); } const drawDottedLine = (p1, p2, steps) => lerpLine(p1, p2, steps).forEach(({x, y}) => circle(x, y, 10)); const lerpLine = (p1, p2, steps = 10) => [...Array(steps)].map((_, i) => p5.Vector.lerp(p1, p2, norm(i, 0, steps)));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>

Or add discretizing:或者添加离散化:

 let anchor; let mouse; function setup() { createCanvas(innerWidth, innerHeight); noLoop(); anchor = createVector(innerWidth / 2, innerHeight / 2); mouse = createVector(0, 0); } function mouseMoved() { clear(); const spacing = 10; mouse.x = floor(mouseX / spacing) * spacing; mouse.y = floor(mouseY / spacing) * spacing; const steps = floor(anchor.dist(mouse) / spacing); drawDottedLine(anchor, mouse, steps); } const drawDottedLine = (p1, p2, steps) => lerpLine(p1, p2, steps).forEach(({x, y}) => circle(x, y, 10)); const lerpLine = (p1, p2, steps = 10) => [...Array(steps)].map((_, i) => p5.Vector.lerp(p1, p2, norm(i, 0, steps)));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>

I think the easiest way here is to use some vectors and trigonometry, please try this:我认为这里最简单的方法是使用一些向量和三角函数,请试试这个:

 function setup() { createCanvas(windowWidth, windowHeight); v = createVector(); } function draw() { background(255); customLine(width / 2, height / 2, mouseX, mouseY); } function customLine(x, y, x1, y1) { vx = x1 - x; vy = y1 - y; for (let i = 0; i < v.mag(); i++) { fill(0).circle(x + i * cos(v.heading()), y + i * sin(v.heading()), 5); } }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js"></script>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM