Midpoint circle drawing algorithm, pixel by pixel

A circle is continuous. A pixel grid needs a rule for choosing squares. Follow the midpoint algorithm, compare two boundary rules at the same radius, and check every selected coordinate.

Same radius. Different pixels.

At radius 5, the midpoint outline and the four-neighbor boundary both use 28 pixels. Yet 32 positions differ between their sets. Equal material counts do not guarantee the same shape. The eight-neighbor boundary uses 36 pixels, and the filled disk contains 81.

Every view uses center (5, 5), radius 5, and the same 11 × 11 grid. Columns and rows start at 0, from the top left. Dashed circles show the continuous radius; crosshairs mark the center.

28 midpoint pixels28 comparison pixels32 differing positions
Midpoint outline · 28 pixels
Four-neighbor boundary · 28 pixels
Overlay · 12 shared, 16 midpoint only, 16 comparison only

SharedMidpoint onlyComparison only

Inspect exact differing coordinates

Coordinates are (column, row). These lists show positions, not a visual-quality score.

Midpoint only: (3,0) (4,0) (6,0) (7,0) (0,3) (10,3) (0,4) (10,4) (0,6) (10,6) (0,7) (10,7) (3,10) (4,10) (6,10) (7,10)

Comparison only: (3,1) (4,1) (6,1) (7,1) (1,3) (9,3) (1,4) (9,4) (1,6) (9,6) (1,7) (9,7) (3,9) (4,9) (6,9) (7,9)

Follow the first octant

Start with x = 0, y = r, d = 1 − r. Each row emits its point and up to seven reflections, then chooses the next step: E keeps y; SE decreases y. Reflected duplicates count once.

Decision trace for radius 5; coordinates relative to the center
Stepxyd before updateNext step
005-4E
115-1E
2254SE
3343Stop after this point
Read the midpoint outline row by row
Inclusive column ranges, zero based
RowOccupied columnsPixels
03–75
12; 82
21; 92
30; 102
40; 102
50; 102
60; 102
70; 102
81; 92
92; 82
103–75

How the midpoint circle drawing algorithm works

The UIC circle-drawing notes describe choosing between neighboring pixels in one octant, then reflecting the choice around the center. This reference uses the following integer recurrence:

x = 0; y = r; d = 1 - r
while x <= y:
    emit the eight reflections of (x, y)
    if d < 0:
        d = d + 2*x + 3
    else:
        d = d + 2*(x - y) + 5
        y = y - 1
    x = x + 1

The coordinates here are relative to the center. Add (r, r) to place them in the 2r + 1 grid. If d is zero, this recurrence takes the SE branch. Axis and diagonal reflections can repeat a coordinate; the count includes each selected pixel only once.

What the comparison rules select

Filled disk
Keep a pixel when its center satisfies (x − r)² + (y − r)² ≤ r². Centers exactly on the circle are included.
Four-neighbor boundary
Keep a disk pixel if at least one neighbor directly above, below, left or right is outside the disk.
Eight-neighbor boundary
Also inspect the four diagonal neighbors. A disk pixel remains if any of these eight neighbors is outside.

These rules answer different questions. The boundary rules keep only centers inside the disk. Midpoint stepping follows the curve and can choose centers just outside it. A larger pixel count or a smaller difference does not establish better visual quality.

Red Blob Games’ circle-on-a-grid explanation discusses fills, outlines, center positions and radius conventions. Stefan Gustavson’s original midpoint demonstration provides another integer formulation. Those sources explain the algorithms; the comparison data below were computed for this reference.

Results for 64 integer radii

We computed radii 1–64, four pixel sets per radius: 256 method cases. Midpoint and four-neighbor masks differ at 63 of 64 radii; midpoint and eight-neighbor masks differ at all 64. The four-neighbor mask agrees with midpoint only at radius 1 in this range.

“Differing positions” means the symmetric difference: the number of coordinates included by exactly one method. It measures a change in selected pixels, not distance from the curve, aesthetic quality or drawing speed.

Inspect all 64 result rows
Version 1 · same integer radius and center for every comparison
RadiusMidpoint4-neighbor8-neighborFilledMidpoint vs 4: differing positionsMidpoint vs 8: differing positions
1445501
212812131216
3161620291620
4242028492028
5282836813240
63232441133244
74036521495268
84444601974864
95248682534464
105656763176484
116460843776892
1268649244192120
13727210052980108
14807610861384116
15848411670980112
16928812479792128
179696132901112148
181001001401009128168
191081041481129124168
201121121561257112156
211201161641373132180
221241241721517128176
231321281801653156208
241361321881793164220
251401401961961128184
261481442042121172232
271521522122289160220
281601562202453196260
291641642282629192256
301681682362821176244
311761722443001228300
321801802523209192264
331881842603409204280
341921922683625192268
351961962763853176256
362042002844053252336
372082082924293224308
382162123004513260348
392202203084777224312
402282243165025236328
412322283245261276372
422362363325525256352
432442403405789300400
442482483486077272372
452562523566361260364
462602603646625288392
472642643726921288396
482722683807213324436
492762763887525320432
502842803967845316432
512882884048173288404
522962924128497292412
533002964208809348472
543043044289145336460
553123084369477356484
563163164449845320448
5732432045210189348480
5832832846010557352484
5933233246810913352488
6034033647611289412552
6134434448411681368508
6235234849212061388532
6335635650012453368512
6436436050812853364512

Download the data and reproduce the results

Download all seven files into one folder. With Node.js 20 or later, run node reproduce.mjs --check to compare the generated CSV and JSON with the downloaded bytes. Run without --check to regenerate them. No additional packages are required.

The JSON stores each mask as inclusive column ranges for every row. For example, [2, 4] means columns 2, 3 and 4. Both column and row indices start at zero. The CSV summarizes counts and differences; the manifest records each other file’s byte size and SHA-256 checksum.

What we checked

All 64 midpoint masks were checked against a separate calculation that rounds the circle equation’s square-root result to the nearest integer in one octant. We also exhaustively checked disk membership, both neighbor predicates, row totals, reflections, transposition symmetry and set differences. The independent check passed 640 assertion groups. This is a computational check, with no claim of external peer review.

Original code and generated data are released under CC0 1.0. Cited sources retain their own rights. To identify a result, cite this page’s version, radius, method and the linked data file.

Scope, corrections and use for block builds

This reference covers integer radii and integer centers on binary grids. It does not test antialiasing, even-width center-gap layouts, half-integer radii, ellipses, 3D shapes, running time or which outline looks best.

The Minecraft circle generator uses a different size convention: its diameter D uses radius D/2. An 11-block plan therefore uses radius 5.5; the 11-cell research grid above uses radius 5. Do not substitute this example’s rows for the generator’s blueprint just because the widths match. For construction, use the generator’s own row instructions or the circle chart.

This study is published by the operator of the circle tool. The cited authors have not endorsed it. Version 1 files stay fixed; corrections will receive a new version and a dated note. Report a correction with the radius, method and coordinate so it can be reproduced.