A rule of 2D graphics states that to draw holes in an object, the hole must be drawn in the reverse order of the outer shape.

Ie. for a circle, you draw the outer diameter clockwise, and the inner one counter-clockwise. Or the reverse.

That said, how to draw a circle in a defined direction? I recently discovered that Java draws them using four CubicCurves, our Bézier curves, with a ratio between control vector and radius of 0.552.

I tried and indeed it matches closely the drawing of an ellipse.

The remainder was then quite simple to do.

It seems to work well.

**Code:**// Clockwise

void drawCircleCW(float x, float y, float w, float h)

{

// Java draws circles using four cubic curves too, with ratio of length of control vector

// against radius of 0.552. I compute the complement of this ratio for convenience.

float l = 1 - 0.552;

float hw = w / 2, hh = h / 2;

float lx = l * hw, ly = l * hh;

// Assume here default CENTER mode

x -= hw; y -= hh;

vertex(x, y + hh); // Left

bezierVertex(x, y + ly,

x + lx, y,

x + hw, y); // Top

bezierVertex(x + w - lx, y,

x + w, y + ly,

x + w, y + hh); // Right

bezierVertex(x + w, y + h - ly,

x + w - lx, y + h,

x + hw, y + h); // Bottom

bezierVertex(x + lx, y + h,

x, y + h - ly,

x, y + hh); // Back to left

}

// Counter Clockwise

void drawCircleCCW(float x, float y, float w, float h)

{

float l = 1 - 0.552;

float hw = w / 2, hh = h / 2;

float lx = l * hw, ly = l * hh;

// Assume here default CENTER mode

x -= hw; y -= hh;

vertex(x, y + hh); // Left

bezierVertex(x, y + h - ly,

x + lx, y + h,

x + hw, y + h); // Bottom

bezierVertex(x + w - lx, y + h,

x + w, y + h - ly,

x + w, y + hh); // Right

bezierVertex(x + w, y + ly,

x + w - lx, y,

x + hw, y); // Top

bezierVertex(x + lx, y,

x, y + ly,

x, y + hh); // Back to left

}

// Draw a ring, assuming it is circular (not an ellipse),

// but accepting that the internal circle isn't centered on the external one

void drawRing(

float xx, float xy, float xd, // Center of external circle and its diameter

float ix, float iy, float id) // Center of internal circle and its diameter

{

beginShape();

drawCircleCCW(xx, xy, xd, xd);

drawCircleCW(ix, iy, id, id);

endShape();

}

void setup()

{

size(500, 500);

noLoop();

noStroke();

background(222);

// To verify it fits to a circle

fill(#FF0000);

ellipse(width/2, height/2, 200, 200);

// Draw test ring

fill(0x8800EE00);

drawRing(width/2, height/2, 200,

width/2, height/2, 100);

// Draw some others

fill(0x440000EE);

for (int i = 0; i < 5; i++)

{

float rxd = width / random(1.5, 5);

float rxx = random(rxd / 2, width - rxd / 2);

float rxy = random(rxd / 2, height - rxd / 2);

float rid = rxd / random(2, 4);

float rix = rxx + rid * random(-0.9, 0.9) / 4;

float riy = rxy + rid * random(-0.9, 0.9) / 4;

drawRing(rxx, rxy, rxd, rix, riy, rid);

}

}