Introdução

Brinquedo espirógrafo que é usado para produzir padrões complexos usando engrenagens de plástico e canetas coloridas. Um fractal é uma curva que se desenvolve usando um padrão recorrente que se repete infinitamente em uma escala baixa. Fractais são usados ​​para modelar estruturas (como flocos de neve) ou para descrever fenômenos parcialmente caóticos.
O espirógrafo pode ser usado para desenhar vários fractais. Alguns deles são dados abaixo

Você pode visitar benice-equation-blogspot.in para mais projetos de fractais com sua equação paramétrica. Alguns deles são dados abaixo

Matemática atrás da cortina

Estas são as duas equações paramétricas para formar os fractais do espirógrafo; para entender essas equações, você deve considerar uma figura generalizada do espirógrafo.



Espirógrafo-Diagrama

Para a parte da matemática, você pode consultar o Wiki, embora eu tente explicar um pouco dessa matemática em um breve resumo aqui. Se estivermos interessados ​​em matemática, você pode verificar os links mencionados. Portanto, a partir de agora, essas várias curvas podem ser desenhadas usando uma equação paramétrica e, variando alguns valores dessa equação, podemos obter diferentes fractais. Então aqui está a equação paramétrica:

  x (t) = R [(1-k) custo + lkcos (((1-k) / k) t)], y (t) = R [(1-k) sint - lksin (((1-k) ) / k) t).

Onde,

   k = r / R

R é um parâmetro de escala e não afeta a estrutura do espirógrafo.

e,

   l = p / r



Então, agora vamos tentar implementar isso no código.

import random, argparse 
import math 
import turtle 
from PIL import Image 
from datetime import datetime     
from fractions import gcd 
class Spiro: 
    
    def __init__(self, xc, yc, col, R, r, l): 
        self.t = turtle.Turtle() 
      self.t.shape('turtle') 
      self.step = 5
      self.drawingComplete = False
        self.setparams(xc, yc, col, R, r, l) 
        self.restart() 
  
    
    def setparams(self, xc, yc, col, R, r, l): 
      self.xc = xc 
        self.yc = yc 
        self.R = int(R) 
        self.r = int(r) 
        self.l = l 
        self.col = col 
      gcdVal = gcd(self.r, self.R) 
        self.nRot = self.r//gcdVal 
      self.k = r/float(R) 
      self.t.color(*col) 
      self.a = 0
  
    
    def restart(self): 
      self.drawingComplete = False
      self.t.showturtle() 
      self.t.up() 
        R, k, l = self.R, self.k, self.l 
        a = 0.0
        x = R*((1-k)*math.cos(a) + l*k*math.cos((1-k)*a/k)) 
        y = R*((1-k)*math.sin(a) - l*k*math.sin((1-k)*a/k)) 
        self.t.setpos(self.xc + x, self.yc + y) 
        self.t.down() 
  
    
    def draw(self): 
      R, k, l = self.R, self.k, self.l 
        for i in range(0, 360*self.nRot + 1, self.step): 
            a = math.radians(i) 
            x = R*((1-k)*math.cos(a) + l*k*math.cos((1-k)*a/k)) 
            y = R*((1-k)*math.sin(a) - l*k*math.sin((1-k)*a/k)) 
            self.t.setpos(self.xc + x, self.yc + y) 
      self.t.hideturtle() 
      
    
    def update(self): 
      if self.drawingComplete: 
            return
      self.a += self.step 
      R, k, l = self.R, self.k, self.l 
      a = math.radians(self.a) 
        x = self.R*((1-k)*math.cos(a) + l*k*math.cos((1-k)*a/k)) 
        y = self.R*((1-k)*math.sin(a) - l*k*math.sin((1-k)*a/k)) 
        self.t.setpos(self.xc + x, self.yc + y) 
      if self.a >= 360*self.nRot: 
            self.drawingComplete = True
              self.t.hideturtle() 
  
    
    def clear(self): 
        self.t.clear() 
