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);
}