Adaptation of mathrabbit's Expanding Rects, but it's just circs.
(Expanding Rects)
Thanks chatgpt for this horrendous mess
Log in to post a comment.
let NUM_CIRCLES = 500; // min=0, max=1000, step=10 let CENTER_RAD = 1; // min=0.5, max=5, step=0.1 let SHRINK = 1; // min=-10, max=10, step=1 let HIT_SIDES_CHANCE = 0.2; // min=0, max=1, step=0.1 let OUTER_PADDING = 10; // min=0, max=50, step=1 let SEED_PADDING = 30; // min=0, max=50, step=1 let MIN_RAD = 2; // min=0, max=20, step=0.5 let MAX_RAD = 10; // min=0, max=20, step=0.5 // The overlap can be a fun parameter to experiment with. let OVERLAP_ALLOWANCE = 2; // min=0, max=10, step=0.5 // Booleans let DO_EXPAND = 1; // min=0, max=1, step=1 let DRAW_CENTERS = 0; // min=0, max=1, step=1 let DRAW_FRAME = 1; // min=0, max=1, step=1 let DRAW_X = 0; // min=0, max=1, step=1 // Hatching options let HATCH_CHANCE = 0.8; // min=0, max=1, step=0.1 let HATCH_SPACING = 1.5; // min=1, max=10, step=0.5 let SPARSE_HATCH_CHANCE = 0.15; // min=0, max=1, step=0.1 let R_SPACING = 15; // min=5, max=45, step=5 let R_SPACING_VARIANCE = 5; // min=0, max=20, step=1 let R_SPACING_MIN = 5; // min=1, max=20, step=1 let HATCH_TYPE_CHANCE = 0.5; Canvas.setpenopacity(1); const turtle = new Turtle(); turtle.pendown(); let rand = (min, max) => Math.random() * (max - min) + min; let randInt = (min, max) => Math.floor(rand(min, max)); let degreesToRadians = degrees => degrees * (Math.PI / 180); let intersect = (circle1, circle2) => { let dx = circle1.x - circle2.x; let dy = circle1.y - circle2.y; let distance = Math.sqrt(dx * dx + dy * dy); return distance < circle1.r + circle2.r - OVERLAP_ALLOWANCE; }; let Circle = (x, y, r) => { let circle = { x: x, y: y, r: r, }; circle.draw = () => { if (DRAW_FRAME) { turtle.jump(circle.x, circle.y - circle.r); turtle.circle(circle.r); } if (DRAW_CENTERS) { turtle.jump(circle.x, circle.y - 0.5); // Adjust the 0.5 to the desired dot radius turtle.circle(); } if (Math.random() < HATCH_CHANCE) { let isRadialHatch = Math.random() < HATCH_TYPE_CHANCE; let spacing = HATCH_SPACING; if (Math.random() < SPARSE_HATCH_CHANCE) { spacing *= 2; } // Adjust the spacing based on variance and minimum spacing for radial hatching let randomSpacing = R_SPACING + (Math.random() - 0.5) * 2 * R_SPACING_VARIANCE; randomSpacing = Math.max(randomSpacing, R_SPACING_MIN); if (isRadialHatch) { for (let angle = 0; angle < 360; angle += randomSpacing) { turtle.jump(circle.x + circle.r * Math.cos(degreesToRadians(angle)), circle.y + circle.r * Math.sin(degreesToRadians(angle))); turtle.goto(circle.x, circle.y); } } else { // 45° hatching using the original 'spacing' value let distance = Math.SQRT2 * circle.r; // This ensures hatching covers the entire circle let x1 = circle.x - distance / 2; let y1 = circle.y + distance / 2; let x2 = circle.x + distance / 2; let y2 = circle.y - distance / 2; for (let i = -distance/2; i <= distance/2; i += spacing) { turtle.jump(x1 + i, y1); turtle.goto(x2 + i, y2); } } } }; circle.expand = (amt) => { circle.r += amt; }; circle.isValid = () => circle.r > 0; return circle; }; let circles = []; for (let ii = 0; ii < NUM_CIRCLES; ii++) { let limit = 100 - SEED_PADDING; let x = randInt(-limit, limit); let y = randInt(-limit, limit); let r = randInt(MIN_RAD, MAX_RAD); let circle = Circle(x, y, r); let intersects = false; for (let jj = 0; jj < circles.length; jj++) { if (intersect(circles[jj], circle)) { intersects = true; break; } } if (!intersects) { circles.push(circle); } } console.log('' + circles.length + ' circles'); for (let c of circles) { c.expand(-1); } circles = circles.filter(c => c.isValid()); function walk(ii) { circles[ii].draw(); return ii < circles.length-1; }