Lindenmayer Systems using Python

Last Update: 21.12.2007. By Kerim in natural | python | Algorithms

A few days ago i posted some code to create screens with stars and galaxies. Today i introduce a new part usable for creating Lindenmayer Systems.

Here the rendering of a penrose tiling using my module:

Just a short introduction:

A Lindenmayer System is a “grammar” that is defined by

  1. a certain vocabulary consisting mostly of single characters (like ‘F’, ‘f’ etc)
  2. a mapping of characters to actions (eg. “F” = draw forward, “-” = turn left, “+” = turn right)
  3. a substitution rule for these characters
  4. a starting axiom

What happens is that you will apply the substitution rules for a certain number of iterations on the axiom and the results of that axiom.

Here is a simple example

Got interested ? See this link for more information about what that a Lindenmayer System is en detail and what you can do with it.

Code

I only quote the method that does the trick here. rendering is done via the turtle module.

def iterate(self,axiom=None, rules=None, repetitions=1):
    if axiom==None or rules==None:
      return
    for repeat in range(0,repetitions):
      newpath=""
      i=0
      while i<len(axiom):
        found=False
        for old,new in rules:
          if old==axiom[i:i+len(old)]:
            newpath+=new
            i+=len(old)
            found=True
            continue          
        if not found:
          newpath+=axiom[i:i+1]
          i+=1
      axiom=newpath

return axiom

A first version of the code can be downloaded here. It also includes the starfieldcode mentioned here. Please be advised that it all is still messed up a bit (as usual). If you have an idea for the for loop, tell me ;)

Honorable mention goes to the python-forum where i found that wonderful piece of code that finally showed me some cool reason to use lambdas. Calling methods in a dictionary … fantastic:

methodToCall = {'F':lambda:self.drawForward(length),
                'A':lambda:self.drawForward(length),
                'B':lambda:self.drawForward(length),
                'f':lambda:self.nonDrawForward(length),
                '-':lambda:self.turn(angle,False),
                '+':lambda:self.turn(angle),
                '|':lambda:self.turn(180),
                '[':lambda:stack.append(self.getState()),
                ']':lambda:self.setState(stack.pop())
                }
for char in path:
  try:
    methodToCall[char]()
  except:
    pass

If you want to play around see lsystemtest.py. There are several LSystems usable here (look for the set…functions). In the init-function directly after initializing the LSystem one is called. Simply replace the called function with a different one.

I would welcome any new rules and renderings you create. Just mail (rules + picture) them to kmansourADDwebDOTde.

I have set up some gallery where you will find all images i create myself or get from you.

I also would like to hear new ideas (variable angles, or drawing length, colors) etc.