I have a question about arc()

I have a question about arc().

I’m not good at English, so I’m using machine translation.

The behavior below seems intuitive.

// P5.js

function setup(){
  createCanvas(200, 400);
}
function draw(){
  translate(0, height/2);
  background(0, 0, 0);
  noStroke();
  ellipseMode(RADIUS);
  fill(255, 255, 0); // yellow
  arc(0, -100, 200, 100, radians(-30), radians(30));
  fill(255, 0, 255); // magenta
  arc(0, 100, 200, 200, radians(-30), radians(30));
}

The behavior below seems counterintuitive to me.

// Processing3.5.4

size(200, 400);
translate(0, height/2);
background(0, 0, 0);
noStroke();
ellipseMode(RADIUS);
fill(255, 255, 0); // yellow
arc(0, -100, 200, 100, radians(-30), radians(30));
fill(255, 0, 255); // magenta
arc(0, 100, 200, 200, radians(-30), radians(30));

Is this a Processing spec?
What’s the difference between the two?
Is there a way to deal with it? I’d like to specify an intuitive angle for this program.

Thank you for reading this.

1 Like

I don’t know which should be more intuitive. But it is odd that those don’t match.
(That the two yellows, the yellow Processing and the yellow p5.js, do not match even though they take the same arguments)

p5.js

Processing (Java)

Perhaps you could open an issue on the Processing and/or p5.js github repo?

2 Likes

The third parameter in the two arc statement are not the same that’s explains the difference between the yellow and magenta arcs.

arc(0, -100, 200, 100, radians(-30), radians(30));
arc(0,  100, 200, 200, radians(-30), radians(30));
//                ^^^
1 Like

Hi all,

I’m guessing that variations in how arcs deal with nonuniform scales (where the width and height of the arc are different) would be of interest.

The implementation for the p5.js arc is here

Maybe p5.js rolls its own because the HTML5 canvas arc doesn’t support nonuniform scaling for an arc.

The Java AWT renderer uses an arc object, which it sets in draw

Looks like the AWT arc object does support non-uniform scaling, so the next step would be to look at a specification or the source code for that.

It might also be interesting to see how the SVG spec for arcs differs from HTML5 and AWT, and what Processing does to bridge any differences when importing.

Best,
Jeremy

5 Likes

It seems like the p5.js interpretation is an elliptical arc (a 60 degree slice of an ellipse)

The Java interpretation seems to be a circular arc scaled by the height/width ratio (a 60 degree slice, scaled by y=y*0.5).

4 Likes

Thank you for your reply.
What I think is more intuitive is the p5.js.
Because p5.js looks like it’s showing the angle I set in arc().
It may be a matter of difference of opinion as to which one you think is more intuitive.
Thank you so much for sharing github with me.

Thank you for your reply.
I may have asked the wrong question.
In Processing(Java), I’m wondering why the angle between yellow and magenta is different, even if the same angle is set between yellow and magenta.

Thank you for showing these images!

Thank you for your reply.
I first learned that Processing uses the AWT arc object.
I’m going to check it out.
Thank you for the detailed commentary.

The Java interpretation seems to be a circular arc scaled by the height/width ratio (a 60 degree slice, scaled by y=y*0.5).

It certainly looks like it.
I think that’s a great tips.
Thank you very much.

As I said before the difference between the colours is because you are not comparing like with like if you can the code as I suggested to

size(200, 400);
translate(0, height/2);
background(0, 0, 0);
noStroke();
ellipseMode(RADIUS);
fill(255, 255, 0); // yellow
arc(0, -100, 200, 200, radians(-30), radians(30));
fill(255, 0, 255); // magenta
arc(0, 100, 200, 200, radians(-30), radians(30));

then you get

There maybe a difference between the Javascript and Java rendering probably down to the implementations of ellipseMode(RADIUS);

1 Like

Thank you for explaining.

I tried about ellipseMode(RADIUS);.
I commented it out to remove its impact.
I made one arc for simplicity.

//Processing(Java)
size(200, 200);
translate(0, height/2);
background(0, 0, 0);
noStroke();
//ellipseMode(RADIUS);
fill(255, 255, 0); // yellow
arc(0, 0, 200, 100, radians(-30), radians(30));

Processing

//p5.js
function setup(){
  createCanvas(200, 200);
}
function draw(){
  translate(0, height/2);
  background(0, 0, 0);
  noStroke();
  //ellipseMode(RADIUS);
  fill(255, 255, 0); // yellow
  arc(0, 0, 200, 100, radians(-30), radians(30));
}

P5js

