Log in to post a comment.

// You can find the Turtle API reference here: https://turtletoy.net/syntax
Canvas.setpenopacity(-.8);

// Global code will be evaluated once.
const turtle = new Turtle();
const n = 6; // min=1, max=20, step=1
const nTwigs = 6 // min=3, max=30, step=1
const pFlip = .5; // min=0, max=1, step=0.01
const pMutate = .5; // min=0, max=1, step=0.01
const pTriangleOverHexagon = .5; // min=0, max=1, step=0.01
const randomHeading = 1; //min=0, max=1, step=1

// The walk function will be called until it returns false.
function walk(i) {
    let size = 150 / n;

    for(let x = (100 / n); x < 200; x+=200/n) {
        for(let y = (100 / n); y < 200; y+=200/n) {
            turtle.jump(x - 100, y - 100);
            turtle.seth(randomHeading == 0? 0: randn_bm(1, 360));
            flake(size * randn_bm(0.2, 1.5), nTwigs, pFlip, pMutate, pTriangleOverHexagon);
        }
    }
    return false;
}

function flake(size, nTwigs, pFlip, pMutate, pTriangleOverHexagon) {
    let twigLength = size / 2;
    let nBranches = Math.floor(randn_bm(1, 13));
    let twigBranches = branch(nBranches, pFlip, pMutate, pTriangleOverHexagon);
    
    let twigRatios = [];
    for(let i = 0; i < nBranches; i++) {
        twigRatios[i] = randn_bm(0,1, 1.3);
    }
    
    let twigOrigins = [];
    for(let i = 0; i <= nBranches; i++) {
        twigOrigins[i] = randn_bm(0, 10);
    }
    twigOrigins = normalize(twigOrigins);

    for(let sym = 0; sym < nTwigs; sym++) {
        for(let i = 0; i < nBranches; i++) {
            turtle.forward(twigOrigins[i] * twigLength);
            
            twigBranches[i](twigLength * twigRatios[i] * ( 1 - (i/nBranches) ));

            if(i == nBranches - 1) {
                turtle.forward(twigOrigins[nBranches] * twigLength);
            }
        }
        turtle.up();
        turtle.backward(twigLength);
        turtle.down();
        turtle.right(360 / nTwigs);
    }
}

function branch(n,  pFlip, pMutate, pTriangleOverHexagon) {
    let b = [];
    
    let simpleLine = function(length, direction) {
        turtle.down();
        
        if(direction > 0) {
            turtle.left(180);
        }
        
        turtle.right(60);
        turtle.forward(length);
        turtle.up();
        turtle.backward(length);
        turtle.left(120);
        turtle.down();
        turtle.forward(length);
        turtle.up();
        turtle.backward(length);
        turtle.right(60);
        
        if(direction > 0) {
            turtle.left(180);
        }
        
        turtle.down();
    }
    
    let triangle = function(length, direction) {
        turtle.down();

        if(direction > 0) {
            turtle.left(180);
        }

        turtle.left(30);
        turtle.forward(length);
        turtle.right(120);
        turtle.forward(length);
        turtle.right(120);
        turtle.forward(length);
        turtle.right(150);

        if(direction > 0) {
            turtle.left(180);
        }
    }
    
    let hexagon = function(length, direction) {
        turtle.up();
        
        turtle.forward(length / 2);
        turtle.right(60);
        turtle.down();
        for(let i = 0; i < 6; i++) {
            turtle.right(60);
            turtle.forward(length / 2);
        }
        turtle.left(60);
        turtle.up();
        turtle.backward(length / 2);
        turtle.down();
    }
    
    for(let i = 0; i < n; i++) {
        let f = Math.random(0, 1) > pMutate? simpleLine: (Math.random(0, 1) < pTriangleOverHexagon? triangle: hexagon);
        b[i] = Math.random(0, 1) < pFlip? function (l) { f(l, 1); } : function(l) { f(l, -1); } ;
    }
    return b;
}

function normalize(inArray) {
    let sum = inArray.reduce((a, b) => a + b, 0);
    let outArray = [];
    for(let i = 0; i < inArray.length; i++) {
        outArray[i] = inArray[i] / sum;
    }
    return outArray;
}

// function below is normal distribution radmon generator
// https://stackoverflow.com/questions/25582882/javascript-math-random-normal-distribution-gaussian-bell-curve#49434653
// by joshuakcockrell answered Mar 22 '18 at 17:14
function randn_bm(min, max, skew = 1) {
  let u = 0, v = 0;
  while(u === 0) u = Math.random() //Converting [0,1) to (0,1)
  while(v === 0) v = Math.random()
  let num = Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v )
  
  num = num / 10.0 + 0.5 // Translate to 0 -> 1
  if (num > 1 || num < 0) 
    num = randn_bm(min, max, skew) // resample between 0 and 1 if out of range
  
  else{
    num = Math.pow(num, skew) // Skew
    num *= max - min // Stretch to fill range
    num += min // offset to min
  }
  return num
}