class SpiroAnimator: 
    
    def __init__(self, N): 
      self.deltaT = 10
      self.width = turtle.window_width() 
        self.height = turtle.window_height() 
      self.spiros = [] 
        for i in range(N): 
              rparams = self.genRandomParams() 
              spiro = Spiro(*rparams) 
            self.spiros.append(spiro) 
      turtle.ontimer(self.update, self.deltaT) 
      
    
    def restart(self): 
        for spiro in self.spiros: 
              spiro.clear() 
              rparams = self.genRandomParams() 
              spiro.setparams(*rparams) 
              spiro.restart() 
  
    
    def genRandomParams(self): 
        width, height = self.width, self.height 
        R = random.randint(50, min(width, height)//2) 
        r = random.randint(10, 9*R//10) 
        l = random.uniform(0.1, 0.9) 
        xc = random.randint(-width//2, width//2) 
        yc = random.randint(-height//2, height//2) 
        col = (random.random(), 
               random.random(), 
               random.random()) 
        return (xc, yc, col, R, r, l) 
  
    def update(self): 
      nComplete = 0
        for spiro in self.spiros: 
              spiro.update() 
              if spiro.drawingComplete: 
                nComplete+= 1
      if nComplete == len(self.spiros): 
            self.restart() 
      turtle.ontimer(self.update, self.deltaT) 
  
    
    def toggleTurtles(self): 
        for spiro in self.spiros: 
            if spiro.t.isvisible(): 
                spiro.t.hideturtle() 
            else: 
                spiro.t.showturtle() 
              
def saveDrawing(): 
    
    turtle.hideturtle() 
    
    dateStr = (datetime.now()).strftime("%d%b%Y-%H%M%S") 
    fileName = 'spiro-' + dateStr  
    print('saving drawing to %s.eps/png' % fileName) 
    
    canvas = turtle.getcanvas() 
    
    canvas.postscript(file = fileName + '.eps') 
    
    img = Image.open(fileName + '.eps') 
    img.save(fileName + '.png', 'png') 
    
    turtle.showturtle() 
def main(): 
    
    print('generating spirograph...') 
    
    descStr =
    
      
    
  
    
    
    
    
    parser = argparse.ArgumentParser(description=descStr) 
    
    
    parser.add_argument('--sparams', nargs=3, dest='sparams', required=False
                        help="The three arguments in sparams: R, r, l.") 
                          
  
    
    args = parser.parse_args() 
  
    
    turtle.setup(width=0.8) 
  
    
    turtle.shape('turtle') 
  
    
    turtle.title("Spirographs!") 
    
    turtle.onkey(saveDrawing, "s") 
    
    turtle.listen() 
  
    
    turtle.hideturtle() 
  
    
    if args.sparams: 
        params = [float(x) for x in args.sparams] 
      
        col = (0.0, 0.0, 0.0) 
        spiro = Spiro(0, 0, col, *params) 
        spiro.draw() 
    else: 
      spiroAnim = SpiroAnimator(4) 
      turtle.onkey(spiroAnim.toggleTurtles, "t") 
      turtle.onkey(spiroAnim.restart, "space") 
  
    
    turtle.mainloop() 
if __name__ == '__main__': 
    main() 

Resultado:


O programa acima desenha 4 tipos diferentes de fractais espirográficos, tente gerar outros fractais e, em seguida, carregue seus links do github no comentário. Terei todo o gosto em ajudá-lo se ocorrer algum erro.

Este artigo é uma contribuição de Subhajit Saha . Se você gosta de GeeksforGeeks e gostaria de contribuir, você também pode escrever um artigo usando contribute.geeksforgeeks.org ou enviar o seu artigo para contribute@geeksforgeeks.org. Veja o seu artigo que aparece na página principal do GeeksforGeeks e ajude outros Geeks.

Escreva comentários se encontrar algo incorreto ou se quiser compartilhar mais informações sobre o tópico discutido acima.

geeks-digest-img