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.


Want content like this in your inbox each workday irregularly? No BS, spam or tricks... just useful content:

I understand and agree to the privacy policy