4

I have an array containing 6 sets of random x, y coordinates. I'm able to draw lines connecting the points, like this:

6 points connected by lines

But, I'm having trouble figuring out how to draw repeating squares (to achieve a dotted line effect) where the lines are. Right now, I'm able to get this, but I want to only draw squares along the line only:

enter image description here

I understand what I'm doing wrong theoretically, but really struggling with the math here. How do I go about only including the squares that appear along the lines? TIA.

This is my code right now:

let w = 500;
let h = 500;
let riverArr = [];
let distanceArr = [];

function setup() {
    createCanvas(w, h);
}

function draw() {
    background(240);
    generatePoints();

    for (i = 1; i < riverArr.length; i++) {
        let x1 = parseInt(riverArr[i][0]);
        let y1 = parseInt(riverArr[i][1]);

        let x2 = parseInt(riverArr[i - 1][0]);
        let y2 = parseInt(riverArr[i - 1][1]);

        line(x1, y1, x2, y2);

        let d = int(dist(x1, y1, x2, y2));

        ellipse(x1, y1, 5);

        for (j = 0; j <= x1; j++) {
            for (k = 0; k <= y1; k++){
                rect(j, k, 1);
            }
        }
        distanceArr.push(d);
    }
    noLoop();
}

function generatePoints() {
    let finished;
    riverArr.push([0, random(h)]);
    for (i = 0; i < 4; i++) {
        finished == false;
        riverArr.push([random(w), random(h)]);
        if (i > 0 && riverArr[i][0] <= riverArr[i - 1][0]) {
            console.log(riverArr[i][0], riverArr[i - 1][0]);
            console.log('Bad path');
        }
        finished == true;
    }
    riverArr.push([w, random(h)]);
}
  • If your goal is to achieve a dotted line effected, why don't you just draw the lines split into pieces? – cegredev May 02 '20 at 09:00
  • Splitting the lines won't achieve the effect I'm going for, unfortunately :P I specifically want to draw squares repeating along the lines. – Anokhee Jandhyala May 02 '20 at 09:04
  • Hmm, okay. Could you please post a picture of what you're going for? I'm not sure if I understand what you mean. – cegredev May 02 '20 at 09:05
  • @Schred I want to draw dotted lines between the points like the one here: https://etc.usf.edu/clipart/13100/13117/square_13117_lg.gif (except with squares instead of rectangles) – Anokhee Jandhyala May 02 '20 at 09:09
  • @AnokheeJandhyala Remember that p5.js renders using Canvas, therefore you can use [setLineDash](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash). (e.g. in `setup()` call `document.querySelector("canvas").getContext('2d').setLineDash([5, 15]);`). Alternatively, if you would like to excercise implementing your own dashed line algorithm you should have a play with [p5.Vector's `lerp()`](https://p5js.org/reference/#/p5.Vector/lerp). Have fun! – George Profenza May 02 '20 at 11:21
  • @GeorgeProfenza Thank you! Sadly, neither of those is quite what I'm looking for. I'm not trying to create a dashed or dotted line, I'm trying to achieve a dotted line effect with squares. – Anokhee Jandhyala May 02 '20 at 17:28
  • @AnokheeJandhyala Unfortunately I didn't have time to explain the above approaches in more detail. Have a look [here](https://editor.p5js.org/george.profenza/sketches/tfIsh81Gn) and [here](https://editor.p5js.org/george.profenza/sketches/JZ243JdwV). Hopefully the examples illustrated ways of achieving similar results – George Profenza May 02 '20 at 21:43

1 Answers1

3

Something like this?

let points = [];
const rectSize = 10;

function setup() {
    createCanvas(400, 400);
    // add random points to a list
    for (let i = 0; i < 4; i++)
        points.push(createVector(random(0, width), random(0, height)));

    rectMode(CENTER);
    fill(0);
    noStroke();
}

function draw() {
    background(255);
    // from the first point to the one before last
    for (let i = 0; i < points.length - 1; i++) {
        // get a reference to the current and next point
        const current = points[i], next = points[i + 1];
        // calculate how many rectangles to draw in between two points
        // 1. calculate the distance between the current and next point
        // 2. divide the distance by twice the rectangle size (to achieve an equal gap between drawn and not drawn rectangles
        // 3. round down (floor) the divided distance
        const count = floor(dist(current.x, current.y, next.x, next.y) / (rectSize * 2));
        // compute direction of movement vector from one point to the next
        // 1. subtract current vector from next vector (e.g. each componeny (x,y))
        // 2. divide direction vector by how many rectangles
        // 3. store result in a p5.js Vector object (e.g. if count = 5, adding dir 5 times to current point gets us to the next point
        const dir = createVector((next.x - current.x) / count, (next.y - current.y) / count);
        // for each inbetween rectangles
        for (let j = 0; j < count; j++)
        // draw it by adding to the current position the direction towards the next position multiplied for each rectangle
            rect(current.x + dir.x * j, current.y + dir.y * j, rectSize, rectSize);
    }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>

It's not using your logic, but I don't think adjusting that will be too hard.

Also I just noticed that in your generatePoints() method, you're saying finished == true/false. I don't know what purpose finished serves, but you should probably change that == to a = for assignement, not comparing.

cegredev
  • 1,485
  • 2
  • 11
  • 25