Reputation: 15
I am having trouble creating a method that can create a FILLED IN circle within a 2d array of pixels. So far, the Image class I have created can create a 2d array of pixels, change individual pixel values, etc. What I have been able to complete so far is use Bresenham's circle algorithm to create a hollow circle of any radius around any given point in the array. I cannot, however, figure out how to make this circle filled in.
I am open to any solution! I have tried creating a "flood fill" method, only to be greeted by various recursion errors. I have also tried just calling the circleBres method several times with decrementing radii, but this does not work either. For the sake of space, just assume that the writePixel method works.
class Image:
def drawCircle(self, centerX, centerY, x, y):
self.writePixel(centerX + x, centerY + y, 50.0)
self.writePixel(centerX - x, centerY + y, 50.0)
self.writePixel(centerX + x, centerY - y, 50.0)
self.writePixel(centerX - x, centerY - y, 50.0)
self.writePixel(centerX + y, centerY + x, 50.0)
self.writePixel(centerX - y, centerY + x, 50.0)
self.writePixel(centerX + y, centerY - x, 50.0)
self.writePixel(centerX - y, centerY - x, 50.0)
def circleBres(self, xc, yc, r):
x = 0
y = r
d = 3 - (2*r)
self.drawCircle(xc, yc, x, y)
while(y>=x):
x+=1
if(d>0):
y-=1
d = d+4*(x-y)+10
else:
d = d + 4 * x + 6
self.drawCircle(xc, yc, x, y)
time.sleep(.06)
obj = Image(50, 50, 51.0)
obj.circleBres(35, 35, 10)
The Image constructor's third parameter is the value that all pixels are assigned upon creation (51.0), and the third parameter of the writePixel method is the value that the pixel is being changed to (50.0).
Any help is greatly appreciated. Thanks!
Upvotes: 0
Views: 1008
Reputation: 80187
When you write
self.writePixel(centerX + x, centerY + y, 50.0)
self.writePixel(centerX - x, centerY + y, 50.0)
you draw the leftmost and the rightmost pixels of some scanline.
To fill it, just make for
loops instead of these 8 lines:
for xx in range(centerX - x, centerX + x + 1):
self.writePixel(xx, centerY + y, 50.0)
self.writePixel(xx, centerY - y, 50.0)
for xx in range(centerX - y, centerX + y):
self.writePixel(centerX + y, centerY + x, 50.0)
self.writePixel(centerX - y, centerY - x, 50.0)
Upvotes: 1
Reputation: 2036
Here's an example of how I would handle a problem like this:
Assuming you have a correct outline of circle, just iterate through the rows and fill all pixels between edges of the circle.
grid = [
[0,0,0,1,1,1,0,0,0],
[0,0,1,0,0,0,1,0,0],
[0,1,0,0,0,0,0,1,0],
[0,1,0,0,0,0,0,1,0],
[0,0,1,0,0,0,1,0,0],
[0,0,0,1,1,1,0,0,0],
]
def fill_circle(grid):
for r in grid: # For each row
j1 = None # left endpoint
j2 = None # right endpoint
for j, v in enumerate(r):
if v == 1 and j1 is None:
j1 = j
continue
if v == 1 and j2 is None:
j2 = j
break
else: # Did not find j1 AND j2
continue
for j in range(j1, j2): # Fill all points between
r[j] = 1
fill_circle(grid)
grid
[[0,0,0,1,1,1,0,0,0],
[0,0,1,1,1,1,1,0,0],
[0,1,1,1,1,1,1,1,0],
[0,1,1,1,1,1,1,1,0],
[0,0,1,1,1,1,1,0,0],
[0,0,0,1,1,1,0,0,0]]
Upvotes: 0