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

Como gerar as figuras 4.7 e 4.8 do livro Generative Art: A Practical Guide Using Processing, de Matt Pearson?

+1 voto
58 visitas
perguntada Jun 1 em Ciência da Computação por Daniel Castro (46 pontos)  
editado Jun 1 por Daniel Castro

As figuras 4.7 e 4.8 são apresentadas abaixo:

A imagem será apresentada aqui.

Compartilhe
comentou Jun 1 por danielcajueiro (5,666 pontos)  
Ola Daniel! Você colocou a pergunta e a resposta junto.
comentou Jun 1 por danielcajueiro (5,666 pontos)  
Use o botão de inclusão de link para incluir o link, pois em caso contrário ele nao funciona.

2 Respostas

+2 votos
respondida Jun 1 por Daniel Castro (46 pontos)  

A listagem 4.5 do livro apresenta o código na linguagem Processing que gerou as figuras:

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

O código basicamente desenha, grau a grau, um ponto a uma distância do centro do círculo dada por um valor fixo (no caso 100), mais um ruído multiplicado por 30. Ou seja, para determinado ângulo, o raio a desenhar pode ser 100, para o grau 1 pode ser 102, para o grau 3 pode ser 130 e assim por diante. Na figura 4.7, o ruído é o cubo do seno de um valor aleatório entre 0 e 10 acrescido de 0.1 a cada grau e a figura desenhada é, portanto, um senóide regular. Já na figura 4.8 o ruído é o seno elevado ao resto da divisão inteira por 12 de um valor aleatório entre 0 e 10 acrescido de 0.1 a cada grau. Assim, a figura não é regular.

Implementação em Python

Em Python, um módulo simples para geração de imagens é o módulo turtle. Usado também para ensino de programação para crianças, simula uma tartaruga se movendo pela tela em função dos comandos escolhidos. O módulo é simples, didático e ainda assim completo.

No código que gera as figuras, em primeiro lugar define-se a função ruido(valor), responsável por gerar o ruido. Para gerar a figura 4.7, o ruído é regular (o cubo do seno), como mencionado anteriormente e para gerar a figura 4.8 ele é irregular (seno elevado a valores variáveis).

def ruido(valor, regular):
"""Retorna o ruído com base no valor recebido com parâmetro
Se o ruído é regular, o valor do ruído é o seno ao cubo.
Se o ruído não é regular, o valor do ruído é o seno elevado ao resto 
da divisão inteira por 12 do valor recebido como parâmetro
"""
if regular:
    return math.pow(math.sin(valor), 3)
else:
    count = int((valor % 12))
    return math.pow(math.sin(valor), count)

Para o desenho propriamente dito, defini duas funções para deixar o código um pouco mais modular, sendo a primeira responsável por traçar o ruído, chamando a função ruido definida anteriormente:

def desenha_ruido(raio_regular, regular):
"""Desenha o ruído ao redor do círculo"""
turtle.pensize(1) # grossura do traço
turtle.begin_fill() # figura será colorida no final

val_ruido = random.randrange(10) # gera um número aleatório entre 0 e 10
for i in range(360):
    """Desenha o ruído ao redor do círculo com espaçamento de um grau"""
    val_ruido += 0.1
    raio_variavel = 30 * ruido(val_ruido, regular)
    raio = raio_regular + raio_variavel # a cada iteração é desenhada uma linha com tamanho tamanho do raio regular mais um valor variável
    rads = (i/180) * math.pi # converte de graus para radianos
    x = raio * math.cos(rads)
    y = raio * math.sin(rads)

    if (i == 0):
        turtle.penup() # não desenha a linha na primeira movimentação
        x_inicial = x # armazena a posição inicial para fechar a figura
        y_inicial = y
    else: 
        turtle.pendown()        

    turtle.setpos(x, y)
    turtle.dot(size = 2)

turtle.setpos(x_inicial, y_inicial) # fecha a figura
turtle.end_fill()

A segunda função desenha o círculo claro traçado com o raio regular:

