Last time, I have explained the basic of Fractal and L-System. Basically L-System is a one of many techniques that used to generate fractal geometries. In this article, I will focus on creating l-system using java. This is not the only way to implement l-system using java. You can find another way or you can create your own way. Before I begin with the code, I will explain about the l-system parts that we’re about to create.
We will divide the system into 6 classes. They are Module, ModuleString, ConditionEvaluator, ParameterModifier, Production, and ProductionManager.
Module will represent one character on our string. It can also contain another parameters which can affect the process of generating new string and affect how the interpreter will draw each character on our string. The parameter can be in any type you want. You can make it generic by using Object as the type of the parameters. I will use my own class as the parameters.
ModuleString will represent our string or the sequence of Module. Actually, this ModuleString class is just a mere wrapper class for the list of Module. I create it to make it easier for us to manage the string.
ConditionEvaluator is just an interface. We will use ConditionEvaluator to evaluate the condition before the string replacement occurs. ParameterModifier is also an interface. It is used to modify each Module’s paramaters after the string replacement occurs.
Production will represent one production rule that exists in the current l-system. This class will store the predecessor and successor string of each production rule. It also store the required condition needed by the rule to replace the string and also how the production should modify the parameters after replacement.
The last one is ProductionManager. This class will manage all the production in one l-system. It also have to apply each the production to each Module on the predecessor string.
This class will have an ID, which is the character that represented by the Module. We will use the ID to compare whether two compared Modules are equal or not. And I will also make an array of Dbl to contain the other parameters. Dbl is only a wrapper class for double type. I make it myself so of course you can’t use that type on your code. You can either create one for yourself or Change it to another type. It’s fine as long as it can store your parameters. Here is my code.
As I said before, this class is basically only a wrapper for the list of Modules. Just make sure when you put a new Module to this ModuleString, you have to put a copy of the Module, not the real one. It is because later we have to modify the parameters of the Modules. If we don’t store the copy, it will store the referenced instance of the Module which means if we change the parameters, all of the other instance that refer to it will also change. To make a copy, I use copy constructor from Module class. This class s quite straightforward. I’m sure you can easily understand what I write here.
ConditionEvaluator and ParameterModifier
Since both of them are just interfaces, these classes will look like this
ConditionEvaluator will take the ModuleString and the index of Module that will be checked. It should return true if the condition fulfilled and vice versa. As for ParameterModifier, it will take both predecessor and successor string because we usually get the values of modified parameter from the predecessor string’s parameters. The implementation of those two interfaces is depend on the l-system. For example, if we only want to create a simple l-system(I mean the one that I used to explain l-system on the previous article), we won’t need any condition to be evaluated or any parameters to be modified.
This class is the most complex in this l-system implementation. It has to store the predecessor and successor string in the rule. It also has to store left and right context on the predecessor string. They are the string that placed on the left and the right side of the predecessor string. Before the rule is applied to the string, it has to check if the left and right context of the checked character match the rule’s left and right context. This class also has to store the implementation of ConditionEvaluator and ParameterModifier that apply to this rule. This is the code
You can see the code, if we don’t need ConditionEvaluator and ParameterModifier, the default will be assigned. On the applyAtIndex() method, first we have to check if the character at the specified index match the rule’s predecessor string. If it match, then check the left and right context and also the condition. After we make sure all the required condition fulfilled, we can start to replace the string with the successor string. After the replacement occur, we can apply the parameter modifier to the string.
This class is the one that manage all the production rules we have on our l-system. It stores the list of the production rules. Its task is very simple, to apply each production rule to every character on the string.
Basically, after we define the production rules on our application, we only need to call apply() method on this class to rewrite entire string to the new string.
Now let’s create a test. We will write a simple implementation of the codes we have written. I will use the simple l-system on the previous article. The notation of that l-system is:
p1: a → ab
p2: b → a
The l-system above should produce the strings below after 5 iteration
Here is the code:
If you do it correctly, you should get the same result as listed above.