Midpoint circle algorithm for filled circles

I needed to do this, here's the code I came up with for it. The visual image here shows the pixels drawn where the number is the order in which the pixels are traversed, and the green numbers represent pixels that are drawn using the reflection of the completion of a column using symmetry as shown in the code.

enter image description here

void drawFilledMidpointCircleSinglePixelVisit( int centerX, int centerY, int radius )
{
    int x = radius;
    int y = 0;
    int radiusError = 1 - x;

    while (x >= y)  // iterate to the circle diagonal
    {

        // use symmetry to draw the two horizontal lines at this Y with a special case to draw
        // only one line at the centerY where y == 0
        int startX = -x + centerX;
        int endX = x + centerX;
        drawHorizontalLine( startX, endX, y + centerY );
        if (y != 0)
        {
            drawHorizontalLine( startX, endX, -y + centerY );
        }

        // move Y one line
        y++;

        // calculate or maintain new x
        if (radiusError<0)
        {
            radiusError += 2 * y + 1;
        }
        else 
        {
            // we're about to move x over one, this means we completed a column of X values, use
            // symmetry to draw those complete columns as horizontal lines at the top and bottom of the circle
            // beyond the diagonal of the main loop
            if (x >= y)
            {
                startX = -y + 1 + centerX;
                endX = y - 1 + centerX;
                drawHorizontalLine( startX, endX,  x + centerY );
                drawHorizontalLine( startX, endX, -x + centerY );
            }
            x--;
            radiusError += 2 * (y - x + 1);
        }

    }

}

I wanted to comment on your Update #2: This solution works: (but I guess I need more reputation first...) that there's a small bug in the solution, coincidentally when drawing small circles. If you set the radius to 1 you get

00000
00000
01110
00100
00000

To fix this all you need to do is change the conditional check in plot4points from

if (x != 0 && y != 0)

to

if (y != 0)

I've tested this on small and big circles to make sure each pixel is still assigned only once. Seems to work great. Me thinks the x != 0 was not needed. Save a tiny bit of performance too.


The answer to the other question is perfectly fine. However since it is creating confusion, I'm going to explain it a bit.

The algorithm you see in Wikipedia basically finds x and y of 1/8 of a circle (angles 0 to pi/4) and then draws 8 points which are its mirrors. For example:

    (o-y,o+x) x         x (o+y,o+x)

(o-x,o+y) x                  x (o+x,o+y) <-- compute x,y

                   o

(o-x,o-y) x                  x (o+x,o-y)

    (o-y,o-x) x         x (o+y,o-x)

What the other solution suggests, which makes perfect sense if you look closely to this picture, is to instead of drawing 8 points, draw 4 horizontal lines:

    (o-y,o+x) x---------x (o+y,o+x)

(o-x,o+y) x-----------------x (o+x,o+y) <-- compute x,y

                   o

(o-x,o-y) x-----------------x (o+x,o-y)

    (o-y,o-x) x---------x (o+y,o-x)

Now if you compute (x,y) for angles in [0, pi/4] and draw these 4 lines for every computed point, you will have drawn many horizontal lines filling a circle without any line overlapping the other.

Update

The reason you get overlapping lines in the bottom of the circle is that the (x,y) coordinates are rounded, so in those locations the (x,y) move horizontally themselves.

If you take a look at this wikipedia picture:

enter image description here

You will notice that on the top of the circle, some pixels are horizontally aligned. Drawing horizontal lines originating from those points overlap.

If you don't want this, the solution is quite easy. You have to keep the previous x you have drawn with (since the top and bottom are mirrors of the original (x,y), you should keep the previous x which represents the y of those lines) and only draw the horizontal lines if that value changes. If it doesn't, it means that you are on the same line.

Given the fact that you will first encounter the innermost points, you should draw lines for the previous point only if the new point has different x (of course, the last line is drawn always). Alternatively, you can start drawing from angle PI/4 down to 0 instead of 0 to PI/4 and that you will first encounter the outer points, therefore you draw lines every time you see a new x.


I came up with an algorithm that draws the circle already filled.
It iterates over the pixels that the circle will be drawn upon and nothing else.
From here on it all about the speed of the draw-pixel function.

Here's a *.gif that demonstrates what the algorithm does !

As for the algorithm here's the code :

    //The center of the circle and its radius.
    int x = 100;
    int y = 100;
    int r = 50;
    //This here is sin(45) but i just hard-coded it.
    float sinus = 0.70710678118;
    //This is the distance on the axis from sin(90) to sin(45). 
    int range = r/(2*sinus);
    for(int i = r ; i >= range ; --i)
    {
        int j = sqrt(r*r - i*i);
        for(int k = -j ; k <= j ; k++)
        {
            //We draw all the 4 sides at the same time.
            PutPixel(x-k,y+i);
            PutPixel(x-k,y-i);
            PutPixel(x+i,y+k);
            PutPixel(x-i,y-k);
        }
    }
    //To fill the circle we draw the circumscribed square.
    range = r*sinus;
    for(int i = x - range + 1 ; i < x + range ; i++)
    {
        for(int j = y - range + 1 ; j < y + range ; j++)
        {
            PutPixel(i,j);
        }
    }

Hope this helps ... some new users ... sorry for necro-posting.
~Shmiggy