DinosaurMoritz
DinosaurMoritz

Reputation: 145

calc Points of sphere

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:

one

If I increase the thickness to 2 layers

two

and to 3 layers:

th

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

Answers (2)

user1196549
user1196549

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

thshea
thshea

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

Related Questions