Make a Bezier curve with more than 2 control points

Actually, the bezier() can only do 2 control points an 1 start,end point. But, I want to do a Bezier curve with 7 control points or more/less. How can I do ? bezierVertex(), quadraticVertex() do not make what I want.

Answers

  • @Mxw309 --

    If you want a Bezier curve with 7 control points, then bezierVertex() does make what you want.

    See the Processing Curves Tutorial section "Continuous Bézier Curves":

    In order to make two curves A and B smoothly continuous, the last control point of A, the last point of A, and the first control point of B have to be on a straight line. Here is an example that meets those conditions. The points that are in a line are shown in bold.

    Example:

     size(200, 200);
     background(255);
     beginShape();
     vertex(30, 70); // first point
     bezierVertex(25, 25, 100, 50, 50, 100);
     bezierVertex(20, 130, 75, 140, 120, 120);
     endShape();
    

    Alternately you can specify a continuous spline curve with no control points at all (but lots of spline points) using curve() / curveVertex().

  • do you want linked cubic beziers or one bezier with 7 control points (an 8th order curve) though?

    latter is possible, but it gets crazy quickly

    so instead of the following (3rd order equation, image from wikipedia)

    wikimedia

    you'd have

    B(t) = (1 - t)^8 * P0
      + 8 * t * (1-t)^7 * P1
      + 28 * t^2 * (1-t)^6 * P2
      + 56 * t^3 * (1-t)^5 * P3
      + 70 * t^4 * (1-t)^4 * P4
      + 56 * t^5 * (1-t)^3 * P5
      + 28 * t^6 * (1-t)^2 * P6
      + 8 * t^7 * (1-t) * P7
      + t^8 * P8
    

    where t goes from 0 to 1 and P0 is start, P8 is the end, P1 to P7 are the 7 control points

    (the 8, 28, 56 etc come from the lines of Pascal's Triangle - https://en.wikipedia.org/wiki/Pascal's_triangle)

  • edited November 2016 Answer ✓

    Do you mean higher order Bezier curve as shown here in Wikipedia

  • edited November 2016

    @jeremydouglass It's doing good for some shape, but, there is a problem. I want to make a shape like a loop, and the anchor points created are problematic. Exemple (white circle : control points, red circle : anchor points) :

    processingbezier

    @koogs I would test this, but I have no idea how to create a curve with this :/

    @quark Yes

  • Answer ✓
    int POINTS = 9;
    PVector[] c = new PVector[POINTS];
    
    void setup() {
      size(400, 400);
      // random control points
      for (int i = 0 ; i < POINTS ; i++) {
        c[i] = new PVector(random(-width / 2, width / 2), random(-height / 2, height / 2));
      }
      noLoop();
    }
    
    void draw() {
      background(255);
      translate(width / 2, height / 2);
    
      // draw control points
      stroke(0, 255, 0);
      fill(255, 0, 0);
      for (int i = 0 ;  i < POINTS ; i++) {
        ellipse(c[i].x, c[i].y, 5, 5);
        if (i != 0) {
          line(c[i].x, c[i].y, c[i - 1].x, c[i - 1].y);
        }
      }
    
      // draw bezier points
      stroke(0, 0, 255);
      for (float i = 0 ; i <= 1 ; i += 1 / 500.0) {
        bpoint(i);
      }
    }
    
    void bpoint(float t) {
      float t0 = 1;
      float t1 = t0 * t;
      float t2 = t1 * t;
      float t3 = t2 * t;
      float t4 = t3 * t;
      float t5 = t4 * t;
      float t6 = t5 * t;
      float t7 = t6 * t;
      float t8 = t7 * t;
      float _t0 = 1;
      float _t1 = _t0 * (1 - t);
      float _t2 = _t1 * (1 - t);
      float _t3 = _t2 * (1 - t);
      float _t4 = _t3 * (1 - t);
      float _t5 = _t4 * (1 - t);
      float _t6 = _t5 * (1 - t);
      float _t7 = _t6 * (1 - t);
      float _t8 = _t7 * (1 - t);
      float bx = _t8 * c[0].x
        + 8 * t1 * _t7 * c[1].x
        + 28 * t2 * _t6 * c[2].x
        + 56 * t3 * _t5 * c[3].x
        + 70 * t4 * _t4 * c[4].x
        + 56 * t5 * _t3 * c[5].x
        + 28 * t6 * _t2 * c[6].x
        + 8 * t7 * _t1 * c[7].x
        + t8 * c[8].x;
      float by = _t8 * c[0].y
        + 8 * t1 * _t7 * c[1].y
        + 28 * t2 * _t6 * c[2].y
        + 56 * t3 * _t5 * c[3].y
        + 70 * t4 * _t4 * c[4].y
        + 56 * t5 * _t3 * c[5].y
        + 28 * t6 * _t2 * c[6].y
        + 8 * t7 * _t1 * c[7].y
        + t8 * c[8].y;
        point(bx, by);
    }
    
  • edited November 2016

    @koogs It's crazy but it works

  • @Mxw309 -- as I quoted before:

    In order to make two curves A and B smoothly continuous, the last control point of A, the last point of A, and the first control point of B have to be on a straight line.

    See how a straight line between the two white dots doesn't have the red dot in between them? That is why the curve is broken.

    Also, your loop is defined with 4 points (3 segments) -- you might want to try 6 points (5 segments) for more control.

  • edited November 2016

    BTW -- I believe that koogs approach and the simple-sectional approach are equivalent, by De Casteljau's algorithm. See the Example Implementation and Geometric Interpretation. Essentially, you can split higher degree Bézier curves into several lower degree Bézier curves. The control points are expressed differently, but the curve is the same.

    Note that the intermediate points that were constructed are in fact the control points for two new Bézier curves, both exactly coincident with the old one.

    That said, @koogs solution is very cool. It would be nice to fancy it up by implementing it as a function that takes any degree, and then rendering line segments from an array rather than points (or even storing the point data as vertices in a PShape).

  • edited November 2016

    One last find:

    On the Math.Stackexchange thread Casteljau's algorithm - practical example, Chris Taylor shared a Java class Casteljau for solving a high degree Bézier curve by interpolating n points between a collection of Bézier section points for a curve of any degree. Eyeballing it, I think this might be the approach of @koogs seven-degree demo approach written as a class.

    Feed the resulting point array back into a simple spline curve / PShape to get a continuous rendering.

  • edited November 2016

    Yeah, apologies, that was just thrown together in 30 minutes using stuff dragged out of my memory from my 1989 degree course... 8)

    A proper solution would, yes, let you define the degree and number of points and join them up.

    To get a c2 continuous bezier curve the control points either side of one of the intermediate start / end points have to be collinear AND of equal length. You end up with an odd mix of points that are passed through and points that affect the curve doing it this way though, which I always find a bit odd. That said, anything above a cubic always seems a bit odd to me anyway.

    (Will draw a picture when I'm on laptop)

    ok, quick sketch

    void setup() {
      size(400, 200);
      noFill();
      noLoop();
    }
    
    PVector start = new PVector(0, 0);
    PVector c1 = new PVector(0, 50);
    PVector c2 = new PVector(50, 50);
    PVector mid = new PVector(50, 0);
    PVector c3 = new PVector(50, -25);
    PVector c4 = new PVector(100, -25);
    PVector end = new PVector(100, 0);
    
    void draw() {
    
      // control points c3 and c4 are colinear but not equal distance
      translate(50, 100);
      ellipse(start.x, start.y, 5, 5);
      ellipse(c1.x, c1.y, 5, 5);
      ellipse(c2.x, c2.y, 5, 5);
      ellipse(mid.x, mid.y, 5, 5);
      ellipse(c3.x, c3.y, 5, 5);
      ellipse(c4.x, c4.y, 5, 5);
      ellipse(end.x, end.y, 5, 5);
      bezier(start.x, start.y, c1.x, c1.y, c2.x, c2.y, mid.x, mid.y);
      bezier(mid.x, mid.y, c3.x, c3.y, c4.x, c4.y, end.x, end.y);
    
      // these are colinear and equal length
      translate(200, 0);
      c3 = new PVector(50, -50);
      c4 = new PVector(100, -50);
      ellipse(start.x, start.y, 5, 5);
      ellipse(c1.x, c1.y, 5, 5);
      ellipse(c2.x, c2.y, 5, 5);
      ellipse(mid.x, mid.y, 5, 5);
      ellipse(c3.x, c3.y, 5, 5);
      ellipse(c4.x, c4.y, 5, 5);
      ellipse(end.x, end.y, 5, 5);
      bezier(start.x, start.y, c1.x, c1.y, c2.x, c2.y, mid.x, mid.y);
      bezier(mid.x, mid.y, c3.x, c3.y, c4.x, c4.y, end.x, end.y);
    
      save("/tmp/bex.png");
    }
    

    bex

    see the curve around the join in the first part isn't smooth but the second one is? there's no sudden change in direction because the control points around the mid point are in a line but there IS a sudden change in the speed in which the curve changes. in the second one it's smoother because the control points are opposite AND at the same distance.

  • What is being discussed here is a Bezier spline NOT a high order Bezier curve.

    Bezier spline - a smooth curve that passes through three or more fixed (anchor) points. The fixed points are connected by cubic (mostly) Bezier curves. These are the ones you normally see in vector graphic packages. A cubic Bezier curve has four controls points, 2 fixed representing the ends and 2 that define the curve shape.

    A high order Bezier is a single curve that has n controls points, where n > 4. As before 2 control points define the start and the end of the curve and the other n-2 points control the shape.

    The Shapes3D library has a number of classes you could use or hack to meet your needs

    Bezier2D for a single Bezier curve of any degree >= 2 in 2D
    P_Bezier3D same but for 3D
    P_BezierSpline a smmoth curve that passes through any number of anchor points linked by cubic Bezier curves.

    Note in your picture above you have 3 Bezier curves, 2 which are cubic (order 4) and the third that links the lower two red points is a quadratic (order 3)

  • What is being discussed here is a Bezier spline NOT a high order Bezier curve.

    we are talking both, i think, because it's not clear which the OP requires.

  • I asked the question in my first comment and the OP agreed he was interested in higher order Bezier curves but then then immediately posted a picture of a Bezier spline. Obviously the OP is confused regarding the difference between high-order and spline hence my last comment.

    I suspect that what he really needs is a Bezier spline because it is much easier to control the overall shape of the curve.

    This discussion gives an example of using the Shapes3D library to create a Bezier spline.

  • @quark @koogs Yes, I think i'm confused between high-order and spline. But the picture that I posted was to demonstrate that bezierVertex() doesn't make what I want (because it create Bezier spline ?). The koogs code make what I want actually (because it create high-order bezier ?). It's why I guess i'm researching high-order bezier. This is what koogs code make, and this is actually what I want

    higorderbezier

    Actually I'm trying to use the 3DShapes to make 2DBezier, because it seem to be shorter and easier to use... but how to make and draw a 2DBezier is confusing me.

  • The koogs code make what I want actually

    woo!

    what jeremy said about being able to decompose beziers into multiple lower order beziers suggests that it'd be possible to write everything in terms of quadratic beziers. but you'd need quite a few. i can't remember ever being told this but it was a long time ago. (we did the maths behind the splines, joining them and then 3d patches, all stuff i still use occasionally)

    i've never used 3dshapes library(1) but it looks like it has a lot of things that i was just about to write my own library for (textured cubes not the least of it). will have to investigate.

    (1) i tend to avoid libraries because most of what i do is an attempt to work out for myself how to do geometrical things. also they get outdated.

    Actually I'm trying to use the 3DShapes to make 2DBezier, because it seem to be shorter and easier to use... but how to make and draw a 2DBezier is confusing me.

    can you post your control point coords so we can emulate?

  • can you post your control point coords so we can emulate?

    Of course :

    (416,272); // start point
    (376,424);
    (132,248);
    (120,176);
    (256,136);
    (392,176);
    (380,248);
    (136,424);
    (96,272);
    
  • Answer ✓

    Although you can decompose high degree to a number of lesser degree Bezier curves this still requires you to calculate new anchor points on the original curve. It is also possible and more common to increase the degree and still retain the original shape. This can be done mathematically

    The code below uses the Shapes3D library and your control points to produce this picture.

    curve

    import shapes3d.*;
    import shapes3d.animation.*;
    import shapes3d.utils.*;
    
    PVector[] points = {
      new PVector(416, 272), 
      new PVector(376, 424), 
      new PVector(132, 248), 
      new PVector(120, 176), 
      new PVector(256, 136), 
      new PVector(392, 176), 
      new PVector(380, 248), 
      new PVector(136, 424), 
      new PVector(96, 272)
    };
    
    Bezier2D bez  = new Bezier2D(points, points.length);
    
    PVector[] curve = bez.points(1000);
    
    void setup() {
      size(500, 500);
      background(0); 
      // Draw hull (green line)
      strokeWeight(1.2);
      stroke(0, 255, 0);
      for (int i = 1; i < points.length; i++)
        line(points[i-1].x, points[i-1].y, points[i].x, points[i].y);
      // Draw curve (white)
      strokeWeight(2);
      stroke(255);
      for (int i = 1; i < curve.length; i++)
        line(curve[i-1].x, curve[i-1].y, curve[i].x, curve[i].y);
      // Draw control points
      noStroke();
      fill(255, 255, 0);
      for (PVector cp : points)
        ellipse(cp.x, cp.y, 8, 8);
      save("curve.png");
    }
    
  • edited November 2016

    @quark Damn, that was easier than I thought. I'll use this so. @all Thanks a lot for your helps, you free me !

Sign In or Register to comment.