How can I draw a filled circle of any radius in 16-bit assembly?
Asked by
MellowPine47
I'm learning NASM and already have a _Make_Pixel routine that can draw individual pixels. I want to write a reasonably short algorithm for drawing a filled circle with a specified center and radius. Ideally it should use only a few data labels, stay under roughly 300 lines, and rely on straightforward high-school-level math. Please explain the approach in programming terms rather than giving only equations. I've tried several perimeter and distance-based algorithms, but they either didn't work or only drew an outline.
Answers
The simplest approach is to scan the square surrounding the circle. For every pixel position, calculate its horizontal and vertical distance from the center. If dx*dx + dy*dy is less than or equal to radius*radius, draw that pixel. You only need to scan from centerX - radius through centerX + radius, and the same range vertically. Squared distances avoid using a square-root instruction.
Reply to this answer
You can calculate the horizontal extent with x = sqrt(radius*radius - y*y), then fill the pixels between the two endpoints. If your processor or code does not have convenient multiplication or square-root support, use a small lookup table for x values based on each y offset. That keeps the drawing loop short and avoids expensive calculations.
Reply to this answer
Bresenham normally gives you the circumference, which is why it does not automatically produce a filled circle. To adapt it, use its calculated boundary points to draw horizontal lines between the matching left and right points on each row. Alternatively, scan each row directly with the squared-distance test; it is easier to debug and is probably the best starting point for learning assembly.
Reply to this answer
A more efficient filled-circle method is to draw horizontal spans one row at a time. For each vertical offset y from -radius to radius, find the largest horizontal offset x satisfying x*x + y*y <= radius*radius. Then draw one line from centerX - x to centerX + x at vertical position centerY + y. The top and bottom rows mirror each other, so you can calculate one side and draw both.
Reply to this answer
Add your answer
Answers are reviewed before publication.
MellowPine47: That makes sense. I was trying something similar, but I probably had the distance comparison or coordinate offsets wrong.