Spiral of circles

Inspired by Compote de plot: twitter.com/loic_gou…380873256611840?s=12

Log in to post a comment.

//  LL 2021

const loops = 5;       // min=1 max=10 step=0.01
const radius_max = 4;  // min=1 max=20 step=0.1
const frequency = 0.1; // min=0 max=1 step=0.01
const density = 0.6;   // min=.1 max=1 step=0.01
const seed = 0;        // min=0 max=100 step=.1

var noise = SimplexNoise(seed ? seed : Math.floor(Math.random() * 1000));

const turtle = new Turtle();

const circles = 50000;
const angle_step = Math.PI * 2 * loops / circles;
const inner_radius_max = 90;
const inner_radius_step = inner_radius_max / circles;

var last_x = 0, last_y = 0;

function walk(i) {
    const inner_radius = i * inner_radius_step;
    const angle = i * angle_step;

    const x = inner_radius * Math.cos(angle);
    const y = inner_radius * Math.sin(angle);
    
    if (Math.hypot(x - last_x, y - last_y) < (2 - density * 2))  return true;

    last_x = x; last_y = y;

    const radius = Math.min(getRadius(x, y, inner_radius), inner_radius / 3);
    turtle.jump(x, y - radius);
    turtle.circle(radius);
    
    return i < circles;
}

function getRadius(x, y, r) {
    const rx = x / 10 * frequency;
    const ry = y / 10 * frequency;
    const rr = r / 100 * frequency;

    var radius = noise.noise3D([rx, ry, rr]);
    radius += .55 * noise.noise3D([rx * 2 + 3.4, ry * 2 - 56.1, rr * 2 - 4.5 ]);
    radius += .35 * Math.abs(1 - noise.noise3D([ rx * 4 + 21.2, ry * 4 + .5, rr * 4 - 8.7 ]));
    radius += .25 * Math.abs(1 - noise.noise3D([ rx * 8 + 421.12, ry * 8 + 21.3, rr * 8 - 45.3 ]));
    radius *= radius_max;

    return radius;
}

////////////////////////////////////////////////////////////////
// Simplex Noise utility code. Created by Reinder Nijhoff 2020
// https://turtletoy.net/turtle/6e4e06d42e
// Based on: http://webstaff.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
////////////////////////////////////////////////////////////////
function SimplexNoise(t=1){const a=[[1,1,0],[-1,1,0],[1,-1,0],[-1,-1,0],[1,0,1],[-1,0,1],[1,0,-1],[-1,0,-1],[0,1,1],[0,-1,1],[0,1,-1],[0,-1,-1]],o=new Uint8Array(512),r=(Math.sqrt(3)-1)/2,h=1/3,n=(3-Math.sqrt(3))/6,s=1/6,e=(t,a)=>t[0]*a[0]+t[1]*a[1],M=(t,a)=>[t[0]-a[0],t[1]-a[1]],l=(t,a)=>t[0]*a[0]+t[1]*a[1]+t[2]*a[2],c=(t,a)=>[t[0]-a[0],t[1]-a[1],t[2]-a[2]];return new class{constructor(t=1){for(let t=0;t<512;t++)o[t]=255&t;for(let a=0;a<255;a++){const r=(t=this.hash(a+t))%(256-a)+a,h=o[a];o[a+256]=o[a]=o[r],o[r+256]=o[r]=h}}noise2D(t){const h=e(t,[r,r]),s=[Math.floor(t[0]+h),Math.floor(t[1]+h)],l=255&s[0],c=255&s[1],f=e(s,[n,n]),m=M(t,M(s,[f,f])),x=m[0]>m[1]?[1,0]:[0,1],i=M(M(m,x),[-n,-n]),u=M(m,[1-2*n,1-2*n]);let q=Math.max(0,.5-e(m,m))**4*e(a[o[l+o[c]]%12],m);return q+=Math.max(0,.5-e(i,i))**4*e(a[o[l+x[0]+o[c+x[1]]]%12],i),70*(q+=Math.max(0,.5-e(u,u))**4*e(a[o[l+1+o[c+1]]%12],u))}noise3D(t){const r=l(t,[h,h,h]),n=[Math.floor(t[0]+r),Math.floor(t[1]+r),Math.floor(t[2]+r)],e=255&n[0],M=255&n[1],f=255&n[2],m=l(n,[s,s,s]),x=c(t,c(n,[m,m,m])),[i,u]=x[0]>=x[1]?x[1]>=x[2]?[[1,0,0],[1,1,0]]:x[0]>=x[2]?[[1,0,0],[1,0,1]]:[[0,0,1],[1,0,1]]:x[1]<x[2]?[[0,0,1],[0,1,1]]:x[0]<x[2]?[[0,1,0],[0,1,1]]:[[0,1,0],[1,1,0]],q=c(c(x,i),[-s,-s,-s]),w=c(c(x,u),[-2*s,-2*s,-2*s]),D=c(x,[1-3*s,1-3*s,1-3*s]);let p=Math.max(0,.6-l(x,x))**4*l(a[o[e+o[M+o[f]]]%12],x);return p+=Math.max(0,.6-l(q,q))**4*l(a[o[e+i[0]+o[M+i[1]+o[f+i[2]]]]%12],q),p+=Math.max(0,.6-l(w,w))**4*l(a[o[e+u[0]+o[M+u[1]+o[f+u[2]]]]%12],w),32*(p+=Math.max(0,.6-l(D,D))**4*l(a[o[e+1+o[M+1+o[f+1]]]%12],D))}hash(t){const a=1103515245*((t=1103515245*(t>>1^t))^t>>3);return a^a>>16}}(t)}