## L-Systems

Lindenmayer or L-systems provide a very simple way of coding/drawing complex structures. For those who may be interested the team thought we should demonstrate this simplicity by showing the code used in the patterns available in pzl_jigsaw.

### Contents

As implemented for the simple patterns used in pzl_jigsaw we have a few commands defined in the dictionary self.commands and a loop to expand the productions for the given number of iterations.

```
class Lindenmayer(object):
"""
Lindenmayer or L-Systems
We've just implemented a few simple examples using a limited
set of commands.
"""
def __init__(self, axiom, productions, iterations):
self.commands = {
'Draw': set(['F','G','1']),
'Move': 'f',
'Turn left': '+',
'Turn right': '-',
'Push': '[',
'Pop': ']'}

current = axiom
next_bit = ""

for i in range(iterations):
for symbol in range(len(current)):
found_it = False
for letter, production in productions.iteritems():
if (current[symbol] == letter):
next_bit = next_bit + production
found_it = True
break
next_bit = next_bit + current[symbol]
current = next_bit
next_bit = ""

self.l_system = current

```

We have a little animal that can follow simple commands and leave behind its trail which will constitute the displayed drawing. With their customary modesty and wit the team have named this class "Hare".

```
class Hare(object):
"""
Turtle graphics!
current position is position
current direction is angle
current increment is step
angle increment is delta_angle
"""
def __init__(self, commands, step, delta):
self.commands = commands
self.stack = []
self.delta_angle = delta
self.position = complex(0, 0j)
self.angle = 270.0
self.step = complex(math.cos(self.angle),
math.sin(self.angle))
self.path = []
self.x_min = self.position.real
self.x_max = self.position.real
self.y_min = self.position.imag
self.y_max = self.position.imag

def get_path(self, l_system):
self.stack = []
segment = []
self.path = []
for command in l_system:
if command in self.commands['Draw']:
segment.append(self.position)
self.position += self.step
segment.append(self.position)
self.path.append(segment)
segment = []
elif command == self.commands['Move']:
self.position += self.step
elif command == self.commands['Turn left']:
self.angle += self.delta_angle
self.step = complex(math.cos(self.angle),
math.sin(self.angle))
elif command == self.commands['Turn right']:
self.angle -= self.delta_angle
self.step = complex(math.cos(self.angle),
math.sin(self.angle))
elif command == self.commands['Push']:
item = (self.position, self.angle)
self.stack.append(item)
elif command == self.commands['Pop']:
item = self.stack.pop()
self.position = item
self.angle = item
self.step = complex(math.cos(self.angle),
math.sin(self.angle))
else:
# unrecognised symbol so do nothing
pass

# get range

for segment in self.path:
self.x_min = int(min(self.x_min, segment.real, segment.real))
self.x_max = int(max(self.x_max, segment.real, segment.real))
self.y_min = int(min(self.y_min, segment.imag, segment.imag))
self.y_max = int(max(self.y_max, segment.imag, segment.imag))
```

And finally the actual axioms and productions which, when processed as above, create the patterns seen on the screen. Where they have been taken from The Algorithmic Beauty of Plants the page numbers are shown.

