More pythonic circle?
Scott David Daniels
scott.daniels at acm.org
Sun Apr 9 19:45:08 EDT 2006
Pythor wrote:
> I wrote the following code for a personal project. I need a function
> that will plot a filled circle in a two dimensional array. I found
> Bresenham's algorithm, and produced this code. Please tell me there's
> a better way to do this.
>
> import numpy
>
> def circle(field=None,radius,center=(0,0),value=255,):
...
Break this code into two functions. Roughly:
def wedge_nz(radius):
'''points in octant 2 of 0-origin radius-sized circle, no zeroes'''
x, y = int(radius), 1
dr2 = x ** 2 + y ** 2
r2 = radius ** 2
dy_limit = int(radius * .71) # sin of 45 degrees + a smidge
while y <= dy_limit:
if r2 >= dr2: # dx**2 + dy**2
for tx in range(1, x + 1):
yield tx, y
dr2 += y * 2 + 1 # dr2 = x ** 2 + (y + 1) ** 2
y += 1
else:
dr2 -= x * 2 - 1 # dr2 = (x - 1) ** 2 + y ** 2
x -= 1
if x < y:
break
and:
def circle2(field=None, radius=3.2, center=(0, 0), entry=255):
'''Fill field at all points within 'radius' of center with entry.
center is assumed integral.
'''
x, y = center
if field is None:
field = numpy.zeros((int(x + radius), int(y + radius)), 'u')
for px, py in wedge_nz(radius):
for dx in (px, -px):
for dy in (py, -py):
# Done once per quadrant. Do both octants.
field[max(0, y + dy)][max(0, x + dx)] = entry
field[max(0, y + dx)][max(0, x + dy)] = entry
# do the diameters
for dx in range(-radius, radius + 1):
field[y][max(0, x + dx)] = entry
field[max(0, y + dx)][x] = entry
return field
There is still overlap done at x = y and x = -y; you could squeeze that
out as well by changing wedge_nz not to put it out, and making circle2
do diagonal diameters as well (leaving the center the sole overwrite).
--Scott David Daniels
scott.daniels at acm.org
More information about the Python-list
mailing list