Trouble configuring bezier start and end points for uniform arc

I’d like to create a shape that is, in essence, two, uniform concentric arcs connected by lines (radius segments) so that I can fill them individually. I’ve come close to doing it with Bezier curves but it’s still not right. In Illustrator I see how the control points are configured to create the arc but I can’t seem to duplicate it in P5. I’ve attached a screenshot from Illustrator to depict the scenario. Maybe curveVertex would be easier?? Thanks for any insights!

1 Like

Hello,

Consider making it with just vertex().

Processing example:

void setup() 
  {
  size(200, 200);
  
  translate(width/2, height/2);
  
  fill(128);
  beginShape();
  vertex(0, 40);
  vertex(0, 50);
  vertex(50*cos(TAU/8), 50*sin(TAU/8));
  vertex(50, 0);
  vertex(40, 0);
  vertex(40*cos(TAU/8), 40*sin(TAU/8));
  endShape(CLOSE);
  
  noFill();
  circle(0, 0, 90);
  }

You can generate all the missing points with a for() loop and some trigonometry:
Trigonometry Primer \ Processing.org

image

:)

1 Like

Hello!,
Now that’s a fascinating idea I had not considered!! Thank you! I’ll give that a shot.

1 Like

Worked like a charm. Thanks again.

1 Like

Hi, if you still want to you brazier curve, what you wanna draw is a half circle.

Look online for how to approximate circle with bezier curves and it will gives you the values to input.

Hi @psemme ,

To draw an arc with the bezier() function, you just need to indicate the control points as you did in your picture from the vector based drawing software :

bezier1

You have two bezier curves (from left to right) that use the same middle point as anchor point.

The way the control points are computed is based on the ratio of the radius multiplied by the radius of the arc, see this animation :

bezier_anim bezier_anim_full_circle

So I found that to have an approximate circle shape, the ratio should be close to 0.555, don’t ask me why :wink: (it can surely be computed with math)

The only downside to this is that you can’t really fill two bezier curves without using beginShape and endShape as @glv wrote.

Note that you could have done it simply using the arc() function.

Here is the code (very verbose) to make that in Processing :

Unfold me ;)
void bezierArc(float x, float y, float diameter, float rotation, float strength, boolean debug) {
  float radius = diameter / 2.0;
  
  PVector leftAnchorPoint = new PVector(-radius, 0);
  PVector leftControlPoint = new PVector(-radius, -radius * strength);
  
  PVector middleAnchorPoint = new PVector(0, -radius);
  PVector middleControlPointLeft = new PVector(-radius * strength, -radius);
  PVector middleControlPointRight = new PVector(radius * strength, -radius);
  
  PVector rightAnchorPoint = new PVector(radius, 0);
  PVector rightControlPoint = new PVector(radius, -radius * strength);
  
  // Apply transform
  pushMatrix();
  translate(x, y);
  rotate(rotation);
  
  // Bezier curves
  stroke(0);
  strokeWeight(4);
  noFill();
  
  // Left portion
  stroke(#80C9A5);
  bezier(leftAnchorPoint.x, leftAnchorPoint.y,
         leftControlPoint.x, leftControlPoint.y,
         middleControlPointLeft.x, middleControlPointLeft.y,
         middleAnchorPoint.x, middleAnchorPoint.y);
  
  // Right portion
  stroke(#DD79DE);
  bezier(middleAnchorPoint.x, middleAnchorPoint.y,
         middleControlPointRight.x, middleControlPointRight.y,
         rightControlPoint.x, rightControlPoint.y,
         rightAnchorPoint.x, rightAnchorPoint.y);
  
  if (debug) {
    // Display handles
    stroke(#EA911C);
    strokeWeight(3);
    
    line(leftAnchorPoint.x, leftAnchorPoint.y, leftControlPoint.x, leftControlPoint.y);
    line(middleAnchorPoint.x, middleAnchorPoint.y, middleControlPointLeft.x, middleControlPointLeft.y);
    line(middleAnchorPoint.x, middleAnchorPoint.y, middleControlPointRight.x, middleControlPointRight.y);
    line(rightAnchorPoint.x, rightAnchorPoint.y, rightControlPoint.x, rightControlPoint.y);
    
    // Points
    float pointSize = 10;
    
    // Control points
    strokeWeight(pointSize);
    point(leftControlPoint.x, leftControlPoint.y);
    point(middleControlPointLeft.x, middleControlPointLeft.y);
    point(middleControlPointRight.x, middleControlPointRight.y);
    point(rightControlPoint.x, rightControlPoint.y);
    
    // Anchor points
    strokeWeight(4);
    fill(255);
    circle(leftAnchorPoint.x, leftAnchorPoint.y, pointSize + 0.1);
    circle(middleAnchorPoint.x, middleAnchorPoint.y, pointSize + 0.1);
    circle(rightAnchorPoint.x, rightAnchorPoint.y, pointSize + 0.1);
  }
  
  popMatrix();
}

float time = 0;

void setup() {
  size(300, 300);
}

void draw() {
  background(255);
  
  float strength = (cos(time) + 1) / 2.0;
  float circleSize = width * 0.8;
  
  translate(width / 2, height / 2);
  
  // Display reference circle
  noFill();
  stroke(#8395F5, 100);
  strokeWeight(6);
  circle(0, 0, circleSize);
  
  // Display rectangle
  rectMode(CENTER);
  stroke(100, 100);
  strokeWeight(3);
  square(0, 0, circleSize);
  
  // Display arcs
  bezierArc(0, 0, circleSize, 0, strength, true);
  bezierArc(0, 0, circleSize, PI, strength, true);
  
  // Display ratio text
  textAlign(CENTER, CENTER);
  textSize(20);
  fill(100);
  text(strength, 0, 0);
  
  time += 0.02;
}

I made this post to explain you how you can effectively use bezier curves to make your own arc function (half circle) but you can have fun with this by animating the parameters :yum: :

bezier_anim_rotate

@psemme

And another way which overlays shapes with different strokeWidth():

I used:
strokeCap(PROJECT); // This seemed to provide square ends

This easy to do with arc() as well:
image

:)

Thanks jb4x - I looked online and saw some entries on what values to use. I’ll give it a try. Thx again.

Hi Joseph - that’s a seriously thorough answer! Thank you! I like the solution from @giv because I can both fill the shape and then manipulate the vertices further in another step. But you’ve opened my eyes on the possibilities of animating beziers! Thanks again.

1 Like

Thanks @giv - I used that approach earlier and it works great, but I like the option of playing with the vertices that make up the original shape, in some later step, and the strokeWeight approach doesn’t allow that. Thanks for continuing to think up answers!

1 Like