L-System

Developer
Size
6,807 Kb
Views
32,384

How do I make an l-system?

Recently fascinated by L-Systems, named after Aristid Lindenmayer. Read more about it: * L-System wikipedia . What is a l-system? How do you make a l-system? This script and codes were developed by Pimskie on 16 September 2022, Friday.

L-System Previews

L-System - Script Codes HTML Codes

<!DOCTYPE html>
<html >
<head> <meta charset="UTF-8"> <title>L-System</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css"> <link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="controls"> <select class="js-curve"> <option value="hilbert">Hilbert</option> <option value="koch">koch</option> <option value="kochSnowflake">koch snowflake</option> <option value="sierpinski">sierpinski</option> <option value="sierpinskiArrowHead">sierpinskiArrowHead</option> <option value="levy" >Lévy C curve</option> <option value="peanoGosper">Peano-Gosper Curve</option> <option value="peano">Peano Curve</option> <option value="dragon" selected>Dragon curve</option> <option value="tree">Tree</option> <option value="tree2">Tree 2</option> </select>
</div>
<canvas class="canvas js-canvas" width="500" height="500"></canvas> <script src="js/index.js"></script>
</body>
</html>

L-System - Script Codes CSS Codes

html,
body { margin: 0; padding: 0; overflow: hidden;
}
.controls,
.canvas { position: absolute;
}
.controls { z-index: 10; top: 0; right: 0;
}
.canvas { z-index: 1; display: block;
}

L-System - Script Codes JS Codes

