L-System 003

An L-system or Lindenmayer system is a parallel rewriting system and a type of formal grammar: en.wikipedia.org/wiki/l-system.

#fractal #lsystem #snowflake

Log in to post a comment.

// Forked from "L-System" by reinder
// https://turtletoy.net/turtle/9dbc3c4cf0

// Global code will be evaluated once.
// const turtle = new Turtle(0,0);

//const turtle = new Turtle();
const turtle = new Slowbro(); turtle.thickness = 1;

const iterations = 5; //min= 1, max=5, step=1

// l-system
function createLSystem(numIters, axiom) {
    let s = axiom;
    for (let i=0; i<numIters; i++) {
        s = processString(s);
    }
    return s;
}

function processString(oldStr) {
    let newstr = "";
    for (let i=0; i<oldStr.length; i++) {
        newstr += applyRules(oldStr[i]);
    }
    return newstr;
}

function applyRules(ch) {
    switch (ch) {
        case "F": return "FF+FF+FFF"; //   # Rule 1
        default: return ch;
    }
}

const inst = createLSystem(iterations, "F"); // number of iterations and axiom
const distance = 9;
const angle = 60;

// The walk function will be called until it returns false.
function walk(i) {
    const cmd = inst[i];
    
    switch (cmd) {
        case "F":   turtle.forward(distance);
                    break;
        case "B":   turtle.backward(distance);
                    break;
        case "+":   turtle.right(angle);
                    break;
        case "-":   turtle.left(angle);
                    break;
        default:
    }
      
    return i < inst.length - 1;
}

////////////////////////////////////////////////////////////////
// Slowbro utility code. Created by Lionel Lemarie 2021
// Built on Reinder's Slowpoke, which removes most duplicate lines
// Slowbro adds optional thickness to the lines
////////////////////////////////////////////////////////////////
function Slowbro(x, y) {
    const linesDrawn = {};
    class Slowbro extends Turtle {
        constructor(x, y) {
        	super(x, y);
        	this.thickness = 1; this.offset = 0.2;
			this.slowpoke_skip = this.slowpoke_draw = 0;
        }
        goto(x, y) {
            if (Array.isArray(x)) { y = x[1]; x = x[0]; }
            const ox = this.x(), oy = this.y();
            if (this.isdown()) {
                const p = [x, y], o = [ox, oy];
                const h1 = o[0].toFixed(2) + '_' + p[0].toFixed(2) + o[1].toFixed(2) + '_' + p[1].toFixed(2);
                const h2 = p[0].toFixed(2) + '_' + o[0].toFixed(2) + p[1].toFixed(2) + '_' + o[1].toFixed(2);
                if (linesDrawn[h1] || linesDrawn[h2]) {
                    super.up(); super.goto(p); super.down();
                    this.slowpoke_skip++;
                    return;
                }
                linesDrawn[h1] = linesDrawn[h2] = true;
                this.slowpoke_draw++;

            	for (var dx = this.thickness-1; dx >=0 ; dx--) {
            		for (var dy = this.thickness-1; dy >= 0; dy--) {
            			if (!dx && !dy) continue;
            			super.goto( x + dx * this.offset,  y + dy * this.offset);
            			super.goto(ox + dx * this.offset, oy + dy * this.offset);
            		}
            	}
            } 
            super.goto(x, y);
        }
    }
    return new Slowbro(x, y);
}