Artistic Corona
COVID-19 🦠(variation)
Log in to post a comment.
const plottable = 0; //min=0 max=1 step=1 (No, Yes) const rMin = 1.5; //min=1 max=5 step=.5 const rMax = 8; //min=5 max=10 step=.5 const bigR = 80; //min=40 max=90 step=5 const margin = 1; const grayScaleSteps = 20; //min=2 max=40 step=1 const rTailIncrease = 1.03; //min=.8 max=1.2 step=.01 const distDev100 = .5; //min=0 max=2 step=.1 // You can find the Turtle API reference here: https://turtletoy.net/syntax Canvas.setpenopacity(plottable == 1? -1: -1/grayScaleSteps); // Global code will be evaluated once. let baleSize = grayScaleSteps; const bales = Array.apply(null,{length: baleSize}).map(b => new Bale(baleSize--)); let cp = new CirclePacker(bigR); // The walk function will be called until it returns false. function walk(i) { let c = cp.get(100, (rMin + ((rMax - rMin) * Math.random())) / bigR, margin / bigR); if(c != null) { for(let j = 0; j < grayScaleSteps; j += (plottable == 0? 1: grayScaleSteps /5)) { let r = c[4] * (plottable == 1? 1: Math.pow(rTailIncrease, j)); bales[j].jump(Math.cos(c[0]) * c[1] * Math.pow(1 + (distDev100/100), j), Math.sin(c[0]) * c[1] * Math.pow(1 + (distDev100/100), j) - r); bales[j].circle(r); } } return i < 500; } function CirclePacker(radius) { class CirclePacker { pts = [] //a, r, x, y, radius constructor(radius) { this.r = radius; } get(candidates = 10, radiusRatio = .5, marginRatio = .02) { let cs = Array.apply(null,{length: candidates}).map(b => [ Math.PI * 2 * Math.random(), Math.sqrt(Math.random()) * this.r ]); cs = cs.map(i => [...i, Math.cos(i[0]) * i[1], Math.sin(i[0]) * i[1], 0] ); //i: cA, cR, x, y, r for(let csi = 0; csi < cs.length; csi++) { //radius = minimum(max allowed radius, max possible radius to fit in this) cs[csi][4] = Math.min(this.r * radiusRatio, this.r - (cs[csi][2]**2+cs[csi][3]**2)**.5); for(let ptsi = 0; ptsi < this.pts.length; ptsi++) { cs[csi][4] = Math.min(cs[csi][4], (((this.pts[ptsi][2] - cs[csi][2])**2 + (this.pts[ptsi][3] - cs[csi][3])**2)**.5 - this.pts[ptsi][4])); } cs[csi][4] -= this.r * marginRatio; } cs.sort((a,b) => a[4] < b[4]? 1: -1); if(cs[0][4] < this.r * marginRatio) { return null; } this.pts.push(cs[0]); return cs[0]; } } return new CirclePacker(radius); } //////////////////////////////////////////////////////////////// // Bale utility code - Created by Jurgen Westerhof 2022 // https://turtletoy.net/turtle/7269af8a23 // Abusing the opacity, usage: // Canvas.setpenopacity(1/baleSize); // const bales = Array.apply(null,{length: baleSize}).map(b => new Bale(baleSize--); // Then use bales[x] wherever you would use a turtle object to 'draw' // in 'color' x (i.e Polygon hatching with a bale object and .15 interspacing) //////////////////////////////////////////////////////////////// function Bale(n) { class Bale { constructor(n) { this.turtles = Array.apply(null,{length: n}).map(i => new Turtle()); } back(e) { this.turtles.map(t => t.back(e)); return this; } backward(e) { this.turtles.map(t => t.backward(e)); return this; } bk(e) { this.turtles.map(t => t.bk(e)); return this; } fd(e) { this.turtles.map(t => t.fd(e)); return this; } forward(e) { this.turtles.map(t => t.forward(e)); return this; } left(e) { this.turtles.map(t => t.left(e)); return this; } lt(e) { this.turtles.map(t => t.lt(e)); return this; } right(e) { this.turtles.map(t => t.right(e)); return this; } rt(e) { this.turtles.map(t => t.rt(e)); return this; } seth(e) { this.turtles.map(t => t.seth(e)); return this; } setheading(e) { this.turtles.map(t => t.setheading(e)); return this; } setx(e) { this.turtles.map(t => t.setx(e)); return this; } sety(e) { this.turtles.map(t => t.sety(e)); return this; } setpos(x, y) { this.turtles.map(t => t.setpos(x, y)); return this; } setposition(x, y) { this.turtles.map(t => t.setposition(x, y)); return this; } toradians(e) { this.turtles.map(t => t.toradians(e)); return this; } degrees(e) { this.turtles.map(t => t.degrees(e)); return this; } goto(x, y) { this.turtles.map(t => t.goto(x, y)); return this; } jmp(x, y) { this.turtles.map(t => t.jmp(x, y)); return this; } jump(x, y) { this.turtles.map(t => t.jump(x, y)); return this; } circle(radius, extent, steps) { this.turtles.map(t => t.circle(radius, extent, steps)); return this; } clone() { let b = new Bale(this.turtle.length); this.turtles.map((t, k) => b.turtles[k] = t.clone()); return b; } h() { return this.turtles[0].h(); } heading() { return this.turtles[0].heading(); } home() { this.turtles.map(t => t.home()); return this; } isdown() { return this.turtles[0].isdown(); } pos() { return this.turtles[0].pos(); } position() { return this.turtles[0].position(); } pd() { this.turtles.map(t => t.pd()); return this; } pendown() { this.turtles.map(t => t.pendown()); return this; } penup() { this.turtles.map(t => t.penup()); return this; } pu() { this.turtles.map(t => t.pu()); return this; } down() { this.turtles.map(t => t.down()); return this; } up() { this.turtles.map(t => t.up()); return this; } radians() { this.turtles.map(t => t.radians()); return this; } x() { return this.turtles[0].x(); } xcor() { return this.turtles[0].xcor(); } y() { return this.turtles[0].y(); } ycor() { return this.turtles[0].ycor(); } } return new Bale(n); }