Smooth curves from series of x,y co-ordinates

edited June 2016 in p5.js

Hi Im trying to produce a series of coloured lines that flow smoothly. I currently do this in Coreldraw by drawing a line through the points and then using CorelDraw's internal smooth function - which leaves some parts of the curve (normally an obtuse angle) not quite right but this is fixed by then removing every other point that the curve must pass thru which results in near perfect smoothness at the cost of accuracy.

Given that it is the smoothnes of the curve that is most important here, can somebody help with advice on what is the right way to go about this in p5.js?

Answers

  • Answer ✓

    Do you mean something like this?

    var points = [];
    var num = 12;
    
    function setup() {
      createCanvas(300, 300);
      background(255);
    
      for (var i = 0; i < num; i++) {
        points[i] = createVector(random(width), random(height));
      }
    }
    
    function draw() {
      noFill();
      stroke(110, 100, 0);
      strokeWeight(3);
    
      beginShape();
      for (var i = 0; i < num; i++) {
          curveVertex(points[i].x, points[i].y);
      }
      endShape();
    
      //so that you can see where the points are
      noStroke();
      fill(110, 30, 0)
      for (var i = 0; i < num; i++) {
         ellipse(points[i].x, points[i].y, 10, 10);
      }
    }
    

    Note that curveVertex() needs to be used between beginShape() and endShape().

  • edited June 2016

    Thanks allonestring, I think I've got it. The use of createVector is a little different from what I expected - am I right in thinking that it actually represents a point in two or 3d space rather than a direction to that point? Im wanting to colour individual parts of the line in different colours so; Is it possible to leave the line in the same place as its drawn but have it broken up into separate objects? (So that it looks like a single continuous line but is in fact made up of many objects, each object being defined by 2 points?)

  • Here I've used the vector just as a convenient way of holding two numbers which I'll use as (x, y) co-ordinates. I could've used arrays for each of x and y. The Vector class provides methods that will look familiar if you use vectors in maths.
    You might have to draw a picture to show what you mean, as I don't think that you mean a dashed line.

  • int num = 12;
    PVector[] points = new PVector[num];
    PVector[] mov  = new PVector[num];
    
    
    void setup() {
      size(600, 600);
      background(255);
    
      for (int i = 0; i < num; i++) {
        points[i] = new PVector(random(width), random(height));
        mov[i] = new PVector(random(-1, 1), random(-1, 1));
      }
    }
    
    void  draw() {
      //
      if (random(100)>92) 
        background(255);
    
      noFill();
      stroke(110, 100, 0);
      strokeWeight(3);
    
      beginShape();
      for (int i = 0; i < num; i++) {
        curveVertex(points[i].x, points[i].y);
      }
      endShape();
    
    
      //fill(random(255), random(255), random(255)); 
    
      //x = curvePoint(5, 73, 73, 15, t);
      //y = curvePoint(26, 24, 61, 65, t);
      //ellipse(x, y, 3, 3);
    
      //so that you can see where the points are
      noStroke();
      fill(110, 30, 0);
      if (!false)
        for (int i = 0; i < num; i++) {
          // ellipse(points[i].x, points[i].y, 10, 10);
          points[i].x+=mov[i].x*10;
          points[i].y+=mov[i].y*10;
    
          mov[i].x=keepInside(mov[i].x, points[i].x, width-10);
          mov[i].y=keepInside(mov[i].y, points[i].y, height-1);
        }
      points[1].x++;
    }
    //
    float keepInside(float a, float b, float max) {
      if (b<10) 
        return abs(a); 
      if (b>max) 
        return -abs(a);
      return a;
    }
    //
    
  • this is just a play on it, nothing to do with the original post....

  • edited June 2016

    Sorry Chrisir - I get an error with your code that points me to p5.js FAQ - Why can't I assign variables using p5 functions and variables before setup()?

  • Thanks for the reply allonestring, https://flic.kr/s/aHskCow13R shows a coloured line of the type. Im drawing fancy graphs and want to plot a line thru a set of points but have that line in a different colour between each point (see http://nicksoph.wix.com/spotline for images, intention is to make similar as an online app. )

  • Answer ✓

    My code is Java p5

  • edited June 2016 Answer ✓

    Like this?

        var points = [];
        var num = 12;
    
        function setup() {
          createCanvas(300, 300);
          background(240, 140, 160);
    
          for (var i = 0; i < num; i++) {
            points[i] = createVector(random(width), random(height));
          }
        }
    
        function draw() {
          noFill();
          strokeWeight(10);
          strokeCap(SQUARE);
    
          for (var i = 0; i < num - 3; i++) {
            stroke(255/num * i)
    
            //see that you need at least four points to draw a curve
            //the first and last being handles which determine the curve of the curve
            beginShape();
            curveVertex(points[i].x, points[i].y);
            curveVertex(points[i + 1].x, points[i + 1].y);
            curveVertex(points[i + 2].x, points[i + 2].y);
            curveVertex(points[i + 3].x, points[i + 3].y);
            endShape();
          }
    
          //so that you can see where the points are
          noStroke();
          fill(110, 30, 0)
          for (var i = 0; i < num; i++) {
            ellipse(points[i].x, points[i].y, 5, 5);
          }
        }  
    

    Love your lines!

  • edited June 2016

    @Chrisr. I didnt know there was such a thing as java P5. Thanks, I will take another look to see if I can understand what it does but I'm struggling with learning javascript and suspect I wont be adding java to my studies.

  • Thanks allonestring - that does exactly what's required. I was thinking about how to break a line up not drawing lots of small ones and your code shows very well how to proceed. Thanks again.

Sign In or Register to comment.