Primeira vez aqui? Seja bem vindo e cheque o FAQ!
x

Como replicar a figura 8.8 do Livro The Algorithmic Beaty of Plants by P. Prusinkiewicz and A. Lindenmayer, p. 186

0 votos
40 visitas
perguntada Dez 16, 2020 em Ciência da Computação por Fernando Fellows (16 pontos)  

A imagem será apresentada aqui.

Compartilhe

1 Resposta

0 votos
respondida Dez 16, 2020 por Fernando Fellows (16 pontos)  
selecionada Dez 18, 2020 por Fernando Fellows
 
Melhor resposta

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.

A imagem será apresentada aqui.
A imagem será apresentada aqui.

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 é:

A imagem será apresentada aqui.

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

A imagem será apresentada aqui.

comentou Dez 19, 2020 por José Henriques Jr (1 ponto)  
Olá Fernando! Gostei bastante da sua resposta e principalmente por ter explicado de maneira bem objetiva o método Lindenmayer Systems. Com relação a exposição do código achei que poderia apresentá-lo em blocos, pois visualmente é mais fácil de identificar os passos. Rodei o seu código e ele funcionou perfeitamente. Tendo em vista que sua a abordagem é baseada em uma estrutura determinística para a identificação do ângulo das ramificações, chamo a atenção para a possibilidade de variações mais complexas com a introdução de números aleatórios, permitindo outras estruturas de ramificações.
...