views:

1778

answers:

4

I am using Bresenham's circle algorithm for fast circle drawing. However, I also want to (at the request of the user) draw a filled circle.

Is there a fast and efficient way of doing this? Something along the same lines of Bresenham?

The language I am using is C.

+5  A: 

Here's a C# rough guide (shouldn't be that hard to get the right idea for C) - this is the "raw" form without using Bresenham to eliminate repeated square-roots.

Bitmap bmp = new Bitmap(200, 200);

int r = 50; // radius
int ox = 100, oy = 100; // origin

for (int x = -r; x < r ; x++)
{
    int height = (int)Math.Sqrt(r * r - x * x);

    for (int y = -height; y < height; y++)
        bmp.SetPixel(x + ox, y + oy, Color.Red);
}

bmp.Save(@"c:\users\dearwicker\Desktop\circle.bmp");
Daniel Earwicker
Or loop on y and draw horizonal lines. Occasionally there is a reason to choose one or the other, but in most cases it does not matter. Either way you use the same Bresenham logic to find the endpoints quickly.
dmckee
All those Math.Sqrt's aren't going to be especially fast...
AakashM
No, but you can use Bresenham to avoid that. The basic idea is to "join the dots" between the upper and lower points at each x coordinate covered by the circle.
Daniel Earwicker
Profile to see which is best. If there's a difference at all, going horizontal should be better. It gets rid of a multiplication by stride and may result in fewer faults.
colithium
@AakashM - have you tried it? I find it makes almost no measurable difference whether I compute the `Math.Sqrt` or not. (Obviously I've eliminated the `SetPixel` as well, which accounts for ALL the time in the complete program; I just add x and y to a counter variable to ensure they're used).
Daniel Earwicker
"All those Math.Sqrts aren't going to be especially fast" - the disassembly shows that the C#/JIT combo emits the inlined SQRTSD instruction on my 64-bit machine, and so it's little wonder that it runs blazingly fast. I can't measure a different between Math.Sqrt and a simple addition. So I think your comment is probably based on pre-FP instruction set guessing!
Daniel Earwicker
This is surprising to me too, as it's been a while since I've had to use Sqrt for anything, so I've blogged it here: http://smellegantcode.wordpress.com/2009/07/29/square-roots-are-slow/
Daniel Earwicker
That perennial problem - what to do with one's carefully-tuned educated-guesswork engine when the fundamentals change?
AakashM
Well, depends if you want to learn about history or get the job done - personally I enjoy both! :)
Daniel Earwicker
+1  A: 

I would just generate a list of points and then use a polygon draw function for the rendering.

KPexEA
If he has implemented Bresenham for the open version, he is working at a lower layer then using an API...either for learning purposes or to *implement* an API.
dmckee
+12  A: 

Having read the Wikipedia page on Bresenham's (also 'Midpoint') circle algorithm, it would appear that the easiest thing to do would be to modify its actions, such that instead of

setPixel(x0 + x, y0 + y);
setPixel(x0 - x, y0 + y);

and similar, each time you instead do

lineFrom(x0 - x, y0 + y, x0 + x, y0 + y);

That is, for each pair of points (with the same y) that Bresenham would you have you plot, you instead connect with a line.

AakashM
Very clear.
dmckee
+2  A: 

Just use brute force. This method iterates over a few too many pixels, but it only uses integer multiplications and additions. You completely avoid the complexity of Bresenham and the possible bottleneck of sqrt.

for(int y=-radius; y<=radius; y++)
    for(int x=-radius; x<=radius; x++)
        if(x*x+y*y <= radius*radius)
            setpixel(origin.x+x, origin.y+y);
palm3D