Arcs and angles with PI (wings)

Hi there! I’m trying to draw some arcs with right angle, but I can’t understand how to use PI in processing. Doing some test I was able to make an angle from 0 to 90°, but I don’t know how to draw another from 135° to 45° and from 45° to 135°, could you please help me?

void setup() {

size(500,500);
noFill();
drawBirds();
}

void draw() {
}

void drawBirds() {

float a = random(width);
float b = random(height);

arc(a,b,100,100,TWO_PI - HALF_PI, TWO_PI);
arc(a+100,b,100,100, PI, TWO_PI - HALF_PI);
noLoop();
//}
//}
}


13a95737d5d457743a7dce924a8d43fc-0

0° is in the east, but then it’s clockwise

see arc() / Reference / Processing.org


//

void setup() {
  size(1000, 600);
  noFill();
}

void draw() {
  drawBirds();
}

void drawBirds() {

  float a = (width/2);
  float b = height/2;

  // RED
  fill(255, 3, 3 );
  arc(a, b,
    100, 100,
    radians(0), radians(44));

  // GREEN
  fill(2, 255, 3 );
  arc(a+300, b,
    100, 100,
    PI, PI+radians(44));

  noLoop();
  //}
  //}
}

2 Likes

When graphing in mathematics the positive x angle points east and the positive y axis points north and the angle increases as the radius rotates anti-clockwise. This can be seen in your picture.

In computer graphics the x axis is unchanged but the positive y axis points south and the angle increases as the radius rotates clockwise. You need to be aware of this when programming.

If you are uncomfortable using Pi then use the radians method - your program becomes

void setup() {
  size(500, 500);
  noFill();
  drawBirds();
}

void draw() {
}

void drawBirds() {
  float a = width/4;
  float b = height/2;

  arc(a, b, 100, 100, radians(270), radians(360));
  arc(a+100, b, 100, 100, radians(180), radians(270));

  noLoop();
  //}
  //}
}

I suspect that you are trying to simulate a bird flapping its wings. Simply changing the arc angles will not work properly because the two arcs will not touch without moving the arc centres.

2 Likes

You are right. The radians method is easier for me, but now I can not join both arcs just adding 100 to x coordinate. :sweat_smile: How could I draw second arc where the first one ends?

void setup() {
  size(500, 500);
  noFill();
  drawBirds();
}

void draw() {
}

void drawBirds() {
  float a = width/4;
  float b = height/2;

  arc(a, b, 100, 100, radians(225), radians(315));
  arc(a+100, b, 100, 100, radians(225), radians(315));

  noLoop();
  
}
1 Like

Here is an example.

You can shorten showCircleOnCircumferenceAtDegree a lot; mainly it calculates the PVector - but we use only pv1.x, so it’s not necessary to calculate y as well.

Chrisir



void setup() {
  size(500, 500);
  noFill();
  drawBirds();
}

void draw() {
}

void drawBirds() {
  float a = width/4;
  float b = height/2;

  arc(a, b, 100, 100, radians(225), radians(315));

  // get the right end point of the left wing
  PVector pv1 = showCircleOnCircumferenceAtDegree (a, b, 315);

  // calc center of the right wing from here
  float a1 = pv1.x + cos( radians(315)) * 50;
  arc(a1, b, 100, 100, radians(225), radians(315));

  noLoop();
}


PVector showCircleOnCircumferenceAtDegree ( float a_, float b_,
  float angleDegree_ ) {

  float angleRadians = radians(angleDegree_);
  float rad = 50;

  // calc pos x1,y1 of small circle on the circumference / at angleDegree_
  float x1 = a_ + cos(angleRadians) * rad ;
  float y1 = b_ + sin(angleRadians) * rad ;

  // draw small circle
  circle(x1, y1, 11);

  pushMatrix();
  translate(x1, y1);
  rotate(angleRadians);
  translate(22, 0);
  text(angleDegree_, 0, 0);
  popMatrix();

  return new PVector(x1, y1);
}

1 Like

