The following Processing program uses a well-known L-System (see this Wikipedia page for more information) to “grow” a realistic looking plant with fractal structure. Below is a video of the frames generated by the program followed by the code that created it.
import java.util.Stack; // I use java Stack objects
// written by Jeff - www.fiz-ix.com
String wseq = "0"; // the starting string of the L-System
Stack xSave = new Stack(); // a Stack to store x coordinates of plant
Stack ySave = new Stack(); // a Stack to store y coordinates of plant
Stack aSave = new Stack(); // a Stack to store angles of branches
int height = 400; // height of output
int width = 400; // width of output
int zz = 0; // interation of L-System
void setup() {
size(width,height);
background(200,224,255); // blue
frameRate(1);
}
void draw() {
zz++;
if (zz > 7) { // start growing from scratch again
zz = 1;
wseq = "0";
background(200,224,255);
}
int treeLength = height/15;
int xStart = width/2;
int yStart = 0;
background(200,224,255);
drawPlant(zz, treeLength, xStart, yStart);
iteratePlant();
delay(3000);
}
void iteratePlant() { // a function to generate successive
// iterations of the L-System
String wseq0 = wseq;
wseq = "";
for (int ii=0;ii < wseq0.length();ii++) {
String cchar = wseq0.substring(ii,ii+1);
if (cchar.equals("0")) { // replace 0 with following string
wseq = wseq + "1MLL0RP0RP1LP10RM0";
}
else if (cchar.equals("L")) { // keep L
wseq = wseq + 'L';
}
else if (cchar.equals("R")) { // keep R
wseq = wseq + "R";
}
else if (cchar.equals("P")) { // keep P
wseq = wseq + "P";
}
else if (cchar.equals("M")) { // keep M
wseq = wseq + "M";
}
else if (cchar.equals("1")) { // replace 1 with 11
wseq = wseq + "11";
}
}
}
void drawPlant(int iteration, int treeLength, int xStart, int yStart) {
int lineLength = treeLength/iteration;
int nBNow = 0; // keep track of the number of branches in the plant
// initial parameters
color lc = color(0, 255, 0); // leaf color is green
color bc = color(117, 71, 25); // branch color is brown
int xNow = xStart;
int yNow = yStart;
double aNow = 1.57079632679; // 90 degrees
double aDelta = 0.436332313; // 25 degrees
for (int ii=0;ii<wseq.length();ii++) {
String cchar = wseq.substring(ii,ii+1);
// the following are the rules for the "turtle" to draw the
// L-System
if (cchar.equals("0")) {
// do nothing
}
else if (cchar.equals("1")) { // draw a line segment
int xStop = xNow+(int)(lineLength*Math.cos(aNow));
int yStop = yNow+(int)(lineLength*Math.sin(aNow));
fill(bc);
stroke(bc);
strokeWeight(0.2*(zz*3-nBNow));
line(xNow,height-yNow,xStop,height-yStop);
xNow = xStop;
yNow = yStop;
}
else if (cchar.equals("M")) { // change direction by aDelta
aNow = aNow + aDelta;
}
else if (cchar.equals("P")) { // change direction by -aDelta
aNow = aNow - aDelta;
}
else if (cchar.equals("L")) { // push the current x and y
// coordinates and angle to the Stacks
xSave.push(new Integer(xNow));
ySave.push(new Integer(yNow));
aSave.push(new Double(aNow));
nBNow++; // one more branch
}
else if (cchar.equals("R")) { // draw a leaf and recover last
// items from the Stacks
fill(lc);
stroke(lc);
strokeWeight(1);
ellipse(xNow,height-yNow,3+iteration,3+iteration);
// draw a leaf
xNow = (Integer)xSave.pop(); // recover last saved x coordinate
yNow = (Integer)ySave.pop(); // recover last saved y coordinate
aNow = (Double)aSave.pop(); // recover last saved angle
nBNow--;
}
}
}