O Lindenmayer Systems é uma ferramenta de uso de recursão, seguindo uma regra predefinida e o uso de orientação a objetos para a reprodução de diversos tipos de fractais, plantas e outras figuras geométricas que seguem alguma regra de reprodução.
A reprodução dessas imagens segue a regra de reprodução das figura 5.11 (p. 129) do livro The Algorithmic Beauty of Plants.
Os parâmetros que definem o atraso dos movimentos dos ramos laterais e a taxa de alongamento entre os nós da figura a e os parâmetros utilizados na construção da figura 8.8, incluindo o número de derivações, encontra-se na tabela abaixo.
O interessante em se observar, o que é muito comum em sistemas que utilizam o L System, é que cada "folha" da árvore é uma reprodução da arvore como um todo. O processo se encerra se não houver derivações ou se todas as derivações forem realizadas.


O código usado para a replicação é o seguinte:
import turtle
from collections import deque
turtle.setup(360,576)
turtle.delay(0) # para aumentar a velocidade da turtle
turtle.delay(0)
class L_system(object):
def __init__(self, turtle, size = 0.5, D = 0, n = 10, R = 2, ang = 45):
"parãmetros definidos na página 129 do livro the Algorithmic Beauty of Plants"
self.t = turtle
self.size = size
self.D = D
self.n = n
self.R = R
self.ang = ang
self.commands(self.t)
self.state = deque()
return None
def commands(self, t):
t.speed(0)
t.penup()
t.setheading(90)
t.setposition(0, -200)
t.pendown()
t.width(1.5)
return None
def ultimoponto(self, t):
self.state.append([t.position(), t.heading()])
return None
def voltarponto(self, t):
t.penup()
previous_checkpoint = self.state.pop()
t.setposition(previous_checkpoint[0])
t.setheading(previous_checkpoint[1])
t.pendown()
return None
class Ex88a(L_system):
def axiom(self):
""" Axiom: A(0)"""
t = self.t
n = self.n
if n == 0: # segue em frente em caso de ser a última geração
t.forward(self.size)
else:
self.regraA(t, d = 0, n = n - 1)
return None
def regraA(self, t, d, n):
""" Regra: A(d) : d > 0 -> A(d-1)
A(d) : d = 0 -> F(1) [+A(D)][-A(D)] F(1) A(0)
"""
if n == 0:
t.forward(self.size) # segue em frente em caso de ser a última geração
return None
elif d > 0:
self.regraA(t, d - 1, n - 1) # delay
return None
else:
self.regraF(t, n = n - 1, a = 1) # F(1) -> multiplica o valor a por um parâmetro pré-estabelecido
# [+A(D)] -> salva o ponto, gira à esquerda, desloca-se o parâmetro e retorna ao último ponto
self.ultimoponto(t)
t.left(self.ang)
self.regraA(t, d = self.D, n = n - 1)
self.voltarponto(t)
# [-A(D)] -> salva o ponto, gira à direita, desloca-se o parâmetro e retorna ao último ponto
self.ultimoponto(t)
t.left(-self.ang)
self.regraA(t, d = self.D, n = n - 1)
self.voltarponto(t)
# F(1) A(0) -> multiplica o valor a por um parâmetro pré-estabelecido e em caso de última geração, segue em frente
self.regraF(t, n = n - 1, a = 1)
self.regraA(t, d = 0, n = n - 1)
return None
def regraF(self, t, n, a):
""" Regra: F(a): * -> F(a * R)
"""
if n == 0:
t.forward(self.size * a)
else:
self.regraF(t, n = n - 1, a = a * self.R)
return None
if __name__ == '__main__':
try:
my_turtle = turtle.Turtle()
except:
my_turtle = turtle.Turtle()
wn = turtle.Screen()
# Draws the leaves
my_leaves = Ex88a(my_turtle, size = 0.5, n = 10, ang = 45, D = 0)
my_leaves.axiom()
O resultado final é:

Percebe-se que é possível replicar as figuras b, c, d, e abaixo alterando os parâmetros da tabela apresentada anteriormente.