In this image the green arcs represent what you have so far. If we forget the arc angles then we can see that each arc res[resents a quarter circle centered on the green dots.

Scan 1

The red arcs are also quarter circles but to get the ends to meet we have to move the circle centers to the red dots.

Using pure geometry to calculate the circle centers and the arc angle limits is challenging but we can make use of Processing to simplify the mathematics required.

The following sketch draws 3 birds on the screen and animates their wings. The method drawBird can be simply copied and pasted into your own sketch.

final float CHANGE = 0.02;
float t = 0;
float dt = CHANGE;

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

void draw() {
  background(200, 200, 255);
  t += dt;
  if (t < 0) {
    t = 0;
    dt = CHANGE;
  } else if (t > 1) {
    t = 1;
    dt = - CHANGE;
  }
  drawBird(200, 200, 60, t);
  drawBird(100, 80, 20, t);
  drawBird(290, 340, 45, t);
}

/*
Function to draw a bird at any position. This function is autonomous in that it dors
 not affact any graphic settings used in
 
 [x, y] are the coordinates to draw the bird. In other words where the wings meet.
 rad is the radius of the arc used for the wing
 t is a parametric parameter whose valoe should be in the rangle 0 to 1 and is used
 to animate the wing positions.
 */
void drawBird(float x, float y, float rad, float t) {
  float angle = t * PI/2;  // Change this to define end of downward wing movment
  push();  // save the graphic context / settings
  translate(x, y); // move drawing origin to where wings will touch
  stroke(0);
  strokeWeight(1.5);
  noFill();
  // Right wing
  float cx = rad * cos(angle);
  float cy = rad * sin(angle);
  push();
  translate(cx, cy); // move origin to circle centre
  rotate(angle);
  arc(0, 0, rad*2, rad*2, PI, 1.5 * PI);
  pop();
  // left wing
  cx = -cx;
  push();
  translate(cx, cy); // move origin to circle centre
  rotate(-angle);
  arc(0, 0, rad*2, rad*2, -0.5 * PI, 0);
  pop();
  pop(); // restore the graphic context / settings
}
3 Likes

Thank you so much! that code is amazing! I have a new problem now, I am using it to draw three models of static birds, as you can see on the picture, but I can’t draw model III and I don’t understand why? Could you please help me?

void setup() {
  size(500, 500);
  noFill();
  drawBirds();
}

void draw() {
}

void drawBirds() {
  float a = width/4;
  float b = height/2;
  float c = width/2;
  float d = height/4;
  float e = width/3;
  float f = height/3;
  

  arc(a, b, 100, 100, radians(225), radians(315));
  // get the right end point of the left wing
  PVector pv1 = showCircleOnCircumferenceAtDegree (a, b, 315);
  // calc center of the right wing from here
  float a1 = pv1.x + cos( radians(315)) * 50;
  arc(a1, b, 100, 100, radians(225), radians(315));
  
  arc(c, d, 100, 100, radians(270), radians(360));
  PVector pv2 = showCircleOnCircumferenceAtDegree (a, b, 360);
  float a2 = pv2.x + cos( radians(360)) * 50;
  arc(c, d, 100, 100, radians(180), radians(270));
  
  arc(e, f, 100, 100, radians(180), radians(270));
  PVector pv3 = showCircleOnCircumferenceAtDegree (a, b, 2180);
  float a3 = pv3.x + cos( radians(180)) * 50;
  arc(e, f, 100, 100, radians(270), radians(360));
  
  noLoop();
}


PVector showCircleOnCircumferenceAtDegree ( float a_, float b_,
  float angleDegree_ ) {

  float angleRadians = radians(angleDegree_);
  float rad = 50;

  // calc pos x1,y1 of small circle on the circumference / at angleDegree_
  float x1 = a_ + cos(angleRadians) * rad ;
  float y1 = b_ + sin(angleRadians) * rad ;

 
  pushMatrix();
  translate(x1, y1);
  rotate(angleRadians);
  translate(22, 0);
  //text(angleDegree_, 0, 0);
  popMatrix();

  return new PVector(x1, y1);
}

here


void setup() {
  size(500, 500);
  noFill();
}

void draw() {
  drawBirds();
}

void drawBirds() {
  float x1 = width/4;
  float y1 = height/2;
  float x2 = width/2;
  float y2 = height/4;
  float x3 = width/3;
  float y3 = height/3;

  float rightWingCenterX ;

  // draw left wing
  stroke(255, 2, 2);
  arc(x1, y1, 100, 100, radians(225), radians(315));
  // get the right end point of the left wing
  PVector pv1 = getPVectorOfPositionOnCircumferenceAtDegree (x1, y1, 315);
  // calc center of the right wing from here
  rightWingCenterX = pv1.x + cos( radians(315)) * 50;
  stroke(2, 255, 2);
  arc(rightWingCenterX, y1, 100, 100, radians(225), radians(315));

  stroke(55, 122, 2);
  arc(x2, y2, 100, 100, radians(270), radians(360));
  PVector pv2 = getPVectorOfPositionOnCircumferenceAtDegree (x2, y2, 360);
  rightWingCenterX = pv2.x + cos( radians(360)) * 50;
  stroke(2, 55, 122);
  arc(rightWingCenterX, y2, 100, 100, radians(180), radians(270));

  stroke(255, 2, 255);
  arc(x3, y3, 100, 100, radians(200), radians(290));
  PVector pv3 = getPVectorOfPositionOnCircumferenceAtDegree (x3, y3, 290);
  rightWingCenterX = pv3.x + cos(radians(290)) * 50;
  stroke(2, 255, 2);
  arc(rightWingCenterX, y3, 100, 100, radians(250), radians(250+90));

  noLoop();
}

// ----------------------------------------------------------------------------


PVector getPVectorOfPositionOnCircumferenceAtDegree ( float x_, float y_, // center
  float angleDegree_ ) {                       // angle on Circumference in degrees

  // returns start- or endpoint of an arc()

  float angleRadians = radians(angleDegree_);
  float rad = 50;

  // calc pos x1,y1 of small circle on the circumference / at angleDegree_
  float xOnCircumference = x_ + cos(angleRadians) * rad ;
  float yOnCircumference = y_ + sin(angleRadians) * rad ;

  return new PVector(xOnCircumference, yOnCircumference);
}

2 Likes

and new version with strokeWeight and an angle


void setup() {
  size(500, 500);
  noFill();
}

void draw() {
  drawBirds();
}

void drawBirds() {
  float x1 = width/4;
  float y1 = height/2;
  float x2 = width/2;
  float y2 = height/4;
  float x3 = width/3;
  float y3 = height/3;

  float rightWingCenterX;

  strokeWeight(3);

  // draw left wing
  arc(x1, y1, 100, 100, radians(225), radians(315));
  // get the right end point of the left wing
  PVector pv1 = getPVectorOfPositionOnCircumferenceAtDegree (x1, y1, 315);
  // calc center of the right wing from here
  rightWingCenterX = pv1.x + cos(radians(315)) * 50;
  arc(rightWingCenterX, y1, 100, 100, radians(225), radians(315));

  arc(x2, y2, 100, 100, radians(270), radians(360));
  PVector pv2 = getPVectorOfPositionOnCircumferenceAtDegree (x2, y2, 360);
  rightWingCenterX = pv2.x + cos(radians(360)) * 50;
  arc(rightWingCenterX, y2, 100, 100, radians(180), radians(270));

  rotate (0.193);
  arc(x3, y3, 100, 100, radians(200), radians(290));
  PVector pv3 = getPVectorOfPositionOnCircumferenceAtDegree (x3, y3, 290);
  rightWingCenterX = pv3.x + cos(radians(290)) * 50;
  arc(rightWingCenterX, y3, 100, 100, radians(250), radians(250+90));

  noLoop();
}

// ----------------------------------------------------------------------------


PVector getPVectorOfPositionOnCircumferenceAtDegree ( float x_, float y_, // center
  float angleDegree_ ) {                       // angle on Circumference in degrees

  // returns start- or endpoint of an arc()

  float angleRadians = radians(angleDegree_);
  float rad = 50;

  // calc pos x1,y1 of small circle on the circumference / at angleDegree_
  float xOnCircumference = x_ + cos(angleRadians) * rad ;
  float yOnCircumference = y_ + sin(angleRadians) * rad ;

  return new PVector(xOnCircumference, yOnCircumference);
}

2 Likes

new version with a drawBird() function

works with different diameters

void setup() {
  size(1200, 500);
  noFill();
  noLoop();
}

void draw() {
  drawBirds();
}

void drawBirds() {
  float x1 = width/4;
  float y1 = height/2+122;
  float x2 = width/2;
  float y2 = height/4;
  float x3 = width/3;
  float y3 = height/3;

  strokeWeight(3);

  drawBird(x1, y1, 225, 315, 225, 315, 60);
  drawBird(x2, y2, 270, 360, 180, 270, 110);
  rotate(0.193);
  drawBird(x3, y3, 200, 290, 250, 250+90, 50);
}

// ----------------------------------------------------------------------------

void drawBird(float x1, float y1, // center left wing
  float a1, float a2, // angles left wing
  float a3, float a4, // angles right wing
  float diameter ) {    // diameter

  float rightWingCenterX;

  // draw left wing
  arc(x1, y1, diameter, diameter, radians(a1), radians(a2));

  // get the right end point of the left wing
  PVector pv1 = getPVectorOfPositionOnCircumferenceAtDegree (x1, y1, a2, (diameter/2));

  // calc center X of the right wing from here
  rightWingCenterX = pv1.x + cos(radians(a2)) * (diameter/2);

  // draw right wing
  arc(rightWingCenterX, y1, diameter, diameter, radians(a3), radians(a4));
}

// ----------------------------------------------------------------------------

PVector getPVectorOfPositionOnCircumferenceAtDegree ( float x_, float y_, // center
  float angleDegree_, // angle on Circumference in degrees
  float radius_) {    // Radius

  // returns start- or endpoint of an arc()

  float angleRadians = radians(angleDegree_);

  // calc pos x1,y1 of small circle on the circumference / at angleDegree_
  float xOnCircumference = x_ + cos(angleRadians) * radius_ ;
  float yOnCircumference = y_ + sin(angleRadians) * radius_ ;

  return new PVector(xOnCircumference, yOnCircumference);
}
//

2 Likes

Thank you again, my brain is exploding! And now that I have my three models of bird, do you know why my loop does not work?

void setup() {
  size(500, 500);
  noFill();
}

void draw() {
  drawBirds();
}

void drawBirds() {
  
  
  float x1 = random(width);
  float y1 = random(height);
  float x2 = random(width);
  float y2 = random(height);
  float x3 = random(width);
  float y3 = random(height);

  float rightWingCenterX ;
  
  
  for(int i=0; i<100; i+=1){
  for(int j=0; j<100;  j+=1){

    
  if(random(1)>0.5) {
  // draw left wing
  arc(x1, y1, 100, 100, radians(225), radians(315));
  // get the right end point of the left wing
  PVector pv1 = getPVectorOfPositionOnCircumferenceAtDegree (x1, y1, 315);
  // calc center of the right wing from here
  rightWingCenterX = pv1.x + cos( radians(315)) * 50;
  arc(rightWingCenterX, y1, 100, 100, radians(225), radians(315));
  }
  else if(random(1)>0.3) {
  arc(x2, y2, 100, 100, radians(270), radians(360));
  PVector pv2 = getPVectorOfPositionOnCircumferenceAtDegree (x2, y2, 360);
  rightWingCenterX = pv2.x + cos( radians(360)) * 50;
  arc(rightWingCenterX, y2, 100, 100, radians(180), radians(270));
  }
  else{
  arc(x3, y3, 100, 100, radians(180), radians(270));
  PVector pv3 = getPVectorOfPositionOnCircumferenceAtDegree (x3, y3, 270);
  rightWingCenterX = pv3.x + cos(radians(270)) * 50;
  arc(rightWingCenterX, y3, 100, 100, radians(270), radians(360));
  }
  noLoop();
}
}
}

// ----------------------------------------------------------------------------


PVector getPVectorOfPositionOnCircumferenceAtDegree ( float x_, float y_, // center
  float angleDegree_ ) {                       // angle on Circumference in degrees

  // returns start- or endpoint of an arc()

  float angleRadians = radians(angleDegree_);
  float rad = 50;

  // calc pos x1,y1 of small circle on the circumference / at angleDegree_
  float xOnCircumference = x_ + cos(angleRadians) * rad ;
  float yOnCircumference = y_ + sin(angleRadians) * rad ;

  return new PVector(xOnCircumference, yOnCircumference);
}

You still have noLoop() on?

In how far doesn’t it work?

What do you want to see and what do you see in reality?

Something like this, but with those 3 different models that have complicated a bit the code :sweat_smile:

void setup() {

size(500,500);
noFill();
drawBirds();
}

void draw() {
}

void drawBirds() {

for(int i=0; i<500; i+=100){
for(int j=0; j<500; j+=50){


float a = random(width);
float b = random(height);

arc(a,b,100,100,TWO_PI - HALF_PI, TWO_PI);
arc(a+100,b,100,100, PI, TWO_PI - HALF_PI);
noLoop();
}
}
}
1 Like

Maybe you mean this:

To see a change in position you need to move these lines into the for-loop section

1 Like
  • here you can hit any key to make a new image
  • better random number handling in if…else if…
  • last bird has random angle

You could make more variety by using random size and random angle.

Remember to hit ctrl-t in the code to get auto-format for your Sketch (indents and the like). Nice.

Chrisir

void setup() {
  size(1500, 500);
  noFill();
  drawBirds();
}

void draw() {
  //
}

void keyPressed() {
  drawBirds();
}

// -------------------------------------------------------------------------------------

void drawBirds() {
  background (#79C3F0);//  (#0DE4FA); // !!!!

  final float dist=35; // from border // !!!!
  float rightWingCenterX;

  for (int i=0; i<100; i+=21) {
    for (int j=0; j<100; j+=21) {

      float x1 = random(dist, width-dist);
      float y1 = random(dist, height-dist);
      float x2 = random(dist, width-dist);
      float y2 = random(dist, height-dist);
      float x3 = random(dist, width-dist);
      float y3 = random(dist, height-dist);

      // make random number  // !!!!!!
      float numberRandom = random(1);
      // evaluate the number
      if (numberRandom >0.66) {
        // Bird 1: wings in the middle, same angle value for both wings
        // draw left wing
        arc(x1, y1, 100, 100, radians(225), radians(315));
        // get the right end point of the left wing
        PVector pv1 = getPVectorOfPositionOnCircumferenceAtDegree (x1, y1, 315);
        // calc center of the right wing from here
        rightWingCenterX = pv1.x + cos( radians(315)) * 50;
        arc(rightWingCenterX, y1, 100, 100, radians(225), radians(315));
      } else if (numberRandom <0.3333) {
        // Bird 2: wings are very high up
        arc(x2, y2, 100, 100, radians(270), radians(360));
        PVector pv2 = getPVectorOfPositionOnCircumferenceAtDegree (x2, y2, 360);
        rightWingCenterX = pv2.x + cos( radians(360)) * 50;
        arc(rightWingCenterX, y2, 100, 100, radians(180), radians(270));
      } else {
        // Bird 3: wings are low (can be low, can be high, random) // !!!
        float add;
        add = random(11, 28); // (17,88)
        arc(x3, y3, 100, 100, radians(180+add), radians(270+add));
        PVector pv3 = getPVectorOfPositionOnCircumferenceAtDegree (x3, y3, 270+add);
        rightWingCenterX = pv3.x + cos(radians(270+add)) * 50;
        arc(rightWingCenterX, y3, 100, 100, radians(270-add), radians(360-add));
      }
    }
  }
}

// ----------------------------------------------------------------------------


PVector getPVectorOfPositionOnCircumferenceAtDegree ( float x_, float y_, // center
  float angleDegree_ ) {                       // angle on Circumference in degrees

  // returns start- or endpoint of an arc()

  float angleRadians = radians(angleDegree_);
  float rad = 50;

  // calc pos x1,y1 of small circle on the circumference / at angleDegree_
  float xOnCircumference = x_ + cos(angleRadians) * rad ;
  float yOnCircumference = y_ + sin(angleRadians) * rad ;

  return new PVector(xOnCircumference, yOnCircumference);
}
//

2 Likes

Well done to @chrisir for managing to do all that mathematics and come up with a solution. As I said in my previous post we can simplify the code dramatically by using the graphic functions provided by Processing i.e. push, pop, translate and rotate. These functions are essential for any serious graphical programming so are well worth getting familiar with.

I have made minor modifications to the drawBird function in my last code to include a parameter to control the horizontal angle of the bird. I have also removed the animation code to reduce complexity. This is the result.

birds

The birdDraw function has two useful features.

  1. The code is simple so easily comprehensible (especially to other programmers)
  2. Most of the work is done by Processing and the graphics processor which is always a good thing :grinning:
void setup() {
  size(400, 300);
}

void draw() {
  background(200, 200, 255);
  drawBird(200, 200, 0, 60, 0);
  drawBird(100, 80, radians(20), 20, 0.9);
  drawBird(290, 240, radians(-30), 45, 0.5);
}

/*
Function to draw a bird at any position. This function is autonomous in that it dors
 not affact any graphic settings used in
 
 [x, y] are the coordinates to draw the bird. In other words where the wings meet.
 ang is the angle the bird makes with the horizontal
 wingRad is the radius of the arc used for the wing
 t is a parametric parameter whose valoe should be in the rangle 0 to 1 and is used
 to animate the wing positions.
 */
void drawBird(float x, float y, float ang, float wingRad, float t) {
  float angle = t * PI/2;  // Change this to define end of downward wing movment
  push();  // save the graphic context / settings
  translate(x, y); // move drawing origin to where wings will touch
  rotate(ang);
  stroke(0);
  strokeWeight(1.5);
  noFill();
  // Right wing
  float cx = wingRad * cos(angle);
  float cy = wingRad * sin(angle);
  push();
  translate(cx, cy); // move origin to circle centre
  rotate(angle);
  arc(0, 0, wingRad * 2, wingRad * 2, PI, 1.5 * PI);
  pop();
  // left wing
  cx = -cx;
  push();
  translate(cx, cy); // move origin to circle centre
  rotate(-angle);
  arc(0, 0, wingRad * 2, wingRad * 2, -0.5 * PI, 0);
  pop();
  pop(); // restore the graphic context / settings
}
4 Likes

Yeah, I was trying to follow OP’s trajectory since he didn’t follow your code and also didn’t use my function drawBirds

So I dropped those…

But he did a great job!

2 Likes

Hello @humano,

An example for you to scrutinize:

// Rotating arcs with transformations
// Author: GLV
// Date: 2023-09-23
// Angles are in degrees

size(500, 500, P2D);
background(0);
noFill();

//float a = random(width);
//float b = random(height);

float a = width/2;
float b = height/2;

stroke(255, 0, 0);
strokeWeight(3);
arc(a, b,  100, 100,  radians(135), radians(45 + 360)); // 135 to 45; add 360 if clockwise arc equals or crosses 0 
  
stroke(0, 255, 0);  
circle(width/2-20, height/2-5, 10);  
circle(width/2+20, height/2-5, 10);       
                                                                
stroke(0, 255, 0);
arc(a, b,  100, 100,  radians(45), radians(135)); // 45 to 135

// Step 1 Make initial arc that you can easily rotate.
push();
translate(100, 100);
stroke(255, 0, 0);
circle(0, 0, 5);
stroke(0, 255, 0);
arc(50, 0,  100, 100,  radians(180), radians(270));
pop();

// Step 2 Rotate.
push();
translate(250, 100);
stroke(255, 0, 0);
circle(0, 0, 5);
rotate(radians(45));
stroke(0, 255, 0);
arc(50, 0,  100, 100,  radians(180), radians(270));
pop();

// Step 3 Arcs in a loop
translate(400, 100);
stroke(255, 0, 0);
circle(0, 0, 5);
for(int i=0; i<6; i++)
  {  
  push();
  rotate(radians(i*22.5));
  stroke(0, 255, 0);
  arc(50, 0,  100, 100,  radians(180), radians(270));
  pop();
  }

References:

:)

1 Like