Reputation: 145
I know there are several other questions and articles on the internet, but they wern't quite enough. My problem is, that right now, i'm calculating the points of a sphere by stacking circles with a ascending/descending radius, made with bresenham's circle drawing algorithm. This is my code, but it should'n be important.
def drawCircle(self, xyz, r): #Draws circle with radius "r" from midpoint "xyz". Note: Circle is parallel to x-axis
xc, yc, zc = xyz
coords = []
def drawC(xc, yc, zc, x, y):
coords.append((xc+x, yc+y, zc))
coords.append((xc-x, yc+y, zc))
coords.append((xc+x, yc-y, zc))
coords.append((xc-x, yc-y, zc))
coords.append((xc+y, yc+x, zc))
coords.append((xc-y, yc+x, zc))
coords.append((xc+y, yc-x, zc))
coords.append((xc-y, yc-x, zc))
x = 0
y = r
d = 3 - 2 * r
drawC(xc, yc, zc, x, y)
while y >= x:
x += 1
if (d > 0):
y -= 1
d = d + 4 * (x - y) + 10
else:
d = d + 4 * x + 6
drawC(xc, yc, zc, x, y)
for c in coords:
self.drawPixel(c)
return coords
def drawSphere(self,xyz,r): #Draws sphere. Not quite functional yet
x, y, z = xyz
for sr in range(-1,r):
self.drawCircle((x,y,z-r+sr),sr)
index = list(range(-1,r))
for sr in index:
self.drawCircle((x,y,z+sr),index[-sr])
When I render one of these spheres this happens:
If I increase the thickness to 2 layers
and to 3 layers:
There are holes. :( The thiccer the sphere has less holes, but is much slower to create. Is there a way to have hole-less sphere?
Upvotes: 0
Views: 222
Reputation:
I would not proceed by drawing circles. Instead I would fill the disk by scanning the bounding box of the projected disk (this is a square), then computing R² - (X-Xc)² - (Y-Yc)²
and drawing when this quantity is positive.
If you need the Z
coordinate, this is the square root of the above quantity.
You can evaluate it very quickly in an incremental way, noting that
R² - (X+1-Xc)² - (Y-Yc)² = R² - (X-Xc)² - (Y-Yc)² + 2(X-Xc) + 1 =
R² - (X-Xc)² - (Y-Yc)² + 2X + 1-2Xc`
Upvotes: 1
Reputation: 1087
So it looks like you are drawing just the edge of each circle.
One way to eliminate the holes is to fill in the area inside each circle. You can pick a point anywhere on the circle, then pick the two points directly next to it and fill in a triangle between them. Then, move the second point to the opposite side of the third and draw a new triangle.
Or, you could pick one axis of the circle (x or y) and take the two points that lie on x=some value for every x. You already have opposing points when you call drawC()
, so just plug them into draw_line below:
def fill_line(x1, x2, y, z):
max = max(x1,x2)
min = min(x1,x2)
for i in range(min, max):
coords.append(i, y, z)
You could also iterate over the square each circle is in and find the points within it:
def fill_circle(xy, r, z):
for i in range(xy[0]-r, xy[0]+r):
for j in range(xy[1]-r, xy[1]+r):
if (i - xy[0])**2 + (j - xy[1])**2 < r**2:
coords.append(i,j,z)
If you get holes between the layers when you fill in the circles, try also drawing circles on another axis.
Upvotes: 0