'use strict';
var qs = function qs(sel) {	return document.querySelector(sel);
};
var toRadian = Math.PI / 180;
var canvas = qs('canvas');
var ctx = canvas.getContext('2d');
var width = window.innerWidth;
var height = window.innerHeight;
canvas.width = width;
canvas.height = height;
var maxDepth = 6;
var defaultScale = 10;
var curveScale = defaultScale;
var dimensions = {	minX: null,	maxX: null,	minY: null,	maxY: null
};
var currentDepth = 0;
var currentAngle = 0;
var hilbert = {	axiom: 'A',	result: 'A',	variables: ['A', 'B'],	rules: {	'A': '-BF+AFA+FB-',	'B': '+AF-BFB-FA+'	},	angle: 90 * toRadian
};
var koch = {	axiom: 'F',	result: 'F',	rules: {	'F': 'F+F-F-F+F'	},	angle: 90 * toRadian
};
var kochSnowflake = {	axiom: 'F++F++F',	result: 'F',	rules: {	'F': 'F-F++F-F'	},	angle: 60 * toRadian
};
var sierpinski = {	axiom: 'F-G-G',	result: 'F-G-G',	rules: {	'F': 'F-G+F+G-F',	'G': 'GG'	},	angle: 120 * toRadian
};
var sierpinskiArrowHead = {	axiom: 'A',	result: 'A',	rules: {	'A': '+B-A-B+',	'B': '-A+B+A-'	},	angle: 60 * toRadian,	maxDepth: 8
};
var levy = {	axiom: 'F',	result: 'F',	rules: {	'F': '+F--F+'	},	angle: -45 * toRadian,	maxDepth: 15
};
var tree = {	axiom: 'X',	result: 'X',	rules: {	'X': 'F-[[X]+X]+F[+FX]-X',	'F': 'FF'	},	angle: -25 * toRadian,	startAngle: -90 * toRadian,	stack: []
};
var tree2 = {	axiom: 'X',	result: 'X',	rules: {	'X': 'F[+X][-X]FX',	'F': 'FF'	},	angle: -25.7 * toRadian,	startAngle: -90 * toRadian,	stack: []
};
var peanoGosper = {	axiom: 'A',	result: 'A',	rules: {	'A': 'A-B--B+A++AA+B-',	'B': '+A-BB--B-A++A+B'	},	startAngle: 0,	angle: 60 * toRadian,	stack: [],	maxDepth: 5
};
var peano = {	axiom: 'F',	result: 'F',	rules: {	'F': 'F+F-F-F-F+F+F+F-F'	},	maxDepth: 4,	angle: 90 * toRadian,	stack: []
};
var dragon = {	axiom: 'FX',	result: 'FX',	variables: ['X', 'Y'],	rules: {	'X': 'X+YF+',	'Y': '-DX-Y'	},	angle: 90 * toRadian,	stack: [],	maxDepth: 15
};
var presets = {	hilbert: hilbert,	koch: koch,	kochSnowflake: kochSnowflake,	sierpinski: sierpinski,	sierpinskiArrowHead: sierpinskiArrowHead,	levy: levy,	tree: tree,	tree2: tree2,	peanoGosper: peanoGosper,	peano: peano,	dragon: dragon
};
var x = 0;
var y = 0;
var clear = function clear() {	ctx.clearRect(0, 0, width, height);
};
var adjustAngle = function adjustAngle(curve, plusMinus) {	if (plusMinus === '+') {	currentAngle -= curve.angle;	} else {	currentAngle += curve.angle;	}
};
var stackPush = function stackPush(curve) {	curve.stack.push([x, y, currentAngle]);
};
var stackPop = function stackPop(curve) {	var _curve$stack$pop = curve.stack.pop();	x = _curve$stack$pop[0];	y = _curve$stack$pop[1];	currentAngle = _curve$stack$pop[2];
};
var drawLine = function drawLine(curve, instruction) {	var runForDimensions = arguments.length <= 2 || arguments[2] === undefined ? true : arguments[2];	var nextX = x + Math.cos(currentAngle) * curveScale;	var nextY = y + Math.sin(currentAngle) * curveScale;	if (!runForDimensions) {	ctx.beginPath();	ctx.moveTo(x, y);	ctx.lineTo(nextX, nextY);	ctx.stroke();	ctx.closePath();	}	x = nextX;	y = nextY;	if (runForDimensions) {	if (!dimensions.minX || x < dimensions.minX) {	dimensions.minX = x;	}	if (!dimensions.maxX || x > dimensions.maxX) {	dimensions.maxX = x;	}	if (!dimensions.minY || y < dimensions.minY) {	dimensions.minY = y;	}	if (!dimensions.maxY || y > dimensions.maxY) {	dimensions.maxY = y;	}	}
};
/** * Draws a curve, sort of.. * * Used in two ways: * first to draw the pattern with a default line length, and get the dimensions * This run isn't painted on the canvas. - runForDimensions = true * * Second, draw and paint the pattern. But with the dimensions of the first run, * scaling and positioning is applied so it fits the screen. - runForDimensions = false */
var drawCurve = function drawCurve(curve) {	var runForDimensions = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1];	clear();	x = 0;	y = 0;	currentAngle = curve.startAngle || 0;	currentDepth = 0;	curve.stack = [];	// remove the variables from the result string, they aren't needed anymore	var variablesPattern = (curve.variables || []).join('|');	var regex = new RegExp(variablesPattern, 'g');	var lSystemString = curve.result.replace(regex, '');	// by splitting the filtered string, we have a list of instructions (turn left, turn right, draw, etc)	var curveInstructions = lSystemString.split('');	// TODO: make this better, clearer	if (!runForDimensions) {	var w = (Math.abs(dimensions.minX) + dimensions.maxX) / (defaultScale / curveScale);	var h = (Math.abs(dimensions.minY) + dimensions.maxY) / (defaultScale / curveScale);	var offsetX = Math.abs(dimensions.minX) / (defaultScale / curveScale) + width * 0.5 - w * 0.5;	var offsetY = -dimensions.minY / (defaultScale / curveScale) + height * 0.5 - h * 0.5;	ctx.save();	ctx.translate(offsetX, offsetY);	}	curveInstructions.forEach(function (instruction) {	var method = map[instruction] || drawLine;	method(curve, instruction, runForDimensions);	});	if (!runForDimensions) {	ctx.restore();	}
};
var reset = function reset(curve) {	x = 0;	y = 0;	dimensions = {	minX: null,	maxX: null,	minY: null,	maxY: null	};	currentAngle = curve.startAngle || 0;	currentDepth = 0;	curveScale = defaultScale;	curve.stack = [];	curve.result = curve.axiom;
};
var generate = function generate(curve) {	reset(curve);	var maxLoops = curve.maxDepth || maxDepth;	/** * this is the core, the most important part * within every loop, the alphabeth chararcter (A, B, X, F, etc) gets replaced by their rule * * Since the rule contains one or more alphabeth characters, the product gets longer and longer */	while (currentDepth < maxLoops) {	var pattern = Object.keys(curve.rules).join('|');	var regex = new RegExp(pattern, 'g');	curve.result = curve.result.replace(regex, function (match) {	return curve.rules[match];	});	currentDepth++;	}	// first a 'dry run': don't paint anything, but get the dimensions of the pattern	drawCurve(curve, true);	// with the dimensions, a scaling can be calculated so it fits the screen	var totalWidth = Math.abs(dimensions.minX) + dimensions.maxX;	var totalHeight = Math.abs(dimensions.minY) + dimensions.maxY;	var scaleWidth = window.innerWidth / totalWidth;	var scaleHeight = window.innerHeight / totalHeight;	curveScale = defaultScale * Math.min(scaleWidth, scaleHeight);	// with that information, the pattern can be drawn on the canvas	drawCurve(curve, false);
};
var map = {	'+': adjustAngle,	'-': adjustAngle,	'[': stackPush,	']': stackPop
};
var presetSelect = qs('.js-curve');
presetSelect.addEventListener('change', function (e) {	generate(presets[e.target.value]);
});
generate(presets[presetSelect.value]);
L-System - Script Codes
L-System - Script Codes
Home Page Home
Developer Pimskie
Username pimskie
Uploaded September 16, 2022
Rating 3.5
Size 6,807 Kb
Views 32,384
Do you need developer help for L-System?

Find the perfect freelance services for your business! Fiverr's mission is to change how the world works together. Fiverr connects businesses with freelancers offering digital services in 500+ categories. Find Developer!

Pimskie (pimskie) Script Codes
Create amazing video scripts with AI!

Jasper is the AI Content Generator that helps you and your team break through creative blocks to create amazing, original content 10X faster. Discover all the ways the Jasper AI Content Platform can help streamline your creative workflows. Start For Free!