Douglas
Douglas

Reputation: 65

How would I create dots in-between 2 positions on a canvas for P5.js?

So ultimately I'm trying to figure out a loop that could create dots in-between the 2 points. If anyone could figure this out it would be greatly appreciated!

let pos1 = {x:383,y:202};
let pos2 = {x:754,y:387};

let dotRadius = 5;

let divisions = 10; 

// Try to create 'divisions' amount of dots between pos1 and pos2

function setup() {
  createCanvas(768,768);
  
}

function draw() {
  background(50,50,50);
  rectMode(CENTER);
  
  stroke(180,180,180);
  
  circle(pos1.x, pos1.y,dotRadius);
  circle(pos2.x, pos2.y,dotRadius);
  
  noLoop();
}

Upvotes: 2

Views: 573

Answers (3)

George Profenza
George Profenza

Reputation: 51847

The existing answers are great (+1).

I would like to point you yet another option: linear interpolation(lerp()).

You pass a from and to value as the first two arguments and the third controls the amount in between these two values will be returned. The third value is a normalised value (i.e. between 0.0 and 1.0). You can think of it as a percentage where:

  • 0.0 = 0 % = the first value
  • 1.0 = 100% = the second value
  • 0.5 = 50% = in between first and second (by this logic you could use this ten times with .1 increments to get 10 divisions):

let pos1 = {x:383,y:202};
let pos2 = {x:754,y:387};

let dotRadius = 5;

let divisions = 10; 

// Try to create 'divisions' amount of dots between pos1 and pos2

function setup() {
  createCanvas(768,768);
  
}

function draw() {
  background(50,50,50);
  rectMode(CENTER);
  
  stroke(180,180,180);
  
  circle(pos1.x, pos1.y,dotRadius);
  circle(pos2.x, pos2.y,dotRadius);
  // in between points
  stroke(32);
  for(let i = 0 ; i < divisions; i++){
    // map 0-9 counter to 0.0 -> 1.0 lerp range
    let interpolationAmount = map(i, 0, divisions - 1, 0.0, 1.0);
    // calculate interpolated position
    let interpolatedX = lerp(pos1.x, pos2.x, interpolationAmount);
    let interpolatedY = lerp(pos1.y, pos2.y, interpolationAmount);
    // render dot (smaller as a way to visualise overlap with pos1, pos2)
    circle(interpolatedX, interpolatedY, dotRadius * 0.5);
  }
  
  noLoop();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.min.js"></script>

(We've also used map() above which: simply dividing i by 10 would've been similar in this case, but in general it's a very useful function)

Additionally, p5.js already provides an object with x,y properties: p5.Vector. It can do a lot of cool things, but one of them is actually lerp() (check out the examples).

Here's a version of the above using p5.Vector instead:

let pos1 = new p5.Vector(383,202);
let pos2 = new p5.Vector(754,387);

let dotRadius = 5;

let divisions = 10; 

// Try to create 'divisions' amount of dots between pos1 and pos2

function setup() {
  createCanvas(768,768);
  
}

function draw() {
  background(50,50,50);
  rectMode(CENTER);
  
  stroke(180,180,180);
  
  circle(pos1.x, pos1.y,dotRadius);
  circle(pos2.x, pos2.y,dotRadius);

  stroke(32);
  for(let i = 0 ; i < divisions; i++){
    // notice we're using p5.Vector.lerp() instead of pos1.lerp(pos2,...) so pos1 x,y remain intact
    let inBetween = p5.Vector.lerp(pos1, pos2, map(i, 0, divisions - 1, 0.0, 1.0));
    circle(inBetween.x, inBetween.y, dotRadius * 0.5);
  }
  
  noLoop();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.min.js"></script>

Hopefully these are useful in the future, but at the moment the existing answers more than suffice.

Upvotes: 3

phentnil
phentnil

Reputation: 2279

The primary way to calculate the dots between two points is getting the x-difference and the y-difference.

let my = pos2.y - pos1.y;
let mx = pos2.x - pos1.x;

Then each x- and y-coordinate can be calculated between based on starting positions, ending positions, and the number of divisions.

Full code (see the running example on the p5.js Editor):

let pos1 = { x: 383, y: 202 };
let pos2 = { x: 754, y: 387 };
let dotRadius = 5;
let divisions = 10;

// Try to create 'divisions' amount of dots between pos1 and pos2
function drawDivisions() {
  // Get the y-distance
  let my = pos2.y - pos1.y;

  // Get the x-distance
  let mx = pos2.x - pos1.x;

  // Add 1 to divisions so that it creates 'divisions' points between, not including start nor end
  let div = divisions + 1;

  // get the step value for y
  let dy = my / div;

  // get the step value for x
  let dx = mx / div;

  // Set a different color just to set these new dots apart
  stroke(240, 40, 180);

  // Enter the loop and create 'divisions' points
  for (let i = 1; i <= divisions; i++) {
    let x = pos1.x + dx * i;
    let y = pos1.y + dy * i;
    circle(x, y, dotRadius);
  }
}

function setup() {
  createCanvas(768, 768);
}

function draw() {
  background(50, 50, 50);
  rectMode(CENTER);

  stroke(180, 180, 180);

  circle(pos1.x, pos1.y, dotRadius);
  circle(pos2.x, pos2.y, dotRadius);

  // Enter our function to draw dots between start and end
  drawDivisions();

  noLoop();
}

Upvotes: 2

ErrorEliminator
ErrorEliminator

Reputation: 120

You can use a for loop and conditionals to draw the circles incrementing the x and y values in each iteration.

let pos1 = {x:383,y:202};
let pos2 = {x:754,y:387};

let dotRadius = 5;

let divisions = 10;

// Try to create 'divisions' amount of dots between pos1 and pos2

let increment_x = (pos2.x-pos1.x)/(divisions+1)
let increment_y = (pos2.y-pos1.y)/(divisions+1)


function setup() {
  createCanvas(768,768);
  
}

function draw() {
  background(50,50,50);
  rectMode(CENTER);
  
  stroke(180,180,180);
  
  circle(pos1.x, pos1.y,dotRadius);
  circle(pos2.x, pos2.y,dotRadius);

  let y=pos1.y
  
  for (let x=pos1.x; x<pos2.x; x+=increment_x) {
    if (y<pos2.y){
      circle(x, y,dotRadius);
    }
    y+=increment_y
  }
}

Upvotes: 3

Related Questions