L Systems

Summary
This assignment dealt with a generative code method called L-Systems. Using push() and pop(), and the Java Turtle library, we were able to display generative artwork and interesting designs.
Task 1 - Humble Beginnings
To familiarize ourselves with the most basic of concepts related to L-Systems, task one required implementing penUP(), goToPoint(), and penDown() as methods of creating simple shapes.
Code Box 1
Show Code
import Turtle.*;
Turtle t;
void setup(){
size(400,400);
background(255);
t = new Turtle(this);
t.goToPoint(50, 50);
t.setHeading(90);
drawLetterI();
t.goToPoint(150, 50);
t.setHeading(90);
drawLetterT();
}
void drawLetterI(){
int heightI = 100;
int widthI = 40;
t.penDown();
t.forward(widthI);
t.penUp();
t.back(widthI / 2);
t.right(90);
t.penDown();
t.forward(heightI);
t.penUp();
t.left(90);
t.forward(widthI / 2);
t.penDown();
t.back(widthI);
t.penUp();
}
void drawLetterT(){
int widthT = 60;
int heightT = 100;
t.penDown();
t.forward(widthT);
t.penUp();
t.back(widthT / 2);
t.right(90);
t.penDown();
t.forward(heightT);
t.penUp();
}
Output:

Code Box 2
Show Code
import Turtle.*;
Turtle t;
void setup() {
size(400, 400);
background(255);
t = new Turtle(this);
// Draw a triangle
t.goToPoint(10, 100);
t.setHeading(0);
drawTriangle();
// Draw a regular pentagon
t.goToPoint(100, 100);
t.setHeading(0);
drawPentagon();
// Draw a circle
t.goToPoint(200, 100);
t.setHeading(0);
drawCircle(50);
}
void drawTriangle() {
int side = 60;
t.penDown();
for (int i = 0; i < 3; i++) {
t.forward(side);
t.right(120);
}
t.penUp();
}
void drawPentagon() {
int side = 50;
t.penDown();
for (int i = 0; i < 5; i++) {
t.forward(side);
t.right(72);
}
t.penUp();
}
void drawCircle(float r) {
float step = (2 * PI * r) / 360.0;
t.penDown();
for (int i = 0; i < 360; i++) {
t.forward(step);
t.right(1);
}
t.penUp();
}
Output:

