Title: Fast Circle Drawing Using Surfarray

Author: Pete Shinners (pete at shinners.org)
Submission date: May 19, 2001

Description: Pete says, "I put together a quick demonstration on how to make your own circles using Numeric python and the surfarray modules. Note that this code only does circles. Changing it to handle ellipses shouldn't be too difficult, but you'll need to be a little up on your math. Remember you'll need Numeric python installed ( www.pfdubois.com ), but other than that you should be able to pick and learn at my little circle drawing example."

Download: circle.tar.gz

Download: circle.zip

pygame version required: Any with SurfArray
SDL version required: Any
Python version required: Any with Numeric

Comments: Pete gives us a circle drawing routine, and a small script to test it. The math is pretty straightforward, but the syntax may be a little unfamiliar to those not used to working with Numpy.

As this script draws its circles, you may note that many look a little oblong. This is most noticable with the smallest , brightest circles, but all look a little squared off. This occurs not because of any particular weakness in the code, but rather because of the lack of anti-aliasing. Also note that this code doesn't run as fast as it could - Pete has added an artificial delay loop at the end of his script. Comment out the last line (pygame.time.delay(100)) to see how fast it can go.

Messages: 3


"""Draw a circle with Numeric"""

#quick and dirty imports
import pygame
from pygame.locals import *
import pygame.surfarray as surfarray
from Numeric import *
squareroot = sqrt


def makecircle(radius, color):
    "make a surface with a circle in it, color is RGB"

    #make a simple 8bit surface and colormap
    surf = pygame.Surface((radius*2, radius*2), 0, 8)
    surf.set_palette(((0, 0, 0), color))

    #first build circle mask
    axis = abs(arange(radius*2)-(radius-0.5)).astype(Int)**2
    mask = squareroot(axis[NewAxis,:] + axis[:,NewAxis])
    mask = less(mask, radius)

    surfarray.blit_array(surf, mask)    #apply circle data
    surf.set_colorkey(0, RLEACCEL)      #make transparent

    return surf


if __name__ == '__main__':
    #lets do a little testing
    from random import *
    pygame.init()
    screen = pygame.display.set_mode((200, 200))
    while not pygame.event.peek([QUIT,KEYDOWN]):
        radius = randint(10, 20)
        pos = randint(0, 160), randint(0, 160)
        color = randint(20, 200), randint(20, 200), randint(20, 200)
        circle = makecircle(radius, color).convert()
        screen.blit(circle, pos)
        pygame.display.update((pos, (radius*2, radius*2)))
        pygame.time.delay(100)

From: Peter

Date: March 03, 2003 11:16 GMT

Hi Pete

Downloaded both Mandelbrot and circle.

When I tried to run them I got this message.

>pythonw -u circle.py
Traceback (most recent call last):
File "circle.py", line 38, in ?
circle = makecircle(radius, color).convert()
File "circle.py", line 23, in makecircle
surfarray.blit_array(surf, mask) #apply circle data
ValueError: unsupported datatype for array

Easy fix?

Is it my installation?

Regards Peter

 

From: Peter

Date: March 03, 2003 11:16 GMT

Hi Pete

Downloaded both Mandelbrot and circle.

When I tried to run them I got this message.

>pythonw -u circle.py
Traceback (most recent call last):
File "circle.py", line 38, in ?
circle = makecircle(radius, color).convert()
File "circle.py", line 23, in makecircle
surfarray.blit_array(surf, mask) #apply circle data
ValueError: unsupported datatype for array

Easy fix?

Is it my installation?

Regards Peter

 

From: Florian Bösch

Date: February 27, 2004 20:10 GMT

I'd propose to change two lines of the core circle calculation.

mask = axis[Numeric.NewAxis,:] + axis[:,Numeric.NewAxis]
mask = Numeric.less(mask, radius**2)

Measurement showed me that I gain time with factor n**2 by doing the former instead of the original lines. This because:

mask = Numeric.sqrt( axis[Numeric.NewAxis,:] + axis[:,Numeric.NewAxis] )
mask = Numeric.less(mask, radius)

does a sqrt on each cell of the 2d field, and my solution avoids doing sqrt at all.

 

Main - Repository - Submit - News

Feedback