Hi all,

Now that pygame includes the (experimental) gfxdraw module for drawing
shapes, I thought it might interest some to hear about an efficient
circle drawing algorithm I came across:

http://slabode.exofire.net/circle_draw.shtml
(mirror: http://www.mmsguru.com/mirror/circle_cached.html)

The link discusses it in the context of OpenGL, but where the
algorithm is simply about finding out where to put the circle's
vertices, it generalizes rather widely. Below I include a timing
example of using it in pygame with gfxdraw. I know gfxdraw has a
built-in circle drawing function; indeed, as you'll see at the end of
the code, the built-in function is rather faster than either manual
function I create (possibly because it wraps compiled code for
determining the vertices?). However, I thought this example might
still be of use to some, for example those that want to make their own
version of the pie function that draws a filled pie, etc. It's even
possible that whatever compiled code achieves the built-in circle
functions may achieve speed-ups by implementing the more efficient
vertex locating algorithm.

A final note of interest, when polygon() is replaced by aapolygon() in
the manual functions below, the traditional trig approach slows down
quite a bit whereas SiegeLord's approach doesn't seem to slow down
much at all. Not sure why this would be though.

#####START CODE#####

#import requisite libraries
import pygame , math , time
from pygame.locals import *
from pygame.gfxdraw import *

pygame.init()

screen_size = (500,500)
screen = pygame.display.set_mode(screen_size)

screen_rect = screen.get_rect()
screen_x_center = screen_size[0]/2
screen_y_center = screen_size[1]/2

BLACK = (0,0,0)
WHITE = (255,255,255)
screen.fill(BLACK)

radius = 200

#define the standard (slow) circle function
def draw_circle(cx,cy,radius):
        points = []
        for angle in range(361):
                points.append(( \
                        cx + math.sin(angle) * radius \
                        , cy + math.cos(angle) * radius \
                ))
        polygon(screen,points,WHITE)

#time the standard circle function
start=time.time()
for i in range(1000):
        draw_circle( \
                screen_x_center \
                , screen_y_center \
                , radius \
        )
print time.time()-start

#define SiegeLord's (faster) circle function
def draw_circle_fast(cx, cy, radius):
        theta = 2 * math.pi / 361
        tangetial_factor = math.tan(theta)
        radial_factor = math.cos(theta)
        x = radius
        y = 0
        points = []
        for ii in range(361):
                points.append((x + cx, y + cy))
                tx = -y
                ty = x
                x = x + tx * tangetial_factor
                y = y + ty * tangetial_factor
                x = x * radial_factor
                y = y * radial_factor
        polygon(screen,points,WHITE)

#time SiegeLord's function
start=time.time()
for i in range(1000):
        draw_circle_fast( \
                screen_x_center \
                , screen_y_center \
                , radius \
        )
print time.time()-start

#time the built-in function
start=time.time()
for i in range(1000):
        circle( \
                screen \
                , screen_x_center \
                , screen_y_center \
                , radius \
                , WHITE \
        )
print time.time()-start

#####END CODE#####

-- 
Mike Lawrence
Graduate Student
Department of Psychology
Dalhousie University

Looking to arrange a meeting? Check my public calendar:
http://tr.im/mikes_public_calendar

~ Certainty is folly... I think. ~

Reply via email to