[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] Efficient circles



Hi Mike,

Possibly the simplest circle drawing algorithm is often called Bresenham's circle algorithm. It uses just addition and subtraction, simlar to Bresenham's line drawing algorithm. It actually only draws a quarter of a circle, but repeating it with sign changed draws the 4 quadrants.

See:
http://en.wikipedia.org/wiki/Midpoint_circle_algorithm
http://en.literateprograms.org/Bresenham's_circle_algorithm_(Python)

I seem to recall hearing, however that some fast circle drawers don't bother drawing true circles, but actually make polygons because a bunch of straight line segments draw extremely quickly, and choosing the number of sides carefully, related to the resolution can produce something that looks virtually indistinguishable from a true circle.

Cheers,

	- Miriam

Mike Lawrence wrote:
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#####


--
If you don't have any failures then you're not trying hard enough.
 - Dr. Charles Elachi, director of NASA's Jet Propulsion Laboratory
-----
Website: http://miriam-english.org
Blog: http://miriam_e.livejournal.com