2

I'm trying to draw smooth curves instead of the normal straight line between points in p5js, using the current and previous mouse position (I can keep a list of past points if needed).

I've tried to adapt this answer to p5, but this does not work for some reason. Trying to rewrite it for p5.js just gives straight lines instead of curves.

let history = []
let value = 0
var p = 10
window.setup = setup;
window.draw = draw;
window.keyPressed = keyPressed;

function setup() {
  createCanvas(window.innerWidth, window.innerHeight);
}

function drawLine(x1, y1, x2, y2, width, color) {
  strokeWeight(p)
  line(x1, y1, x2, y2);
}

async function keyPressed() {
  if (key === " ") {
    background(255)
    for (let i = 0; i < history.length - 1; i++) {
      window.setTimeout(function() {
        drawLine(history[i][0], history[i][1], history[i + 1][0], history[i + 1][1])
      }, await sleep(1))
      // sleep(1000)
    }
    // drawing = 0
  }
}

function draw() {
  if (mouseIsPressed === true) {
    stroke(0)
    drawLine(mouseX, mouseY, pmouseX, pmouseY)
    history.push([pmouseX, pmouseY], [mouseX, mouseY])
    history = history.slice(history.length - 1000, history.length)
  }
}

function mouseReleased() {
  beginShape()
  noFill()
  stroke('red')
  strokeWeight(2)
  vertex(history[0][0], history[0][1]);
  for (i = 1; i < history.length - 1; i++) {
    var xc = (history[i][0] + history[i + 1][0]) / 2;
    var yc = (history[i][1] + history[i + 1][1]) / 2;
    quadraticVertex(xc, yc, history[i][0], history[i][1]);
  }
  vertex(history[history.length-1][0], history[history.length-1][1])
  endShape()
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.js" integrity="sha512-DWtDo/6AXxH1t9p7GCWqmC4XTVK/eje94XTV6QYB39rGllLN8Tr3izDf6lkmebgqRnYh4wtSFm4CvBoA9SrdpA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

How can I draw curved lines and properly translate the vanilla HTML5 canvas code to p5?

ggorlen
  • 44,755
  • 7
  • 76
  • 106
Vixey
  • 37
  • 7
  • [how to draw smooth curve through N points using javascript HTML5 canvas?](https://stackoverflow.com/questions/7054272/how-to-draw-smooth-curve-through-n-points-using-javascript-html5-canvas) – ggorlen May 09 '23 at 15:06
  • @ggorlen that uses html5 canvas, im not really sure how to modify it for p5js – Vixey May 09 '23 at 16:03
  • The logic is the same. P5 just renders things differently and has its own wrappers on events, but they're all easily translatable from vanilla canvas. Try making an attempt at adapting the underlying algorithm and update with your attempt if you get stuck. `getCurvePoints` is totally agnostic of your UI library, just plain JS, so all you need to translate is `drawCurve` and `drawLines`, which is about 8 lines of code, and you'd probably want to adapt anyway to match your use case. – ggorlen May 09 '23 at 16:04
  • BTW, there are many other solutions in that thread, like [this one](https://stackoverflow.com/a/7058606/6243352) which seems very simple. https://p5js.org/reference/#/p5/quadraticVertex should work. – ggorlen May 09 '23 at 16:11
  • @ggorlen i've tried some solutions, they all seem to draw straight lines instead of curves with p5js – Vixey May 09 '23 at 16:45
  • 2
    Does this answer your question? [how to draw smooth curve through N points using javascript HTML5 canvas?](https://stackoverflow.com/questions/7054272/how-to-draw-smooth-curve-through-n-points-using-javascript-html5-canvas) – Rabbid76 May 09 '23 at 16:51
  • @ggorlen alrighty, my codes a bit messy so i apologize in advanced haha – Vixey May 09 '23 at 16:52
  • @Rabbid76 See other comments on this, i've tried and it doesnt work – Vixey May 09 '23 at 16:53
  • One or more of the solutions in the link probably do work, it's a matter of adapting one properly to your use case. Remember, p5 is just a renderer, basically, so the logic of what you're asking is totally decoupled from p5. It doesn't make sense to reinvent all of the work done in that other thread again just for a different renderer. At the end of the day, we're dealing with how to build a certain array of points. – ggorlen May 09 '23 at 16:57
  • 1
    alright @ggorlen, i've updated the post with a code snippet, hope this helps – Vixey May 09 '23 at 17:02

1 Answers1

2

You're pretty close. The problem has to do with building the points rather than the algorithm. You can detect this with a print(history), or by minimizing the code to remove the mouse and use a hardcoded list of points instead, which you'd see works.

When you test mousePressed in draw, you're actually adding a bunch of the same point since one mouse press can span many frames, but the points need to be spread out for the curve effect to work properly.

Here's an example of the multiple fires per mouse press:

function draw() {
  if (mouseIsPressed) {
    print(`mouse pressed at ${mouseX}, ${mouseY}`);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.js"></script>

A solution might be to push a new point only on release:

const history = [];

function setup() {
  createCanvas(window.innerWidth, window.innerHeight);
  noFill();
  stroke("red");
  strokeWeight(2);
}

function mouseReleased() {
  clear();
  history.push({x: mouseX, y: mouseY});
  history.forEach(({x, y}) => ellipse(x, y, 5, 5));

  if (history.length < 2) {
    return;
  }

  beginShape();
  vertex(history[0].x, history[0].y);

  for (let i = 1; i < history.length - 2; i++) {
    const xc = (history[i].x + history[i + 1].x) / 2;
    const yc = (history[i].y + history[i + 1].y) / 2;
    quadraticVertex(history[i].x, history[i].y, xc, yc);
  }

  quadraticVertex(
    history.at(-2).x,
    history.at(-2).y,
    history.at(-1).x,
    history.at(-1).y
  );
  endShape();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.js"></script>

Playing with this a bit, you can see that previously-drawn curves can change, which seems unrealistic in a drawing app. To fix this, you may need to work around it or try another algorithm from the canonical thread, if this doesn't fit your needs.

ggorlen
  • 44,755
  • 7
  • 76
  • 106
  • This works really well, thank you so much! (I'll look through the linked thread, should I make a self-answer if I make it work? (along with separating curves)) – Vixey May 09 '23 at 19:04
  • Please do, that'd be great! Thanks for responding and patiently updating your post to address the feedback. I think this thread will be a good resource. – ggorlen May 09 '23 at 19:08
  • Of course! Thank you so much for your help, I've had a mixed experience with SO so its nice to have somebody who seems like they want to help – Vixey May 09 '23 at 19:20