Stochastic L-systems add probability distributions to the production rules in order to model the variations which would occur between individual specimens of a given plant.
This L-system is based on chapter 1.7 "Stochastic L-systems" of the book "The Algorithmic Beauty of Plants" by Przemyslaw Prusinkiewicz & Aristid Lindenmayer
algorithmicbotany.org/
This turtle is forked from "Fractal plant #1" by reinder
Fractal plant #1
#lsystem
Log in to post a comment.
// --------------------------------------------------
// CREDITS
// --------------------------------------------------
// Forked from "Fractal plant #1" by reinder
// https://turtletoy.net/turtle/b750bb0220
//
// Based on chapter 1.7 "Stochastic L-systems"
// of the book "The Algorithmic Beauty of Plants"
// by Przemyslaw Prusinkiewicz & Aristid Lindenmayer
//
// http://algorithmicbotany.org/
// --------------------------------------------------
// Setup
Canvas.setpenopacity(.5);
// Put the turtle in the bottom left corner pointed toward the top right corner
const turtle = new Turtle(-100,100);
turtle.left(45);
// The number of times to evaluate the production rules before drawing the result
const recursion = 5; // min=1, max=10, step=1
// The number of degrees in a left or right turn when drawing
const angle = 22; // min=0, max=90, step=1
// The distance to travel forward or back when drawing
const distance = 2; // min=1, max=10, step=0.25
// The starting string for the l-system
const axiom = "F";
// The rules and probabilities for transforming symbols in the L-system
// For a given production rule, all probability values should sum to 1.0
const productions = {
"F": [
{
probability: 0.20,
to: "F[+F]F[-F]F"
},
{
probability: 0.40,
to: "FF-[-F+F+O]+[+F-F-F]"
},
{
probability: 0.40,
to: "FF+[+F-F-F]-[-F+F+O]"
}
]
}
// 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) {
let r = Math.random();
let p = 0;
let rules = productions[ch];
// If there are no replacement productions, leave the character as-is.
if (!rules) {
return ch;
}
// Choose the production rule with the appropriate probability
for (let i=0; i<rules.length; i++) {
p += rules[i].probability;
if (r < p) {
return rules[i].to;
}
}
// If something is amiss with the probabilities, fall back to the last rule listed
return rules[rules.length - 1].to;
}
// Calculate the the final string to render.
const inst = createLSystem(recursion, axiom);
const states = [];
// 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;
case "O": turtle.circle(distance / 2);
break;
case "[": states.push({
x: turtle.xcor(),
y: turtle.ycor(),
h: turtle.heading()
});
break;
case "]": const state = states.pop();
turtle.penup();
turtle.goto(state.x, state.y);
turtle.setheading(state.h);
turtle.pendown();
break;
default:
}
return i < inst.length - 1;
}