Creating my own Processing arc method

The Processing arc() command isn’t robust enough for my tastes so I wrote a new one that gives me more control over the things I care about. Along the way it lets me validate my arc code for the Makelangelo’s support of gcode commands G02 and G03. If people are learning Gcode then their arc() command would be helpful if it looked the same as a gcode command. Don’t you agree?

Gcode G02 and G03

G02 X[decimal number] Y[decimal number] I[decimal number] J[decimal number];
G03 X[decimal number] Y[decimal number] I[decimal number] J[decimal number];

  • G02 indicates a clockwise arc.
  • G03 is a counter-clockwise arc.
  • Arcs begin at the current tool location.
  • Arcs end at (X,Y).
  • Arc center is (I,J).

I’m going to make a processing method that follows the same format.

drawArc(float sx,float sy,float ex,float ey,float cx,float cy,boolean cw)

  • cw=true is a G02 clockwise arc.
  • cw=false is a G03 counter-clockwise arc.
  • Arcs begin at (sx,sy).
  • Arcs end at (ex,ey).
  • Arc center is (cx,cy).

This method works even if the arc is not a perfect circle.

The processing arc example code

/**
 * Illustrating G02 (clockwise) and G03 (counter-clockwise) arcs.
 * 2016-06-29 Dan Royer ([email protected])
 * CC-by-SA
 */
void setup() {
  size(500,500);
  drawOneRandomArc();
  //drawArc(250+125,250+0,250+0,250+125,250+0,250+0,true);
}

void draw() {}


void drawOneRandomArc() {
  // start of arc
  float sx = random(width);
  float sy = random(height);
  // end of arc
  float ex = random(width);
  float ey = random(height);
  // center of arc
  float cx = random(width);
  float cy = random(height);
  
  boolean clockwise = (random(2)==1);

  stroke(random(255),random(255),random(255));
  drawArc(sx,sy,ex,ey,cx,cy,clockwise);
}



// returns angle of dy/dx as a value from 0...2PI
float atan3(float dy,float dx) {
  float a=atan2(dy,dx);
  if(a<0) a=(PI*2.0)+a;
  return a;
}


// draw an arc
void drawArc(float sx,float sy,float ex,float ey,float cx,float cy,boolean cw) {
  println("start =("+sx+","+sy+")");
  println("end =("+ex+","+ey+")");
  println("center =("+cx+","+cy+")");
  println("clockwise="+cw);
  
  // start radius
  float dx = sx - cx;
  float dy = sy - cy;
  float angle1=atan3(dy,dx);
  float sr=sqrt(dx*dx+dy*dy);
  // end radius
  dx = ex - cx;
  dy = ey - cy;
  float angle2=atan3(dy,dx);
  float er=sqrt(dx*dx+dy*dy);

  // find angle of arc (sweep)
  float sweep=angle2-angle1;

  if(!cw && sweep<0) angle2+=2*PI;
  else if(cw && sweep>0) angle1+=2*PI;

  sweep = angle2-angle1;
  float dr = er-sr;
  println("angle1="+angle1);
  println("angle2="+angle2);
  println("sweep="+sweep);
  println("delta radius="+dr);

  println("green is start");
  stroke(0,255,0);
  line(cx,cy,sx,sy);
  println("red is end");
  stroke(255,0,0);
  line(cx,cy,ex,ey);
    
  // get length of arc
  // float circ=PI*2.0*radius;
  // float len=theta*circ/(PI*2.0);
  // simplifies to
  float len1 = abs(sweep) * sr;
  float len = sqrt( len1 * len1 + dr * dr );

  int i, segments = max( ceil( len / 10 ), 1);
  float r, nx, ny, a, scale;

  strokeWeight(2);
  println("segments="+segments);
  for(i=0;i<=segments;++i) {
    // interpolate around the arc
    scale = ((float)i)/((float)segments);
    a = sweep * scale + angle1;
    r = dr * scale + sr;
    //print("R="+r);
    //println("\tS="+scale);
    nx = cx + cos(a) * r;
    ny = cy + sin(a) * r;
    // send it to the planner
    stroke(scale*255,255-scale*255,0);
    line(sx,sy,nx,ny);
    sx = nx;
    sy = ny;
  }
}

How the processing arc code would work in a CNC machine

The stroke() command would be removed. The line() command would be send to the layer that does the Inverse Kinematics and then runs Bresenham’s algorithm to move the motors along the line. We piggy back on the existing G00/G01 line ability to make our arcs.

Now you try

Copy the Processing arc code from Github into Processing and draw some choice arcs. Make a happy face. Write the same arcs as gcode commands. Load them in the Makelangelo. Draw your happy face on a piece of paper with the robot. Tweet me a pic.