def desenha_circulo(raio_regular):
"""Desenha o círculo interno da figura"""
turtle.penup() # para não desenhar a linha na primeira movimentação
turtle.setpos(0, -raio_regular) # a posição inicial do círculo é a parte mais baixa dele e não o centro
turtle.pendown()
turtle.pensize(3) # largura do círculo é maior que a largura do desenho que envolve o circulo
turtle.circle(raio_regular) # desenha um círculo de raio 100

O trecho principal chama as funções que desenham o ruído e o círculo regular, especificando com parâmetro se o ruído é regular ou não.

if __name__ == '__main__':
# https://ecsdtech.com/8-pages/121-python-turtle-colors
turtle.color("light gray", "dim gray") # primeira cor é da linha e segunda é do preenchimento
turtle.speed(10) # seta a velocidade máxima do turtle
turtle.home()

raio_regular = 100
regular = 0 # se 1, o ruido é regular e a figura 4.7 é desenhada; se 0, o ruído não é regular e a figura 4.8 é desenhada
desenha_ruido(raio_regular, regular)
desenha_circulo(raio_regular)

turtle.done()

As imagens geradas são as seguintes:

Figura da 4.7
A imagem será apresentada aqui.

Figura da 4.8
A imagem será apresentada aqui.

O código foi disponibilizado também no script aula1_7a.py de repositório no GitHub.

Evolução do programa poderia criar duas funções "ruido" e passá-las como mais um parâmetro da função desenha_ruido. Outra possibilidade seria permitir que o usuário digitasse como input a escolha entre ruído regular e irregular. Uma terceira possibilidade é criar subclasses de uma classe genérica que implementariam métodos ruídos específicos.

0 votos
respondida Jul 2 por Felipe Amaral (16 pontos)  

Achei muito interessante a sua implementação, Daniel! Nunca tinha utilizado a biblioteca Turtle. O que achei mais interessante é que o gráfico é gerado pouco a pouco permitindo visualizar o desenrolar do algoritmo.

Na primeira vez que rodei, usei o Jupyter Notebook instalado no servidor do Cocalc, mas não funcionou. Tive que rodar localmente no Spyder/Desktop para funcionar. Uma modificação no seu código que pode ajudar para rodar sem o Turtle é esta aqui, adaptada para rodar com o matplotlib e as funções fill e plot:

import matplotlib.pyplot as plt
def desenha_ruido2(raio_regular, regular):
    xx=list()
    yy=list()
    val_ruido = random.randrange(10) # gera um número aleatório entre 0 e 10
    for i in range(361):
        """Desenha o ruí­do ao redor do círculo com espalhamento de um grau"""
        val_ruido += 0.1
        raio_variavel = 30 * ruido(val_ruido, regular)
        raio = raio_regular + raio_variavel # a cada iteração desenha uma linha com tamanho tamanho do raio regular mais um valor variável
        rads = (i/180) * math.pi # converte de graus para radianos
        x = raio * math.cos(rads)
        y = raio * math.sin(rads)
        if i==0:
           x0=x
           y0=y
        xx.append(x)      
        yy.append(y)
        if i==360:
            xx.append(x0)      
            yy.append(y0)
    return xx,yy

def desenha_circulo2(raio_regular):
    """Desenha o círculo interno da figura"""
    xx=list()
    yy=list()
    val_ruido = 0 # Zera o valor do ruído na figura anterior
    for i in range(361):
        """Desenha o ruí­do ao redor do círculo com espalhamento de um grau"""
        val_ruido += 0.1
        raio_variavel = 0
        raio = raio_regular + raio_variavel # a cada iteração desenha uma linha com tamanho tamanho do raio regular mais um valor variável
        rads = (i/180) * math.pi # converte de graus para radianos
        x = raio * math.cos(rads)
        y = raio * math.sin(rads)
        if i==0:
           x0=x
           y0=y
        xx.append(x)      
        yy.append(y)
        if i==360:
            xx.append(x0)      
            yy.append(y0)

    return xx,yy

x1,y1=desenha_ruido2(raio_regular, regular)
x2,y2=desenha_circulo2(raio_regular)     
p1=plt.fill(x1,y1,facecolor='grey', edgecolor='black', linewidth=1) 
plt.axis('equal')
plt.plot(x2,y2,'-',color="lightgrey", linewidth=3)
plt.axis('equal')

O resultado final é este aqui:

A imagem será apresentada aqui.

...