Homework Nine: Forest of Trees


Project Writeup

The overall objective of this homework assingment was to create a class that handles an L(Lindenmayer)-System, and then a program that uses the L-system class to create shapes. Professor Maxwell provided us with a skeleton for the class with the capability to handle L-systems. He provided some of the methods which he already wrote, but we had to write the following methods: set(), setIterations(), setAngle(), getAngle(), generateString(), and write(). The set() method was simply a method that stores all the parameters entered when the lsystem class is called into certain fields. An lsystem requires six parts: a base string, a rule, a symbol for which the rule will be replaced for each occurance in the l-system, an angle, the number of iterations through which the rule will be replaced in the base string, and the distance. The rule parameter in this case is a list that holds a series of lists. Each list in the list first holds two items; the first item is a symbol, and the second item in the list is the rule for replacement. My set method looks like this:



This set method contains all of the fields in the l-system class. The self.baseString stores a string data type entered by the user. The self.rules field stores a list of lists for the purpose described in the previous paragraph. The self.iterations field holds an integer data type that determines how many times the rule will be replaced within the continuously updated base string. The self.angle stores a floating point data type that determines how far left or right the turtle will turn when commanded within the base string. The self.distance field stores an integer data type that determines how far forward the turtle will go forward for each forward command within the base string.

The setIterations method allowed the user to enter a new value for the number of iterations to be complemented within a certain l-system, and the code was a conditional if statment that tested to make sure the value entered was less than 10 and greater than zero before setting the value to the self.iterations field. The setAngle() method was simply setting a given value for angle into the self.angle field, and the getAngle() method simply returned the value in the self.angle field.

The generate string method is what takes advantage of the replace method within the string class to create a given l-system string. My code first makes a copy of the base string, which I stored in a variable copyString. Then I used a for statement that iterated by an amount specified in the self.iterations field. Each time through the loop I used replace method take the second item in the self.rules list (for this assignment there is only one rules list within the self.rules list) and will replace that string within the copy of the base string for each occurance of the first item in the self.rules list, and stores this l-system string into a variable. The last line of the code returns this string.

The write method had to write the l-system string to a given file. First using file method for python, a given file is opened and the syntax 'w' is entered to demonstrate that something will be written to the file. Then, using the generic write method, the self.baseString, self.iterations, self.angle, and self.distance are written to the given file. This order was important because this is how Professor Maxwell set up the read method(). The fields that do not contain a string data type had to be converted to a string in order for the write method to work properly. A newline character also had to be added to the end of each so that the split method in the read method (written by Professor Maxwell) would work. The tricky part of this write() method was writing the self.rules to a file, because it contains a list with two items. In order to write the self.rules field to a file, a for loop was used that iterated through the length of the self.rules list (this step was a mute point for this exercise because there is only one item in the rules list, but hopefully this will save a little time on a future project where multiple lists are in the self.rules list). Then a string was created that started with a flag word 'rule' (which is important for Professor Maxwell's read method to function), and then added the first and second items of the self.rules list to a string, each separated with white space and ending with a newline character (needed for the split method in the read function). This 'rulesString' was then written to the file last.

To create a final scene I took a file created by Professor Maxwell, parse.py, that was used to test our methods in the lsystem2.py skeleton file, and modified the main function. This file contains a processString function that correlates characters in the l-system string into turtle actions. In the main function, I created a bunch of objects with the l-system class created, and then made a call to set method for each in order to make some new l-systems (one taken from Professor Maxwell's parse.py file, the others from the Algorithmic Beauty of Plants). I then used a nested for loop to draw these l-systems randomly into a cluster in order to appear like a forest. The outer loop iterated through the length of a list 'forest' that I created which held each of the l-system objects. With each iteration through the outer loop, I made a randX variable that created a random value that would change with each iteration through the outer loop. With the inner loop, I iterated through each item in the forest list. Within the inner loop, the first part of the code created a conditional if statement that changed the random number created in the randX variable to be positive or negative (with a probability of 50% for each) with each iteration through the inner loop. Inside the inner loop, I also created a randY variable that simply moved trees up by a random amount from the bottom line of the -300 coordinate. I then moved the turtle to the point(randX, randY), and drew the a different l-system with each iteration through the list. I need to thank Brittany Thomas for helping me with this aspect of the code. She also showed my how to modify the processString function so that the turtle would return to its initial position after drawing a leaf. Using the nested for loop to draw the l-systems randomly, I got the following image:



Here is an image that clearly displays each of my l-systems, with the code for each l-system appearing below the picture. The 'L1' object is the tree on the far left of the image, while the 'L4' object is the tree on the far right side of the image.





And lastly, a little random color added to the forest with a purely green base...


Back To Home Page