Base for the algo of
fxhash.xyz/generative/2881
DISK has been published December, 2021
Log in to post a comment.
// Forked from "Circle grid 🌕" by markknol
// https://turtletoy.net/turtle/b7ad210a56
const turtle = new Turtle();
function fxrand() { return Math.random(); }
function range(a,b) { return a + (b-a)*fxrand() }
function pick(arr) { return arr[arr.length*fxrand()|0] }
const dotFillRatio = range(2/3, 1.0); // min=0 max=1, step=0.001
const dotSize = 3;
const dotGrid = pick([10,15,20,25]);
const drawSize = 90;
const discSizes = [drawSize/6, drawSize/5, drawSize/4];
const discInnerRatio = [1/3, 2/3]
const discPositionType = 0 // min=0 max=1, step=1 (radial, grid)
let discPositionRange = drawSize*2/3;
const startAngle = pick([0,Math.PI * 0.5,Math.PI * 0.25]);
const discs = [];
let totalDiscs = discPositionType == 0 ? pick([2,3,4,5,6,7,8,9]) : pick([4,9]); // min=1 max=25, step=1
if (discPositionType == 0 && totalDiscs > 2 && fxrand() > 0.85) {
// append disc to center
totalDiscs --;
discs.push([0, 0, pick(discSizes),pick(discInnerRatio)]);
}
let excluded = 0;
for(let i=0;i<totalDiscs;i++) {
if (discPositionType == 1 && excluded <= 2 && fxrand() > 2/3) {
excluded ++;
continue;
}
let disc;
switch (discPositionType) {
case 0:
let t = i / totalDiscs;
disc = [Math.sin(startAngle+t*Math.PI*2) * discPositionRange, Math.cos(startAngle+t*Math.PI*2) * discPositionRange];
break;
case 1:
let discGrid = totalDiscs == 4 ? 2 : 3;
let discGridOffset = discGrid == 3 ? -0.5 : 0;
if (discGrid == 2) discPositionRange = drawSize;
disc = [-discPositionRange * 0.5 + (i%discGrid + discGridOffset) * discPositionRange, -discPositionRange * 0.5 + ((i/discGrid|0) + discGridOffset) * discPositionRange];
break;
}
disc[2] = pick(discSizes)
disc[3] = pick(discInnerRatio);
discs.push(disc);
}
function hits(pos) {
for(let disc of discs) {
if (dist(disc, pos) < disc[2]) {
return true;
}
}
return false;
}
function walk(i) {
const gridX = (i % dotGrid) + 0.5;
const gridY = (i / dotGrid | 0) + 0.5;
const gridOffset = (drawSize * 2 / dotGrid);
if (i === 0) {
for (let disc of discs) {
let decrease = pick([2,4,6,8])
// outer disk
let dotDrawRadius = disc[2] - (dotSize * disc[3]);
turtle.jump(disc[0], disc[1] - dotDrawRadius);
turtle.circle(dotDrawRadius);
// inner disc
dotDrawRadius = disc[2] * disc[3];
turtle.jump(disc[0], disc[1] - dotDrawRadius);
turtle.circle(dotDrawRadius);
}
}
if (i != 0 && i != dotGrid - 1 && i != dotGrid * dotGrid - dotGrid && i != dotGrid * dotGrid - 1) { // "rounded corner"
let closest = {disc: null, dist: 999999};
const dotPos = [-drawSize + gridX * gridOffset, -drawSize + gridY * gridOffset];
for (let disc of discs) {
const d = dist(disc, dotPos);
if (d < closest.dist) {
closest.disc=disc;
closest.dist=d;
}
}
const closestDisc = closest.disc;
const closestRadius = closestDisc[2];
const randomPosInDisc = add2(dotPos, [(fxrand() - closestDisc[3]) * closestRadius, (fxrand() - closestDisc[3]) * closestRadius]);
const len = dist(randomPosInDisc, closestDisc);
const posInInnerDisc = add2(closestDisc, scl2(sub2(randomPosInDisc, closestDisc), 1 / len * closestRadius));
if (!hits(dotPos)) {
const shouldDraw = fxrand() < dotFillRatio;
if (fxrand() < dotFillRatio) {
const dotDrawRadius = closestDisc[3] * dotSize;
turtle.jump(dotPos[0] , dotPos[1] - dotDrawRadius);
turtle.circle(dotDrawRadius);
turtle.jump(dotPos[0], dotPos[1]);
turtle.goto(posInInnerDisc[0], posInInnerDisc[1]);
}
}
}
return i < dotGrid * dotGrid - 1;
}
// vec2 functions
const scl2=(a,b)=>[a[0]*b,a[1]*b];
const add2=(a,b)=>[a[0]+b[0],a[1]+b[1]];
const sub2=(a,b)=>[a[0]-b[0],a[1]-b[1]];
const dist_sqr2=(a,b)=>(a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1]);
const dist=(a,b)=>Math.sqrt(dist_sqr2(a,b));