DISK ⭕

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