1 Like

Hello @356,

My exploration of this while doing laundry.
If I divide the angle by width/height ratio in the P5.js mode the results are the same as Processing Java mode in each ellipseMode().

A mouse click will toggle through the modes.

//Processing (Java)

int num = 0;

void setup()
  {
  size(200, 200);
  }
  
void draw()
  {
  background(0);
  translate(0, height/2);

  noStroke();
  
  switch(num)
    {
    case 0:
      ellipseMode(CENTER);
      break;
    case 1:
      ellipseMode(RADIUS);
      break;
    case 2:
      ellipseMode(CORNER);
      break;
    case 3:
      ellipseMode(CORNERS);
      break;
    default:
      ellipseMode(CENTER);
      break;
    }

  fill(0, 255, 0);
  ellipse(0, 0, 200, 100);

  fill(255, 255, 0); // yellow
  arc(0, 0, 200, 100, radians(-30), radians(30));  
  }
  
void mousePressed()
  {
  num++;
  if (num>4) num = 0;
  }

image

//p5.js (JavaScript)

let num = 0;

function setup()
  {
  createCanvas(200, 200);
  }

function draw()
  {
  background(0);
  translate(0, height/2);

  noStroke();
  
  switch(num)
    {
    case 0:
      ellipseMode(CENTER);
      break;
    case 1:
      ellipseMode(RADIUS);
      break;
    case 2:
      ellipseMode(CORNER);
      break;
    case 3:
      ellipseMode(CORNERS);
      break;
    default:
      ellipseMode(CENTER);
      break;
    }

  fill(0, 255, 0);
  ellipse(0, 0, 200, 100);

  fill(255, 255, 0); // yellow
  arc(0, 0, 200, 100, radians(-30)/2.0, radians(30/2.0));  
  }
  

function mousePressed()
  {
  num++;
  if (num>4) 
    {
    num = 0;
    }
  }

image

That was fun!

This was just a start…

:)

2 Likes

Hello @glv,

It’s an interesting program.
I think I’ve been given an important point of view.
Thank you.

1 Like

I was able to create the program as I envisioned it.
I’m not sure if it’s completely correct.
The white line is the 45-degree line of the landmark.
Note that the angle used for arc2() is not radian.
Also, ellipseMode() is not supported.
Other than that, I think it’s pretty much the same as Processing’s standard arc().

//Processing(Java)

void settings()
{
  size(200, 200);
}

void setup()
{
  background(0);
  stroke(255);
  line(0, height, width, 0);
  //translate(width/2, height/2);
  //translate(0, height/2);
  translate(0, height);
  noStroke();
  fill(255, 255, 0, 190); // yellow
  arc2(0, 0, 200, 100, -45, 0);  
}

void arc2(float x, float y, float w, float h, float startdeg, float stopdeg){
  println("arc2");
  float a = w/2;
  println("a:"+a);
  float b = h/2;
  println("b:"+b);
  float deg_step = 1;
  
  beginShape();
    vertex(x, y);
    float xp, yp;
    for(float i = startdeg; i <= stopdeg; i+=deg_step){
      println("i:"+i);
      xp = xc(a, b, i);
      yp = yc(xp, i);
      if(0 == i){
        xp = a;
        yp = 0;
      }else if( (0 < i) && (i < 90) ){  // 1st quadrant.
        xp = abs(xp);
        yp = abs(yp);
      }else if(90 == i){
        xp = 0;
        yp = b;
      }else if( (90 < i) && (i < 180) ){  // 2nd quadrant.
        xp = -abs(xp);
        yp = abs(yp);
      }else if(180 == i){
        xp = -a;
        yp = 0;
      }else if( (180 < i) && (i < 270) ){  // 3rd quadrant.
        xp = -abs(xp);
        yp = -abs(yp);
      }else if(270 == i){
        xp = 0;
        yp = -b;
      }else if( (270 < i) && (i < 360)){  //  4th quadrant.
        xp = abs(xp);
        yp = -abs(yp);
      }
      vertex(xp+x, yp+y);
    }
  endShape(CLOSE);
}

float xc(float a, float b, float theta_deg){
  float xc;
  xc = 1 / (
              sqrt(
                    sq(1/a) + sq(
                                  tan(
                                       radians(theta_deg)
                                     ) / b
                                )
                  )
           );
  println("xc:"+xc);
  return xc;
}
float yc(float xc, float theta_deg){
  float yc;
  yc = xc*tan(radians(theta_deg));
  println("yc:"+yc);
  return yc;
}

sketch_arc2

2 Likes