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

Como replicar modelos de inflorescências usando Lindenmayer Systems (L-Systems)?

+1 voto
61 visitas
perguntada Ago 24 em Ciência da Computação por Renata Oliveira (46 pontos)  

Figura 3.13(a) do livro "The Algorithmic Beauty of Plants" de Przemyslaw Prusinkiewicz e Aristid Lindenmayer (1991).

A imagem será apresentada aqui.

Compartilhe

1 Resposta

+1 voto
respondida Ago 24 por Renata Oliveira (46 pontos)  

Para replicar a figura da pergunta, foi utilizado o pacote turtle. Duas funções foram criadas, a primeira para desenhar o eixo principal (axis) e a segunda para as inflorescências em forma de espiral para a direita (spiral_right). Ambas as funções utilizam a recursão para desenhar a imagem. Na primeira função, é possível escolher o número de segmentos do eixo principal, o comprimento dos segmentos, e o tamanho das folhas, que são arcos de circunferências (portanto a escolha é do raio e da extensão do arco). As folhas aparecem alternadamente, à direita e à esquerda. Para replicar este padrão, se o número do segmento a ser desenhado for par, a folha é desenhada à esquerda, caso contrário a folha é desenhada à direita.

A segunda função desenha as inflorescências em formato de espiral. Da mesma forma, escolhe-se o número de segmentos e seu comprimento, o tamanho das pequenas folhas, o ângulo que será alterado para criar a espiral e o incremento deste ângulo a cada segmento. O formato em espiral é reproduzido reduzindo, a cada segmento, o ângulo que indica a direção em que a imagem será desenhada, ou seja, a cada segmento o cursor se vira um pouco mais à direita. Para uma espiral mais "fechada", basta aumentar o parâmetro increment da função.

from turtle import *

def axis(n, x, r, s):
    '''
    Draws the main axis
    n = number of segments
    x = length of each segment
    r = radius of the leaf
    s = size of the leaf
    '''
    forward(x/2)
    circle(-r,s) #draws an arc in clockwise direction
    circle(-r,-s) #goes back to the axis
    forward(x/2)
    if n==0:
        forward(x)  
    elif n>0:
        if n%2==0: #alternates the side of the leaves
            axis(n-1, x, -r, s)
        else: 
            axis(n-2, x, -r, s)
    else:
        return


def spiral_right(n, x, r, s, angle, increment):
    '''
    Draws the spiral figure to the right
    n = number of segments 
    x = length of segments
    r = radius of small leaf
    s = size of small leaf
    increment = higher value means a more closed spiral.
    To create the spiral, the direction the turtle faces must be changed in each segment
    '''

    seth(30 - angle) #turtle faces northeast
    circle(-r, s) #draws tiny leaf
    circle(-r,-s) #back to the axis
    seth(90-angle) #turtle faces north/northeast
    forward(x) #draws the stem that holds the inflorescence
    seth(0-angle)
    fillcolor('black') #draws the inflorescence
    begin_fill()
    circle(8)
    end_fill()
    seth(90-angle)
    backward(x) #back to the axis
    seth(50-angle) #turtle faces northeast
    forward(x) #segment of the axis
    if n==0:
        forward(x)
    if n>0:
        spiral_right(n-1, x, r, s, angle+increment, increment)
    else:
        return

Para desenhar a imagem, as duas funções são chamadas em sequência. Os parâmetros foram escolhidos de modo a replicar a figura do livro.

if __name__ == '__main__':
    begin_fill()
    screensize(200,1500)
    penup()    
    goto(0,0)  
    pendown()  
    left(90) #turtle faces north
    axis(17, 30, 30, 80)
    spiral_right(7, 25, 20, 50, 0, 25)
    done()

O resultado obtido foi a imagem abaixo
A imagem será apresentada aqui.

comentou Set 3 por Rodrigo Stuckert (46 pontos)  
Ola, Renata. Tudo bem? Achei muito boa sua solução, você resolveu o problema por recursão, como sugerido, e foi direto ao ponto nas explicações. A única sugestão que tenho a fazer é que talvez seja interessante descrever brevemente alguns comandos, como "penup" e "pendown", no último pedaço de código. Forte abraço!
comentou Set 13 por Renata Oliveira (46 pontos)  
Obrigada pela dica! De fato acabei não mencionando os comandos penup e pendown. Eles fazem parte da biblioteca turtle do python e determinam se as linhas estarão ou não sendo desenhadas enquanto o turtle se move. No código da resposta, o objetivo é que não seja desenhada uma linha enquanto o turtle vai até o ponto (0,0). Depois disso, a figura passa a ser desenhada enquanto o turtle está se movendo.
...