Nerd content and
cringe since 1999
Alexander Grupe

There are two hard problems in IT: transferring large files and, apparently, drawing circles.

I’m writing a lot of demo prototyping tools in Java and Kotlin. Doing that, an exotic requirement came up: I wanted to draw a filled circle. Outrageous, I know, but how hard can it be?

Since there is no fillCircle, let’s try fillOval. According to the documentation, “fills an oval bounded by the specified rectangle with the current color” – just what we need!

g.fillOval(x, y, size, size)

Weird, the circle was supposed to span the bounding box, but the first column and row are empty. Also, there are ugly jaggies. Hm, why not try to move the circle up and left by 1 pixel and increase the size by 1 to make up for that:

g.fillOval(x-1, y-1, size+1, size+1)

That’s somewhat better, but now we have a single stray pixel outside of the bounding box! fillArc with angles from 0 to 360 gives the same result.

Maybe we can use drawOval instead and fill that? Of course, that method behaves slightly different (“covers an area that is width+1 pixels wide and height+1 pixels tall”), but we keep that in mind.

g.drawOval(x, y, size-1, size-1)

At least the outline fills the bounding box neatly now. But wait… the circles aren’t even symmetrical?! You gotta be kidding me.

At this point, I’m not really in the mood to investigate if this is a problem of the specific JRE* or something, and do the obvious thing: Use the circle equation and plot every pixel by hand.

(x-centerX)² + (y-centerY)² <= r²

Huzzah! That was easy. As a bonus, these circles don’t seem to suffer from ugly jaggies, and they mostly match up with the circles PersonalPaint and DeluxePaint would draw.

White: pixels not drawn by PPaint/DPaint

Why didn’t I do it that way from the start? Stupid me. /s

*) For reference: Amazon Corretto 17.0.10 on Windows 10

previous next close