Packing circles for a good wander.
Log in to post a comment.
Canvas.setpenopacity(1); let shrinkageAcceleration = 100 //min=50, max=100, step=1 shrinkageAcceleration = 150 - shrinkageAcceleration let AngleIncrementA = -240; // min=-360, max=360, step=1 const angleIncrement1 = AngleIncrementA * Math.PI / 180; const maxFailures = 0 let AngleIncrementB = -180 // min=-360, max=360, step=1 const angleIncrement2 = AngleIncrementB * Math.PI / 180 let minimumRadius = 0.75 // min=0.5, max=10, step=0.05 let initialRadius = 3.0 // min=1, max=10, step=0.1 initialRadius = minimumRadius > initialRadius ? minimumRadius : initialRadius; const circleArray = [createCircle(-5, -5, initialRadius, Math.PI * 16)]; let ratio = 0.999; const initialRatio = ratio; let currentCircle = circleArray[0]; let failures = 0; const t = new Turtle(); t.pd(); t.radians(); function walk(i){ if (i === 0){ drawCircle(circleArray[0], t); } else { currentCircle = getAndCheck(currentCircle, circleArray); } return i < 100000; } function createCircle(x, y, rad, heading){ return [x, y, rad, heading]; } function checkCircles(c1, c2){ const xd = (c2[0] - c1[0]) ** 2; const yd = (c2[1] - c1[1]) ** 2; const dsq = xd + yd; return dsq >= (c1[2] + c2[2]) ** 2; } function drawCircle(c, turtle){ turtle.jmp(c[0], c[1] - c[2]); // turtle.seth(c[3]) turtle.circle(c[2]) } function getNextCircle(c){ let radiusOld = c[2]; let radiusNew = radiusOld * ratio; radiusNew = radiusNew < minimumRadius ? minimumRadius : radiusNew let headingNew = c[3] += angleIncrement1 //* [-1, 0, 1][Math.floor(Math.random() * 3)]; c[3] = headingNew; let d = ((radiusOld + radiusNew) * 2 + minimumRadius) / 2; let xOld = c[0]; let yOld = c[1]; let xNew = xOld + d * Math.cos(headingNew); let yNew = yOld + d * Math.sin(headingNew); return createCircle(xNew, yNew, radiusNew, headingNew); } function checkBounds(c){ let add = 1; add *= c[0] < 100 - c[2]; add *= c[0] > -100 + c[2]; add *= c[1] < 100 - c[2]; add *= c[1] > -100 + c[2]; return add; } function getAndCheck(c1, circleArray){ let c2 = getNextCircle(currentCircle); let add = 1; add *= checkBounds(c2); let newC; for (let c of circleArray){ if (!add){ break; } add *= checkCircles(c, c2); if (!add){ newC = c; break; } } if (!add){ // c1[3] += angleIncrement2 failures++; if (failures > maxFailures){ failures = 0; c1[3] += angleIncrement2; ratio *= 0.975 + shrinkageAcceleration / 4000; radius = initialRadius; let index = circleArray.indexOf(c1) - 1; index = index < 0 ? circleArray.length - 1 : index; // return circleArray[index]; return circleArray[Math.floor(Math.random() * circleArray.length)] } return currentCircle; } else { ratio = initialRatio; drawCircle(c2, t); circleArray.push(c2); return c2; } }