### Fractal fractal

Fractal IFS text. Inspired by the 'CHAOS' fractal on Paul Bourke's site.
Letters look just as bad as my handwriting. Work in progress

// Forked from "Barnsley fern" by reinder

// https://turtletoy.net/turtle/7e604ce874
// Your word in all caps here (not too long)
var word = "FRACTAL";

Canvas.setpenopacity(-1);

const turtle = new Turtle();

let x = 0;
let y = 0;

function d2r(degrees){
return degrees * (Math.PI/180);
}

function angle(thetha){
return [[Math.cos(d2r(thetha)),-Math.sin(d2r(thetha))]
,[Math.sin(d2r(thetha)), Math.cos(d2r(thetha))]];
}

// Assuming 2x2 matrices as input
function mm(a, b){
return [[a[0][0]*b[0][0] + a[0][1]*b[1][0], a[0][0]*b[0][1] + a[0][1]*b[1][1]],
[a[1][0]*b[0][0] + a[1][1]*b[0][1], a[1][0]*b[0][1] + a[1][1]*b[1][1]]];
}

function stretch(x_scale, y_scale){
return [[x_scale, 0.],
[0., y_scale]];
}

var k = 2.0;
var scale = [[k, 0.],[0., k]];
var thickness = 0.07;
var length_factor = 0.065;

var letters = {
"A": [[1.0*length_factor, thickness, 75, -0.125, 0.5],
[1.0*length_factor, thickness, -65, 0.125, 0.8],
[0.3*length_factor, thickness,0, 0, 0.45]],
"B": [[1.0*length_factor, thickness, 90, -0.15, 0.5],
[0.35*length_factor, thickness, 90, 0.3, 0.77],
[0.5*length_factor, thickness, 0, 0, 1.],
[0.5*length_factor, thickness, 0, 0, 0.5],
[0.5*length_factor, thickness, 0, 0, 0.125],
[0.35*length_factor, thickness, 90, 0.4, 0.3]
],
"C": [[0.5*length_factor, thickness, 0, -0.125, 1.0],
[0.5*length_factor, thickness,0, -0.125, 0.2],
[1.0*length_factor, thickness, 90, -0.25, 0.5]],
"D": [[0.5*length_factor, thickness, -15, -0.125, 1.0],
[0.5*length_factor, thickness,15, -0.125, 0.125],
[1.0*length_factor, thickness, 90, -0.25, 0.5],
[0.9*length_factor, thickness, 90, 0.2, 0.5]],
"E": [[0.5*length_factor, thickness, 0, 0., 1.0],
[0.5*length_factor, thickness,0, 0, 0.2],
[1.0*length_factor, thickness, 90, -0.125, 0.5],
[0.3*length_factor, thickness,0, 0, 0.6]],
"F": [[1.0*length_factor, thickness, 0, 0., 1.0],
[0.5*length_factor, thickness,0, 0, 0.5],
[1.0*length_factor, thickness, 90, -0.25, 0.5]],
"G": [[1.0*length_factor, thickness, 90, -0.25, 0.5],
[0.5*length_factor, thickness, 0, -0.125, 1.0],
[0.5*length_factor, thickness,0, -0.125, 0.125],
[0.5*length_factor, thickness, 90, 0.25, 0.2],
[0.4*length_factor, thickness,0, 0, 0.5]],
"H": [[1.0*length_factor, thickness, 90, -0.25, 0.5],
[1.0*length_factor, thickness, 90, 0.25, 0.5],
[0.5*length_factor, thickness, 0, -0.125, 0.5]],
"I": [[0.8*length_factor, thickness, 90, 0, 0.4], [0.1*length_factor, thickness, 0, -0.125, 1.]],
"J": [[0.5*length_factor, thickness, 0, 0.125, 1.0],
[1.0*length_factor, thickness, 90, 0.25, 0.5],
[0.5*length_factor, thickness, 0, 0.125, 0.0],
[0.5*length_factor, thickness, 90, -0.25, 0.125]],
"K": [[1.0*length_factor, thickness, 90, -0.25, 0.5],
[0.7*length_factor, thickness, 45., 0., 0.7],
[0.7*length_factor, thickness, -45., 0., 0.5]],
"L": [[0.5*length_factor, thickness, 0, -0.125, 0.125],
[1.0*length_factor, thickness, 90, -0.25, 0.5]],
"M": [[1.0*length_factor, thickness, 90, -0.3, 0.5],
[1.0*length_factor, thickness, 90, 0.45, 0.5],
[0.5*length_factor, thickness, 70., 0.2, 0.76],
[0.7*length_factor, thickness, -70., -0.25, 0.88]],
"N": [[1.0*length_factor, thickness, 90, -0.25, 0.5],
[1.0*length_factor, thickness, 90, 0.2, 0.5],
[0.8*length_factor, thickness, -75., -0.25, 0.85]],
"O": [[0.7*length_factor, thickness, 0, -.125, 1.0],
[0.7*length_factor, thickness,0,  -.125, 0.25],
[1.0*length_factor, thickness, 90, -0.25, 0.5],
[1.0*length_factor, thickness, 90, 0.25, 0.5]],
"P": [[1.0*length_factor, thickness, 90, -0.15, 0.5],
[0.35*length_factor, thickness, 90, 0.4, 0.77],
[0.5*length_factor, thickness, 0, 0, 1.],
[0.5*length_factor, thickness, 0, 0, 0.5]],
"Q": [[0.7*length_factor, thickness, 0, -.125, 1.0],
[0.7*length_factor, thickness,0,  -.125, 0.25],
[1.0*length_factor, thickness, 90, -0.25, 0.5],
[1.0*length_factor, thickness, 90, 0.25, 0.5],
[0.7*length_factor, thickness, -45., 0., 0.5]],
"R": [[1.0*length_factor, thickness, 90, -0.15, 0.5],
[0.35*length_factor, thickness, 90, 0.4, 0.77],
[0.5*length_factor, thickness, 0, 0, 1.],
[0.5*length_factor, thickness, 0, 0, 0.5],
[0.7*length_factor, thickness, -30, 0.0, 0.35]],
"S": [[0.7*length_factor, thickness, 0, -.125, 1.0],
[0.7*length_factor, thickness,0,  -.125, 0.],
[0.5*length_factor, thickness, 90, -.25, 0.8],
[0.7*length_factor, thickness,0,  -.125, 0.5],
[0.5*length_factor, thickness, 90, .25, 0.2]],
"T": [[1.0*length_factor, thickness, 0, -0.125, 1.0],
[0.8*length_factor, thickness, 90, 0.125, 0.5]],
"U": [	[0.7*length_factor, thickness,0,  -.125, 0.25],
[1.0*length_factor, thickness, 90, -0.25, 0.5],
[1.0*length_factor, thickness, 90, 0.25, 0.5]],
"V": [[1.0*length_factor, thickness, -70, -0.25, 0.7],
[1.0*length_factor, thickness, 70, 0.25, 0.5]],
"W": [[1.0*length_factor, thickness, 100, -0.3, 0.5],
[1.0*length_factor, thickness, 80, 0.3, 0.5],
[0.7*length_factor, thickness, -70., 0., 0.6],
[0.7*length_factor, thickness, 70., -.125, 0.4]],
"X": [[1.*length_factor, thickness, 45., 0., 0.5],
[1.0*length_factor, thickness, -45., 0., 0.6]],
"Y": [[1.0*length_factor, thickness, -70, -0.25, 0.7],
[1.0*length_factor, thickness, 70, 0.25, 0.5],
[0.6*length_factor, thickness, 90, 0.1, 0.125]],
"Z": [[0.7*length_factor, thickness, 0, -.125, 1.0],
[0.7*length_factor, thickness,0, -.125, 0.25],
[0.7*length_factor, thickness, 55, 0, 0.6]] // Thanks Akash
};

