Nested Circles and Squares with p5.js
I’ve been getting into p5.js lately, and this little sketch is a nice case study in how a simple geometric rule can turn into something visually rich.
There’s also a lot to be said for getting involved with new programming frameworks without the help of AI. I found myself reading the documentation, debugging and even googling when things didn’t work. It’s genuinely fun to reconcile your mental model with the reality of the runtime. In this case, what I didn’t realize was that this framework was designed for animation. So drawing something isn’t just a matter of drawing something by default, it’s running at 60fps in a loop. So that was why my initial cut of this ran for
I also had to revisit middle school geometry which was educational and humbling. It would have been much faster to just let the AI write the code but the extra time and sweat meant I learned a few new things.
The idea in this sketch is traightforward: start with a circle, draw the largest square that fits inside it, then draw the largest circle that fits inside that square. Keep alternating until the shapes get too small to matter. Because each next radius is derived from the previous square’s side length, the whole image becomes a clean nested rhythm of black circles and white squares against a blue field.
var canvasSizeX = 800;
var canvasSizeY = 800;
var centerX = canvasSizeX / 2;
var centerY = canvasSizeY / 2;
function setup() {
createCanvas(canvasSizeX, canvasSizeY);
stroke("black");
strokeWeight(1);
rectMode(CENTER);
noLoop(); // draw only once
}
function draw() {
background("blue");
// Start with the outer circle radius
let R = min(canvasSizeX, canvasSizeY) / 2; // circle radius
// Draw alternating inscribed circle -> square -> circle -> ...
while (R > 0.5) {
// draw circle (diameter = 2*R)
fill("black");
circle(centerX, centerY, R * 2);
// compute square side that has its corners on the circle: side = diagonal / sqrt(2)
// diagonal = 2*R => side = (2*R)/sqrt(2) = R * sqrt(2)
let s = R * sqrt(2);
// draw square centered
fill("white");
square(centerX, centerY, s);
// next circle is the one inscribed inside the square: its radius = s/2
R = s / 2;
}
}