Super slow for extra enjoyment.
Log in to post a comment.
Canvas.setpenopacity(1); const precision = 300; /// min=3 max=1000 step=1 const concentric = 50; // min=1 max=100 step=1 const density = 0.25; // min=0.0.1 max=3 step=0.01 const radius = 90; // min=0 max=300 step=1 const epicenters = 25; // min=1 max=1000 step=1 const variation = 0.0; // min=0 max=0.5 step=0.01 const frequency = 4; // min=1 max=10 step=0.1 const turtle = new Turtle(); let circle_list; let radius_t = radius; let epicenter_list; function walk(i, t) { if (i == 0) { circle_list = []; epicenter_list = []; while (epicenter_list.length < epicenters) { var x, y; if (radius < 0.1) { var retries = 100; var done = false; while (retries-- > 0 && !done) { x = (Math.random() - 0.5) * 200; y = (Math.random() - 0.5) * 200; done = true; epicenter_list.forEach(e => { const distance = Math.hypot(x-e.x, y-e.y); if (distance < 10) done = false; }); } } else { const i = epicenter_list.length; const r = radius_t * ((1-variation) + Math.sin(Math.PI * 2 * frequency / epicenters * i) * variation * 2); x = r * Math.cos(Math.PI/2 + Math.PI * 2 / epicenters * i); y = r * Math.sin(Math.PI/2 + Math.PI * 2 / epicenters * i); } epicenter_list.push({x:x, y:y, r:0.4}); } radius_t = radius * (Math.cos(Math.PI * 2 * t) + 1) / 2; } const e = epicenter_list[i % epicenters]; const c = new Circle(e.x, e.y, e.r); e.r += 1/density; c.clip(circle_list); if (c.lines.length > 10) { c.draw(); circle_list.push(c); } return (i+1) < concentric * epicenters; } class Circle { constructor(x, y, r) { this.x = x; this.y = y; this.r = r; this.lines = []; const p = Math.max(3, Math.round(precision * this.r / 10)); const step = Math.PI * 2 / p; for (var i=0; i<p; i++) { const a0 = step * i; const a1 = step * (i+1); const x0 = this.x + Math.cos(a0) * this.r; const y0 = this.y + Math.sin(a0) * this.r; const x1 = this.x + Math.cos(a1) * this.r; const y1 = this.y + Math.sin(a1) * this.r; this.lines.push({start:{x:x0, y:y0}, end:{x:x1, y:y1}}); } } draw() { this.lines.forEach(l => { turtle.jump(l.start.x, l.start.y); turtle.goto(l.end.x, l.end.y); }) } // This would benefit from some serious optimization // For starters: 3 calls to hypot need to go clip(list) { list.forEach(c => { if (this.x - c.x < c.r + this.r && this.y - c.y < c.r + this.r) { const distance = Math.hypot(this.x - c.x, this.y - c.y); if (distance < (c.r + this.r)) { if (distance < (c.r - this.r)) { this.lines = []; } const to_delete = []; this.lines.forEach((l, i) => { if ((Math.abs(l.start.x) > 150 || Math.abs(l.start.y) > 150) && (Math.abs(l.end.x) > 150 || Math.abs(l.end.y) > 150)) { to_delete.unshift(i); } else { const d0 = Math.hypot(l.start.x - c.x, l.start.y - c.y); const d1 = Math.hypot(l.end.x - c.x, l.end.y - c.y); if (d0 < c.r || d1 < c.r) { to_delete.unshift(i); } } }); to_delete.forEach(i => { this.lines.splice(i, 1); }); } } }); } }