Implementing Bresenham's circle drawing algorithm

Your Bresenham method isn't slow per se, it's just comparatively slow.

Swing's drawArc() implementation is machine-dependent, using native code. You'll never beat it using Java, so don't bother trying. (I'm actually surprised the Java Bresenham method is as fast as it is compared to drawArc(), a testament to the quality of the virtual machine executing the Java bytecode.)

Your trigonometric method, however, is unnecessarily fast, because you're not comparing it to Bresenham on an equal basis.

The trig method has a set angular resolution of PI/36 (~4.7 degrees), as in this operation at the end of the for statement:

angle = angle + Math.PI/36  

Meanwhile, your Bresenham method is radius-dependent, computing a value at each pixel change. As each octant produces sqrt(2) points, multiplying that by 8 and dividing by 2*Pi will give you the equivalent angular resolution. So to be on equal footing with the Bresenham method, your trig method should therefore have:

resolution = 4 * r * Math.sqrt(2) / Math.PI;

somewhere outside the loop, and increment your for by it as in:

angle += resolution

Since we will now be back to pixel-level resolutions, you can actually improve the trig method and cut out the subsequent drawline call and assignments to x0 and y0, eliminate unnecessarily casts, and furthermore reduce calls to Math. Here's the new method in its entirety:

public static void drawTrigonometricalCircle (double r, double width, double height, 
    Graphics g) {

    double localPi = Math.PI;
    double resolution = 4 * r * Math.sqrt(2) / Math.PI;

    for (double angle = 0; angle <= localPi; angle += resolution) {
        double x = r * Math.cos(angle);
        double y = r * Math.sin(angle);
        drawPoint(x, y, width, height, g);
    }

}

The trig method will now be executing more often by several orders of magnitude depending on the size of r.

I'd be interested to see your results.


Your problem lies in that Bresenham's algorithm does a variable number of iterations depending on the size of the circle whereas your trigonometric approach always does a fixed number of iterations.

This also means that Bresenham's algorithm will always produce a smooth looking circle whereas your trigonometric approach will produce worse looking circles as the radius increases.

To make it more even, change the trigonometric approach to produce approximately as many points as the Bresenham implementation and you'll see just how much faster it is.

I wrote some code to benchmark this and also print the number of points produced and here are the initial results:

Trigonometric: 181 ms, 73 points average
Bresenham: 120 ms, 867.568 points average

After modifying your trigonometric class to do more iterations for smoother circles:

    int totalPoints = (int)Math.ceil(0.7 * r * 8);
    double delta = 2 * Math.PI / totalPoints;
    for (double angle = 0; angle <= 2*Math.PI; angle = angle + delta) {

These are the results:

Trigonometric: 2006 ms, 854.933 points average
Bresenham: 120 ms, 867.568 points average