Task 2 - Square L-System
With the help of a provided code skeleton, a simple square based L-System can be iterated through.
Code Box 3
Show Code
// Main Processing Sketch for L-System Assignment
import processing.svg.*;
import processing.pdf.*;
import Turtle.*;
boolean shouldExportAsPDF = false; // Change to true for PDF export
int numIterations = 0; // Global iteration counter
BaseLSystem lSys; // L-System instance
Turtle t; // Turtle instance
void setup() {
size(1000, 1000);
background(255);
stroke(0);
t = new Turtle(this);
lSys = initSquare(); // Create an instance of our concrete L-System
noLoop();
printInstructions();
}
void draw() {
background(255);
resetTurtle();
lSys.reset();
for (int i = 0; i < numIterations; i++) {
lSys.iterate();
}
lSys.drawLSystem(t);
lSys.printIterationNumber();
lSys.printState();
}
void keyPressed() {
switch (key) {
case 'n':
numIterations = max(0, numIterations - 1);
redraw();
break;
case 'm':
numIterations++;
redraw();
break;
case 's':
String fileType = (shouldExportAsPDF) ? ".pdf" : ".svg";
String fileName = "H:/Downloads/" + getDateString() + fileType;
beginRecord((shouldExportAsPDF) ? PDF : SVG, fileName);
setup();
draw();
endRecord();
println("Saved to file: " + fileName);
break;
}
}
void resetTurtle() {
t.penUp();
t.clearTurtleHistory();
t.goToPoint(width-50, height-50);
t.setHeading(0);
t.penDown();
}
void printInstructions() {
println("======== L-System Instructions ========");
println("Press 'm' to increment the L-system iterations.");
println("Press 'n' to decrement the L-system iterations.");
println("Press 's' to save to PDF/SVG.");
println("=======================================");
}
String getDateString() {
String time = hour() + "_" + minute() + "_" + second();
String date = year() + "_" + month() + "_" + day();
return date + "-" + time;
}
BaseLSystem initSquare() {
String axiom = "F-F-F-F";
float moveDistance = 10;
float rotateAngle = 90;
float scaleFactor = 1.0;
return new SquareLSystem(axiom, moveDistance, rotateAngle, scaleFactor);
}
// -----------------------
// BaseLSystem and SquareLSystem classes here...
Output:
Task 3 - Making Our Own
Once we've established usage of L-Systems, task 3 involved coming up with our own custom generative designs
Design 1: Serpinski Triangle
Code Box 4
Show Code
import processing.svg.*;
import processing.pdf.*;
import Turtle.*;
boolean shouldExportAsPDF = false;
int numIterations = 0;
BaseLSystem lSys;
Turtle t;
void setup() {
size(1000, 1000);
background(255);
stroke(0);
t = new Turtle(this);
lSys = initSierpinski();
noLoop();
printInstructions();
}
void draw() {
background(255);
resetTurtle();
lSys.reset();
for (int i = 0; i < numIterations; i++) {
lSys.iterate();
}
lSys.drawLSystem(t);
lSys.printIterationNumber();
lSys.printState();
}
void keyPressed() {
switch (key) {
case 'n':
numIterations = max(0, numIterations - 1);
redraw();
break;
case 'm':
numIterations++;
redraw();
break;
case 's':
String fileType = (shouldExportAsPDF) ? ".pdf" : ".svg";
String fileName = "H:/Downloads/" + getDateString() + fileType;
beginRecord((shouldExportAsPDF) ? PDF : SVG, fileName);
setup();
draw();
endRecord();
println("Saved to file: " + fileName);
break;
}
}
void resetTurtle() {
t.penUp();
t.clearTurtleHistory();
t.goToPoint(width/1.6, height-20);
t.setHeading(0);
t.penDown();
}
void printInstructions() {
println("======== Sierpinski L-System Instructions ========");
println("Press 'm' to increment the L-system iterations.");
println("Press 'n' to decrement the L-system iterations.");
println("Press 's' to save to PDF/SVG.");
println("==================================================");
}
String getDateString() {
String time = hour() + "_" + minute() + "_" + second();
String date = year() + "_" + month() + "_" + day();
return date + "-" + time;
}
BaseLSystem initSierpinski() {
String axiom = "A";
float moveDistance = 5;
float rotateAngle = 60;
float scaleFactor = 1.0;
return new SierpinskiLSystem(axiom, moveDistance, rotateAngle, scaleFactor);
}
// -----------------------
// BaseLSystem and SierpinskiLSystem classes here...
Output:
Subtask 3.2
Code Box 5
Show Code
import processing.svg.*;
import processing.pdf.*;
import Turtle.*;
import java.util.Stack;
boolean shouldExportAsPDF = false;
int numIterations = 0;
BaseLSystem treeLsys;
Turtle t;
void setup() {
size(1000, 1000);
background(255);
stroke(0);
t = new Turtle(this);
treeLsys = initTreeLSystem();
noLoop();
printInstructions();
}
void draw() {
background(255);
resetTurtle();
treeLsys.reset();
for (int i = 0; i < numIterations; i++) {
treeLsys.iterate();
}
treeLsys.drawLSystem(t);
treeLsys.printIterationNumber();
treeLsys.printState();
}
void keyPressed() {
switch (key) {
case 'n':
numIterations = max(0, numIterations - 1);
redraw();
break;
case 'm':
numIterations++;
redraw();
break;
case 's':
String fileType = (shouldExportAsPDF) ? ".pdf" : ".svg";
String fileName = "H:/Downloads/" + getDateString() + fileType;
beginRecord((shouldExportAsPDF) ? PDF : SVG, fileName);
setup();
draw();
endRecord();
println("Saved to file: " + fileName);
break;
}
}
void resetTurtle() {
t.penUp();
t.clearTurtleHistory();
t.goToPoint(width/2, height-50);
t.setHeading(0);
t.penDown();
}
void printInstructions() {
println("======== Instructions ========");
println("Press 'm' to increment tree iterations.");
println("Press 'n' to decrement tree iterations.");
println("Press 's' to save to PDF/SVG.");
println("================================");
}
String getDateString() {
String time = hour() + "_" + minute() + "_" + second();
String date = year() + "_" + month() + "_" + day();
return date + "-" + time;
}
BaseLSystem initTreeLSystem() {
String axiom = "F";
float moveDistance = 3;
float rotateAngle = 90;
float scaleFactor = 1.0;
return new TreeLSystem(axiom, moveDistance, rotateAngle, scaleFactor);
}
// -----------------------
// BaseLSystem and TreeLSystem classes here...
Output:
Subtask 3.3
Code Box 6
Show Code
import processing.svg.*;
import processing.pdf.*;
import Turtle.*;
boolean shouldExportAsPDF = false;
int numIterations = 0;
BaseLSystem hexLsys;
Turtle t;
void setup() {
size(1000, 1000);
background(255);
stroke(0);
t = new Turtle(this);
hexLsys = initHexagonLSystem();
noLoop();
printInstructions();
}
void draw() {
background(255);
resetTurtle();
hexLsys.reset();
for (int i = 0; i < numIterations; i++) {
hexLsys.iterate();
}
hexLsys.drawLSystem(t);
hexLsys.printIterationNumber();
hexLsys.printState();
}
void keyPressed() {
switch(key) {
case 'n':
numIterations = max(0, numIterations - 1);
redraw();
break;
case 'm':
numIterations++;
redraw();
break;
case 's':
String fileType = (shouldExportAsPDF) ? ".pdf" : ".svg";
String fileName = "H:/Downloads/hexLsystem-" + getDateString() + fileType;
beginRecord((shouldExportAsPDF) ? PDF : SVG, fileName);
setup();
draw();
endRecord();
println("Saved to file: " + fileName);
break;
}
}
void resetTurtle() {
t.penUp();
t.clearTurtleHistory();
t.goToPoint(width/2, height/2);
t.setHeading(0);
t.penDown();
}
void printInstructions() {
println("======== Hexagon L-System Instructions ========");
println("Press 'm' to increment iterations.");
println("Press 'n' to decrement iterations.");
println("Press 's' to save to PDF/SVG (H:/Downloads).");
println("============================================");
}
String getDateString() {
String time = hour() + "_" + minute() + "_" + second();
String date = year() + "_" + month() + "_" + day();
return date + "-" + time;
}
BaseLSystem initHexagonLSystem() {
String axiom = "F+F-F-F-F-F";
float moveDistance = 10;
float rotateAngle = 60;
float scaleFactor = 1.0;
return new HexagonLSystem(axiom, moveDistance, rotateAngle, scaleFactor);
}
// -----------------------
// BaseLSystem and HexagonLSystem classes here...
Output:

Task 4 - Laser Engraving
Last Step was to bring some of the designs to life. Using the ITLL Laser Cutters and the included code for exporting svgs, I was able to accomplish this easily.
Conclusion
This was a very fun and interesting assignment, and I learned a lot about L-systems and generative designing.