fixed and sorted/added comments to L-System
This commit is contained in:
@@ -1,178 +1,257 @@
|
||||
let angle = 3.141592653589*1.5;
|
||||
let angleDecrement = 1;
|
||||
let stepSize = 10;
|
||||
let widthIncrement = 1;
|
||||
let currentWidth = 1;
|
||||
let currentPosition = [501 / 2, 500];
|
||||
let fractalst = "FF+[+F-F-F]-[-F+F+F]";
|
||||
let stackList = [];
|
||||
let lineLenghtScaleFactor = 1.5;
|
||||
/*
|
||||
L-System Fractal Generator
|
||||
|
||||
The following characters have a geometric interpretation:
|
||||
|
||||
Character Meaning
|
||||
F Move forward by line length drawing a line
|
||||
f Move forward by line length without drawing a line
|
||||
+ Turn left by turning angle
|
||||
- Turn right by turning angle
|
||||
| Reverse direction (ie: turn by 180 degrees)
|
||||
[ Push current drawing state onto stack
|
||||
] Pop current drawing state from the stack
|
||||
# Increment the line width by line width increment
|
||||
! Decrement the line width by line width increment
|
||||
@ Draw a dot with line width radius
|
||||
{ Open a polygon
|
||||
} Close a polygon and fill it with fill colour
|
||||
> Multiply the line length by the line length scale factor
|
||||
< Divide the line length by the line length scale factor
|
||||
& Swap the meaning of + and -
|
||||
( Decrement turning angle by turning angle increment
|
||||
) Increment turning angle by turning angle increment
|
||||
*/
|
||||
|
||||
let angle = Math.PI * 1.5;
|
||||
let turningAngle = Math.PI * 0.5;
|
||||
let lineLength = 5;
|
||||
let lineWidthIncrement = 1;
|
||||
let currentLineWidth = 1;
|
||||
let currentPosition = [0, 0];
|
||||
let stateStack = [];
|
||||
let lineLengthScaleFactor = 1.5;
|
||||
let swapPlusMinusState = false;
|
||||
let turningAngleIncrement = 0.1;
|
||||
let polygonVertices = [];
|
||||
let polygonOpen = false;
|
||||
|
||||
//FF+[+F-F-F]-[-F+F+F] fork
|
||||
let axiom = 'F+F+F+F';
|
||||
let maxIterations = 4;
|
||||
const maxCalculations = 50000;
|
||||
let rules = {
|
||||
'F': 'FF+F-F+F+FF'
|
||||
};
|
||||
|
||||
// Generate the fractal string from axiom and rules
|
||||
for (let i = 0; i < maxIterations; i++) {
|
||||
if (axiom.length > maxCalculations) {//hard coded limit to prevent infinite loops
|
||||
console.log('Reached max calculations, stopping at iteration', i);
|
||||
break;
|
||||
}
|
||||
let newAxiom = '';
|
||||
for (let char of axiom) {//loop through each character in the axiom and replace it with the corresponding rule
|
||||
if (rules[char]) {
|
||||
newAxiom += rules[char];
|
||||
} else {
|
||||
newAxiom += char;
|
||||
}
|
||||
}
|
||||
axiom = newAxiom;
|
||||
}
|
||||
|
||||
function setup() {
|
||||
console.log("setup");
|
||||
createCanvas(windowWidth, windowHeight);
|
||||
background(255, 255, 255)
|
||||
background(255, 255, 255);
|
||||
noFill();
|
||||
stroke(0, 0, 0);
|
||||
strokeWeight(1);
|
||||
currentPosition = [width / 2, height];
|
||||
strokeWeight(currentLineWidth);
|
||||
currentPosition = [width / 2, height - 100];
|
||||
generateFractal();
|
||||
}
|
||||
|
||||
function generateFractal() {
|
||||
for (let i = 0; i < fractalst.length; i++) {
|
||||
let c = fractalst.charAt(i);
|
||||
for (let i = 0; i < axiom.length; i++) {
|
||||
let c = axiom.charAt(i);
|
||||
switch (c) {
|
||||
case "F":
|
||||
forward();
|
||||
break;
|
||||
case "+":
|
||||
plus();
|
||||
break;
|
||||
case "-":
|
||||
minus();
|
||||
moveForwardDraw();
|
||||
break;
|
||||
case "f":
|
||||
forwardNoLine();
|
||||
moveForwardNoDraw();
|
||||
break;
|
||||
case "+":
|
||||
turnLeft();
|
||||
break;
|
||||
case "-":
|
||||
turnRight();
|
||||
break;
|
||||
case "|":
|
||||
reverseDirection();
|
||||
break;
|
||||
case "#":
|
||||
lineWidthIncrement();
|
||||
break;
|
||||
case "!":
|
||||
lineWidthDecrement();
|
||||
break;
|
||||
case "[":
|
||||
pushStack(i);
|
||||
pushState(i);
|
||||
break;
|
||||
case "]":
|
||||
popStack(i);
|
||||
popState(i);
|
||||
break;
|
||||
case ">":
|
||||
lineWidthMultiply();
|
||||
case "#":
|
||||
incrementLineWidth();
|
||||
break;
|
||||
case "<":
|
||||
lineWidthDivide();
|
||||
break;
|
||||
case "&":
|
||||
swapPlusMinus();
|
||||
case "!":
|
||||
decrementLineWidth();
|
||||
break;
|
||||
case "@":
|
||||
drawDot();
|
||||
break;
|
||||
case "{":
|
||||
openPolygon();
|
||||
break;
|
||||
case "}":
|
||||
closePolygon();
|
||||
break;
|
||||
case ">":
|
||||
multiplyLineLength();
|
||||
break;
|
||||
case "<":
|
||||
divideLineLength();
|
||||
break;
|
||||
case "&":
|
||||
swapPlusMinus();
|
||||
break;
|
||||
case ")":
|
||||
angleIncrement();
|
||||
incrementTurningAngle();
|
||||
break;
|
||||
case "(":
|
||||
angleDecrement();
|
||||
decrementTurningAngle();
|
||||
break;
|
||||
default:
|
||||
console.log("unrecognized character",c);
|
||||
// Ignore characters not in the specification (like X)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function minus() {
|
||||
if (swapPlusMinusState) {
|
||||
angle += angleDecrement;
|
||||
return
|
||||
// F: Move forward by line length drawing a line
|
||||
function moveForwardDraw() {
|
||||
let x = currentPosition[0] + cos(angle) * lineLength;
|
||||
let y = currentPosition[1] + sin(angle) * lineLength;
|
||||
if (polygonOpen) {
|
||||
polygonVertices.push([x, y]);
|
||||
} else {
|
||||
line(currentPosition[0], currentPosition[1], x, y);
|
||||
}
|
||||
angle -= angleDecrement;
|
||||
}
|
||||
|
||||
function plus() {
|
||||
if (swapPlusMinusState) {
|
||||
angle -= angleDecrement;
|
||||
return
|
||||
}
|
||||
angle += angleDecrement;
|
||||
}
|
||||
|
||||
function lineWidthIncrement(){
|
||||
currentWidth + widthIncrement;
|
||||
strokeWeight(currentWidth);
|
||||
}
|
||||
|
||||
function lineWidthDecrement(){
|
||||
currentWidth - widthIncrement;
|
||||
strokeWeight(currentWidth);
|
||||
}
|
||||
|
||||
function forward() {
|
||||
let x = currentPosition[0] + cos(angle) * stepSize;
|
||||
let y = currentPosition[1] + sin(angle) * stepSize;
|
||||
line(currentPosition[0], currentPosition[1], x, y);
|
||||
currentPosition = [x, y];
|
||||
}
|
||||
|
||||
function forwardNoLine(){
|
||||
let x = currentPosition[0] + cos(angle) * stepSize;
|
||||
let y = currentPosition[1] + sin(angle) * stepSize;
|
||||
// f: Move forward by line length without drawing a line
|
||||
function moveForwardNoDraw() {
|
||||
let x = currentPosition[0] + cos(angle) * lineLength;
|
||||
let y = currentPosition[1] + sin(angle) * lineLength;
|
||||
currentPosition = [x, y];
|
||||
}
|
||||
|
||||
function backward() {
|
||||
let x = currentPosition[0] - cos(angle) * stepSize;
|
||||
let y = currentPosition[1] - sin(angle) * stepSize;
|
||||
line(currentPosition[0], currentPosition[1], x, y);
|
||||
currentPosition = [x, y];
|
||||
}
|
||||
|
||||
function reverseDirection(){
|
||||
angle - 3.14159265358979323;
|
||||
}
|
||||
|
||||
function pushStack(i){
|
||||
console.log(angle)
|
||||
stackList.push([i,currentPosition[0],currentPosition[1],angle,currentWidth]);
|
||||
}
|
||||
|
||||
function popStack(i){
|
||||
stackToPop = stackList.length - 1;
|
||||
console.log(stackList[stackToPop])
|
||||
currentPosition = [stackList[stackToPop][1],stackList[stackToPop][2]];
|
||||
angle = stackList[stackToPop][3];
|
||||
strokeWeight[stackList[stackToPop][4]]
|
||||
}
|
||||
|
||||
function lineWidthMultiply(){
|
||||
currentWidth * lineLenghtScaleFactor;
|
||||
strokeWeight(currentWidth);
|
||||
}
|
||||
|
||||
function lineWidthDivide(){
|
||||
currentWidth / lineLenghtScaleFactor;
|
||||
strokeWeight(currentWidth);
|
||||
}
|
||||
|
||||
function swapPlusMinus(){
|
||||
// +: Turn left by turning angle
|
||||
function turnLeft() {
|
||||
if (swapPlusMinusState) {
|
||||
swapPlusMinusState = false;
|
||||
angle -= turningAngle;
|
||||
return
|
||||
}
|
||||
swapPlusMinusState = true;
|
||||
angle += turningAngle;
|
||||
}
|
||||
|
||||
// -: Turn right by turning angle
|
||||
function turnRight() {
|
||||
if (swapPlusMinusState) {
|
||||
angle += turningAngle;
|
||||
return
|
||||
}
|
||||
angle -= turningAngle;
|
||||
}
|
||||
|
||||
// |: Reverse direction (turn by 180 degrees)
|
||||
function reverseDirection() {
|
||||
angle += Math.PI;
|
||||
}
|
||||
|
||||
// [: Push current drawing state onto stack
|
||||
function pushState(i) {
|
||||
stateStack.push([i, currentPosition[0], currentPosition[1], angle, currentLineWidth]);
|
||||
}
|
||||
|
||||
// ]: Pop current drawing state from the stack
|
||||
function popState(i) {
|
||||
let stackIndex = stateStack.length - 1;
|
||||
currentPosition = [stateStack[stackIndex][1], stateStack[stackIndex][2]];
|
||||
angle = stateStack[stackIndex][3];
|
||||
currentLineWidth = stateStack[stackIndex][4];
|
||||
strokeWeight(currentLineWidth);
|
||||
}
|
||||
|
||||
// #: Increment the line width by line width increment
|
||||
function incrementLineWidth() {
|
||||
currentLineWidth += lineWidthIncrement;
|
||||
strokeWeight(currentLineWidth);
|
||||
}
|
||||
|
||||
// !: Decrement the line width by line width increment
|
||||
function decrementLineWidth() {
|
||||
currentLineWidth -= lineWidthIncrement;
|
||||
strokeWeight(currentLineWidth);
|
||||
}
|
||||
|
||||
// @: Draw a dot with line width radius
|
||||
function drawDot() {
|
||||
let x = currentPosition[0];
|
||||
let y = currentPosition[1];
|
||||
strokeWeight(currentWidth);
|
||||
strokeWeight(currentLineWidth);
|
||||
point(x, y);
|
||||
}
|
||||
|
||||
function angleIncrement() {
|
||||
angle += turningAngleIncrement;
|
||||
// {: Open a polygon
|
||||
function openPolygon() {
|
||||
polygonVertices = [[currentPosition[0], currentPosition[1]]];
|
||||
polygonOpen = true;
|
||||
}
|
||||
|
||||
function angleDecrement() {
|
||||
angle -= turningAngleIncrement;
|
||||
// }: Close a polygon and fill it with fill colour
|
||||
function closePolygon() {
|
||||
if (polygonOpen && polygonVertices.length > 2) {
|
||||
fill(100, 150, 255); // Default fill colour
|
||||
beginShape();
|
||||
for (let v of polygonVertices) {
|
||||
vertex(v[0], v[1]);
|
||||
}
|
||||
endShape(CLOSE);
|
||||
noFill(); // Reset to no fill
|
||||
}
|
||||
polygonVertices = [];
|
||||
polygonOpen = false;
|
||||
}
|
||||
|
||||
// >: Multiply the line length by the line length scale factor
|
||||
function multiplyLineLength() {
|
||||
lineLength *= lineLengthScaleFactor;
|
||||
}
|
||||
|
||||
// <: Divide the line length by the line length scale factor
|
||||
function divideLineLength() {
|
||||
lineLength /= lineLengthScaleFactor;
|
||||
}
|
||||
|
||||
// &: Swap the meaning of + and -
|
||||
function swapPlusMinus() {
|
||||
swapPlusMinusState = !swapPlusMinusState;
|
||||
}
|
||||
|
||||
// ): Increment turning angle by turning angle increment
|
||||
function incrementTurningAngle() {
|
||||
turningAngle += turningAngleIncrement;
|
||||
}
|
||||
|
||||
// (: Decrement turning angle by turning angle increment
|
||||
function decrementTurningAngle() {
|
||||
turningAngle -= turningAngleIncrement;
|
||||
}
|
||||
|
||||
function draw() {
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
2images.js, AbstractAlgorithm.js, calmCircles.js, Cubes.js, image.js,
|
||||
imageNoice.js, labyrinth.js, L-System.js
|
||||
imageNoice.js, labyrinth.js, L-System.js
|
||||
Reference in New Issue
Block a user