Skip to content

Commit

Permalink
Optimize draw.aacircle and fix typo (#3012)
Browse files Browse the repository at this point in the history
* Optimized draw.aacircle and fixed typo

Moved pow(radius, 2) outside of loop

* formatted

* float to double

double trouble
  • Loading branch information
mzivic7 authored Jul 22, 2024
1 parent bf4d301 commit ba6d659
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 33 deletions.
2 changes: 1 addition & 1 deletion docs/reST/ref/draw.rst
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ object around the draw calls (see :func:`pygame.Surface.lock` and
| :sg:`aacircle(surface, color, center, radius, width=0, draw_top_right=None, draw_top_left=None, draw_bottom_left=None, draw_bottom_right=None) -> Rect`
Draws an antialiased circle on the given surface.
Uses Xaolin Wu Circle Algorithm.
Uses Xiaolin Wu Circle Algorithm.
adapted from: https://cgg.mff.cuni.cz/~pepca/ref/WU.pdf

:param Surface surface: surface to draw on
Expand Down
66 changes: 34 additions & 32 deletions src_c/draw.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,13 @@ static void
draw_circle_bresenham_thin(SDL_Surface *surf, int x0, int y0, int radius,
Uint32 color, int *drawn_area);
static void
draw_circle_xaolinwu(SDL_Surface *surf, int x0, int y0, int radius,
int thickness, Uint32 color, int top_right, int top_left,
int bottom_left, int bottom_right, int *drawn_area);
draw_circle_xiaolinwu(SDL_Surface *surf, int x0, int y0, int radius,
int thickness, Uint32 color, int top_right, int top_left,
int bottom_left, int bottom_right, int *drawn_area);
static void
draw_circle_xaolinwu_thin(SDL_Surface *surf, int x0, int y0, int radius,
Uint32 color, int top_right, int top_left,
int bottom_left, int bottom_right, int *drawn_area);
draw_circle_xiaolinwu_thin(SDL_Surface *surf, int x0, int y0, int radius,
Uint32 color, int top_right, int top_left,
int bottom_left, int bottom_right, int *drawn_area);
static void
draw_circle_filled(SDL_Surface *surf, int x0, int y0, int radius, Uint32 color,
int *drawn_area);
Expand Down Expand Up @@ -820,33 +820,33 @@ aacircle(PyObject *self, PyObject *args, PyObject *kwargs)
if (!width || width == radius) {
draw_circle_filled(surf, posx, posy, radius - 1, color,
drawn_area);
draw_circle_xaolinwu(surf, posx, posy, radius, 2, color, 1, 1, 1,
1, drawn_area);
draw_circle_xiaolinwu(surf, posx, posy, radius, 2, color, 1, 1, 1,
1, drawn_area);
}
else if (width == 1) {
draw_circle_xaolinwu_thin(surf, posx, posy, radius, color, 1, 1, 1,
1, drawn_area);
draw_circle_xiaolinwu_thin(surf, posx, posy, radius, color, 1, 1,
1, 1, drawn_area);
}
else {
draw_circle_xaolinwu(surf, posx, posy, radius, width, color, 1, 1,
1, 1, drawn_area);
draw_circle_xiaolinwu(surf, posx, posy, radius, width, color, 1, 1,
1, 1, drawn_area);
}
}
else {
if (!width || width == radius) {
draw_circle_xaolinwu(surf, posx, posy, radius, radius, color,
top_right, top_left, bottom_left,
bottom_right, drawn_area);
draw_circle_xiaolinwu(surf, posx, posy, radius, radius, color,
top_right, top_left, bottom_left,
bottom_right, drawn_area);
}
else if (width == 1) {
draw_circle_xaolinwu_thin(surf, posx, posy, radius, color,
top_right, top_left, bottom_left,
bottom_right, drawn_area);
draw_circle_xiaolinwu_thin(surf, posx, posy, radius, color,
top_right, top_left, bottom_left,
bottom_right, drawn_area);
}
else {
draw_circle_xaolinwu(surf, posx, posy, radius, width, color,
top_right, top_left, bottom_left,
bottom_right, drawn_area);
draw_circle_xiaolinwu(surf, posx, posy, radius, width, color,
top_right, top_left, bottom_left,
bottom_right, drawn_area);
}
}

Expand Down Expand Up @@ -2514,23 +2514,24 @@ draw_eight_symetric_pixels(SDL_Surface *surf, int x0, int y0, Uint32 color,
}
}

/* Xaolin Wu Circle Algorithm
/* Xiaolin Wu Circle Algorithm
* adapted from: https://cgg.mff.cuni.cz/~pepca/ref/WU.pdf
* with additional line width parameter and quadrants option
*/
static void
draw_circle_xaolinwu(SDL_Surface *surf, int x0, int y0, int radius,
int thickness, Uint32 color, int top_right, int top_left,
int bottom_left, int bottom_right, int *drawn_area)
draw_circle_xiaolinwu(SDL_Surface *surf, int x0, int y0, int radius,
int thickness, Uint32 color, int top_right, int top_left,
int bottom_left, int bottom_right, int *drawn_area)
{
for (int layer_radius = radius - thickness; layer_radius <= radius;
layer_radius++) {
int x = 0;
int y = layer_radius;
double pow_layer_r = pow(layer_radius, 2);
double prev_opacity = 0.0;
if (layer_radius == radius - thickness) {
while (x < y) {
double height = sqrt(pow(layer_radius, 2) - pow(x, 2));
double height = sqrt(pow_layer_r - pow(x, 2));
double opacity = 255.0 * (ceil(height) - height);
if (opacity < prev_opacity) {
--y;
Expand All @@ -2547,7 +2548,7 @@ draw_circle_xaolinwu(SDL_Surface *surf, int x0, int y0, int radius,
}
else if (layer_radius == radius) {
while (x < y) {
double height = sqrt(pow(layer_radius, 2) - pow(x, 2));
double height = sqrt(pow_layer_r - pow(x, 2));
double opacity = 255.0 * (ceil(height) - height);
if (opacity < prev_opacity) {
--y;
Expand All @@ -2565,7 +2566,7 @@ draw_circle_xaolinwu(SDL_Surface *surf, int x0, int y0, int radius,
}
else {
while (x < y) {
double height = sqrt(pow(layer_radius, 2) - pow(x, 2));
double height = sqrt(pow_layer_r - pow(x, 2));
double opacity = 255.0 * (ceil(height) - height);
if (opacity < prev_opacity) {
--y;
Expand All @@ -2584,15 +2585,16 @@ draw_circle_xaolinwu(SDL_Surface *surf, int x0, int y0, int radius,
}

static void
draw_circle_xaolinwu_thin(SDL_Surface *surf, int x0, int y0, int radius,
Uint32 color, int top_right, int top_left,
int bottom_left, int bottom_right, int *drawn_area)
draw_circle_xiaolinwu_thin(SDL_Surface *surf, int x0, int y0, int radius,
Uint32 color, int top_right, int top_left,
int bottom_left, int bottom_right, int *drawn_area)
{
int x = 0;
int y = radius;
double pow_r = pow(radius, 2);
double prev_opacity = 0.0;
while (x < y) {
double height = sqrt(pow(radius, 2) - pow(x, 2));
double height = sqrt(pow_r - pow(x, 2));
double opacity = 255.0 * (ceil(height) - height);
if (opacity < prev_opacity) {
--y;
Expand Down

0 comments on commit ba6d659

Please sign in to comment.