Brandon Li
Brandon Li

Reputation: 181

Drawing using curveVertex in p5.js/processing randomly creates a weird loop

I have been trying to make a paint app using p5.js recently, and I've used lines, but they do not produce a smooth curve if my cursor moves fast. Now, I am trying to use curveVertex to connect the points, and it does work, just that it sometimes randomly creates a loop (when my cursor moves fast).

enter image description here

Circled in red are the loops, and sometimes I get weird curves too (circled in green).

Code:

let shapes = [];
let trail = [];
let drawings = [];

let penStrokeSize = 10;
let penFill = "black";
let backdrop = "white";
let trailLength = 10;

let defaultColors = ["white", "black", "red", "green", "blue", "yellow", "orange", "purple", "pink"];

let lastMousePos = [0, 0];
let lastPressed = false;

function setup() {
    // create a screen size canvas
    createCanvas(windowWidth, windowHeight);
}

function draw() {
    background(backdrop);

    putDrawings();
    drawSquares();
    drawTrail();

    // set last mouse pos to current mouse x and mouse y
    lastMousePos = [mouseX, mouseY];
    lastPressed = mouseIsPressed;
}

function updateDrawings() {
    if (lastPressed && mouseIsPressed) {
        drawings[drawings.length - 1].push([mouseX, mouseY]);
    } else if (mouseIsPressed) {
        drawings.push([[mouseX, mouseY]]);
    }
}

function putDrawings() {
    updateDrawings();
    // loop through each element of drawings, and draw a vertex through each of the points in the array
    for (let i = 0; i < drawings.length; i++) {
        noFill();
        stroke(penFill);
        strokeWeight(penStrokeSize);
        beginShape();
        for (let j = 0; j < drawings[i].length; j++) {
            curveVertex(drawings[i][j][0], drawings[i][j][1]);
        }
        endShape();
        fill(penFill);
        strokeWeight(0);
    }
}

function updateTrail() {
    trail.push([mouseX, mouseY]);
    if (trail.length > trailLength) {
        trail.shift();
    }
}

function drawTrail() {
    updateTrail();

    noFill();
    stroke(penFill);
    strokeWeight(penStrokeSize);

    beginShape();
    for (let i = 0; i < trail.length; i++) {
        curveVertex(trail[i][0], trail[i][1]);
    }
    endShape();

    fill(penFill);
    strokeWeight(0);
}

// ignore this function
function drawShape() {
    for (let i = 0; i < shapes.length; i++) {
        const type = shapes[i].type;

        switch (type) {
            case "ellipse":
                fill(shapes[i].color);
                ellipse(shapes[i].x, shapes[i].y, shapes[i].width, shapes[i].height);
                break;
            case "rect":
                fill(shapes[i].color);
                rect(shapes[i].x, shapes[i].y, shapes[i].width, shapes[i].height);
                break;
            case "line":
                stroke(shapes[i].color);
                strokeWeight(shapes[i].strokeSize);
                line(shapes[i].x1, shapes[i].y1, shapes[i].x2, shapes[i].y2);
                strokeWeight(0);
                break;
            case "point":
                stroke(shapes[i].color);
                strokeWeight(shapes[i].strokeSize);
                point(shapes[i].x, shapes[i].y);
                strokeWeight(0);
                break;
        }
    }
}

// ignore this function
function addShape(shape, props) {
    switch (shape) {
        case "ellipse":
            shapes.push({
                type: "ellipse",
                x: props[0],
                y: props[1],
                width: props[2],
                height: props[3],
                color: props[4],
            });
            break;
        case "rect":
            shapes.push({
                type: "rect",
                x: props[0],
                y: props[1],
                width: props[2],
                height: props[3],
                color: props[4],
            });
            break;
        case "line":
            shapes.push({
                type: "line",
                x1: props[0],
                y1: props[1],
                x2: props[2],
                y2: props[3],
                color: props[4],
                strokeSize: props[5],
            });
            break;
        case "point":
            shapes.push({
                type: "point",
                x: props[0],
                y: props[1],
                color: props[2],
            });
            break;
    }
}

// create a function that draws 9 squares of size 7% of window height
function drawSquares() {
    for (let i = 0; i < defaultColors.length; i++) {
        if (defaultColors[i] === "white") {
            stroke("black");
            strokeWeight(2);
        }

        // create an array with the square's x and y coordinates and its width and height
        let square = [i * windowHeight * 0.05 + windowWidth * 0.05, windowHeight * 0.9, windowHeight * 0.05, windowHeight * 0.05];

        fill(defaultColors[i]);
        // draw a square with the array square as its arguments
        rect(square[0], square[1], square[2], square[3]);
        // if the current mouse position is inside the current square and mouse is pressed and mouse button is left, change pen fill to the current color
        if (mouseX > square[0] && mouseX < square[0] + square[2] && mouseY > square[1] && mouseY < square[1] + square[3] && mouseIsPressed && mouseButton === LEFT) {
            penFill = defaultColors[i];
        }

        strokeWeight(0);
    }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.min.js"></script>

Help is appreciated!

Upvotes: 2

Views: 321

Answers (1)

danh
danh

Reputation: 62686

The curveVertex method is drawing a spline (see here),where every 2nd and 3rd point in a series of 4 are being treated as control points. Just use plain old vertex (doc).

        beginShape();
        for (let j = 0; j < drawings[i].length; j++) {
            vertex(drawings[i][j][0], drawings[i][j][1]);
        }
        endShape();

Upvotes: 1

Related Questions