```
def start_game_l(self, name):
"""
Define the codes for various l-systems.
Mostly taken from Prusinkiewicz and Lindenmayer (page nos)
"""

iterations = None
if name == 'Koch a':
#p10 a
iterations = 4
delta = 90
axiom = "F-F-F-F"
productions = {'F': 'FF-F-F-F-F-F+F'}
side_ratio = 1.0
elif name == 'Koch b':
#p10 b
delta = 90
iterations = 4
axiom = "F-F-F-F"
productions = {'F': 'FF-F-F-F-FF'}
side_ratio = 1.0
elif name == 'Koch c':
#p10 c
delta = 90
iterations = 3
axiom = "F-F-F-F"
productions = {'F': 'FF-F+F-F-FF'}
side_ratio = 1.0
elif name == 'Koch d':
#p10 d
delta = 90
iterations = 4
axiom = "F-F-F-F"
productions = {'F': 'FF-F--F-F'}
side_ratio = 1.0
elif name == 'Koch e':
#p10 e
delta = 90
iterations = 5
axiom = "F-F-F-F"
productions = {'F': 'F-FF--F-F'}
side_ratio = 1.0
elif name == 'Koch f':
#p10 f
delta = 90
iterations = 4
axiom = "F-F-F-F"
productions = {'F': 'F-F+F-F-F'}
side_ratio = 1.0
elif name == 'Islands and Lakes':
#p9, 1.8
iterations = 2
delta = 90
axiom = "F+F+F+F"
productions = {'F': 'F+f-FF+F+FF+Ff+FF-f+FF-F-FF-Ff-FFF',
'f': 'ffffff'}
side_ratio = 1.0
elif name == 'Quadratic Koch island':
#p9 a
iterations = 2
delta = 90
axiom = 'F-F-F-F'
productions = {'F' : 'F+FF-FF-F-F+F+FF-F-F+F+FF+FF-F'}
side_ratio = 1.0
#p9, 1.7b
iterations = 4
delta = 90
axiom = "-F"
productions = {'F': 'F+F-F-F+F'}
side_ratio = 1.0
elif name == 'Dragon':
#p11 a
iterations = 10
delta = 90
axiom = "F"
productions = {'F': 'F+G+', 'G' : '-F-G'}
side_ratio = 1.0
#p11 b
iterations = 8
delta = 60
axiom = "G"
productions = {'F': 'G+F+G', 'G' : 'F-G-F'}

side_ratio = 1.0
elif name == 'Plant 1':
#p25 a
iterations = 5
delta = 27.7
axiom = 'F'
productions = {'F': 'F[+F]F[-F]F'}
side_ratio = 0.4
elif name == 'Plant 2':
#p25 b
iterations = 5
delta = 20
axiom = 'F'
productions = {'F': 'F[+F]F[-F][F]'}
side_ratio = 0.6
elif name == 'Plant 3':
#p25 c
iterations = 4
delta = 22.5
axiom = 'F'
productions = {'F': 'FF-[-F+F+F]+[+F-F-F]'}
side_ratio = 0.7
elif name == 'Plant 4':
#p25 d
iterations = 6
delta = 20
axiom = 'X'
productions = {'X': 'F[+X]F[-X]+X',
'F': 'FF'}
side_ratio = 0.7
elif name == 'Plant 5':
#p25 e
iterations = 7
delta = 25.7
axiom = 'X'
productions = {'X': 'F[+X][-X]FX', 'F': 'FF'}
side_ratio = 0.5
elif name == 'Plant 6':
#p25 f
iterations = 5
delta = 22.5
axiom = 'X'
productions = {'X': 'F-[[X]+X]+F[+FX]-X',
'F': 'FF'}
side_ratio = 0.7

elif name == 'Sierpinski carpet':
iterations = 4
delta = 90.0
axiom = 'F'
productions = {'F': 'F+F-F-F-f+F+F+F-F',
'f': 'fff'}
side_ratio = 1.0

elif name == 'Penrose':
iterations = 5
delta = 36.0
axiom = '++++++++'
productions = {'6': '81++91----71[-81----61]++',
'7': '+81--91[---61--71]+',
'8': '-61++71[+++81++91]-',
'9': '--81++++61[+91++++71]--71',
'1': ''}
side_ratio = 1.0

if iterations != None:
self.do_l_systems(iterations, delta, axiom, productions, side_ratio)

```

## Examples

Below we show videos of various examples of L-Systems patterns being generated by jigsaw.

## Plant 1

A video from jigsaw showing the generation of an L-System plant 1 using the "Type" style.

## Plant 2

A video from jigsaw showing the generation of an L-System plant 2 using the "Type" style.

## Plant 3

A video from jigsaw showing the generation of an L-System plant 3 using the "Type" style.

## Koch_a

A video from jigsaw showing the generation of an L-System Koch a using the "Type" style.

## Koch_b

A video from jigsaw showing the generation of an L-System Koch b using the "Type" style.

## Islands

A video from jigsaw showing the generation of an L-System Islands and Lakes using the "Type" style.

## Penrose

A video from jigsaw showing the generation of an L-System Penrose using the "Random" style.

# L_Systems

• Double-click any word to get its definition

## Last update

• 2022-04-10 