The Allegro Wiki is migrating to github at https://github.com/liballeg/allegro_wiki/wiki

# NewAPI/Primitives/al draw circle

Planned variations: Just filled and outlined so far. In theory, a gradient one can be made as well. A thick outlined circle is also feasible.

## Outlined Circle

Goals:

• Use the Bresenham criterion for the pixel placement
• When x and y and r are integers, the output should be precisely like do_circle from allegro 4.4 branch - Done

Problems with the code so far:

• Circle loses its symmetry when not predicted by the location of the circle... e.g. a circle at (0, 0.5) should be symmetrical around the y axis, but this algorithm creates an asymmetrical one

Potential fixes:

• Given my experience with the line drawer, it seems that a good approach at this would be to switch the order of the worker macros to do their operations in this order
1. Handle the non-driving axis first (the error check module)
2. Plot point
3. Handle the driving axis
• That seemed to work well with the line drawer (basically, it fixed all of the problems instantaneously), so perhaps similar success can be had here

A4 test code:

<highlightSyntax language="cpp"> void al_do_circle(BITMAP *bmp, float x, float y, float radius, int d, void (*proc)(BITMAP *, int, int, int)) {

```   if(radius < 1)
{
proc(bmp, x, y, d);
return;
}
int X, Y;//initial int values
float fX, fY;//the floating point versions of the above
float a, b;//fractional differences between the integer center, and the the float center
int ix, iy;//integer center coordinates
float xchange, ychange;

ix = floorf(x);
iy = floorf(y);
a = x - float(ix);
b = y - float(iy);

```

#define YDEP(whiletest, Xsign, Comp, Ysign) \ while(whiletest) \ { \ proc(bmp, X + ix, Y + iy, d); \ Y += Ysign 1; \ error += ychange; \ ychange += 2.0; \ if(2.0 * error + xchange Comp 0) \ { \ X += Xsign 1; \ error += xchange; \ xchange += 2.0; \ } \ }

#define XDEP(whiletest, Xsign, Comp, Ysign) \ while(whiletest) \ { \ proc(bmp, X + ix, Y + iy, d); \ X += Xsign 1; \ error += xchange; \ xchange += 2.0; \ if(2.0 * error + ychange Comp 0) \ { \ Y += Ysign 1; \ error += ychange; \ ychange += 2.0; \ } \ }

X = 0; Y = (int)floorf(-sqrtf(radius * radius - (float(ix) - x) * (float(ix) - x)) + y + 0.5f) - iy;

fX = X; fY = Y;

float error = fX * fX + fY * fY - radius * radius + a * (a - 2 * fX) + b * (b - 2 * fY);

xchange = 1.0 + 2.0 * (fX - a); ychange = 1.0 + 2.0 * (fY - b);

XDEP(X < -Y, +, >, +) YDEP(Y < 0, +, <, +)

fX = X; fY = Y; xchange = 1.0 - 2.0 * (fX - a); ychange = 1.0 + 2.0 * (fY - b);

YDEP(X > Y, -, >, +) XDEP(X > 0, -, <, +)

fX = X; fY = Y; xchange = 1.0 - 2.0 * (fX - a); ychange = 1.0 - 2.0 * (fY - b);

XDEP(Y > -X, -, >, -) YDEP(Y > 0, -, <, -)

fX = X; fY = Y; xchange = 1.0 + 2.0 * (fX - a); ychange = 1.0 - 2.0 * (fY - b);

YDEP(-Y < -X, +, >, -) XDEP(X < 0, +, <, -)

#undef XDEP #undef YDEP } </highlightSyntax>

## Filled Circle

• Use the Bresenham criterion for the pixel placement
• When x and y and r are integers, the output should be precisely like circlefill from allegro 4.4 branch