for (const [key, value] of Object.entries(letters)) {
let new_entry = [];
for(let i =0; i<value.length;i++){
let segment = value[i];
let t = mm(mm(angle(segment[2]),stretch(segment[0],segment[1])), scale);
new_entry.push([t[0][0], t[0][1], t[1][0], t[1][1], segment[3]*k, segment[4]*k]);
}
letters[key] = new_entry;
}

function calculate_offset(param, idx, total_length, margin) {
let half_len = (total_length-1)*0.5;
var ret_param = [];
for(let i =0; i<param.length;i++){
//How do I clone (or write javascript?)
ret_param.push([param[i][0], param[i][1], param[i][2], param[i][3], param[i][4] - half_len + idx + idx*margin, param[i][5]]);
}
return ret_param;
}

params = [];

for(let i =0; i<word.length;i++){
console.log();
let param = calculate_offset(letters[word[i]], i, word.length, 1.0);
for(let j =0; j<param.length;j++){
params.push(param[j]);
}
}

function walk(i) {
turtle.pendown();

turtle.jump(-35 + x * 14, 15 - y * 14);
turtle.circle(0.1);

const r = Math.random();

let cumulative_p = 0.;

for(let i =0; i<params.length;i++){
cumulative_p = cumulative_p + 1/params.length;

if(r<cumulative_p){
let a = params[i][0];
let b = params[i][1];
let c = params[i][2];
let d = params[i][3];
let e = params[i][4];
let f = params[i][5];
[x,y] = [a*x + b*y + e, c*x + d*y + f];
break;
}
}

return i < 100000;
}