Change language

Fractal using Spirograph in Python

|

A spirograph is a geometric-patterned toy that creates the mathematical curves of a tape measure of a variety technically known as hypotrochoids and epitrochoids. It was developed by British engineer Denis Fisher and first sold in 1965.
The name is a registered trademark of Hasbro Inc. since 1998 after the purchase of the company that acquired Denys Fisher. The Spirograph brand was renewed worldwide with the original product configuration in 2013 by Kahootz Toys.

The Spirograph can be used to draw various fractals. Some of them are below

You can visit benice-equation-blogspot.in for more detailed designing fractals using a parametric equation. Some of them are given below

Math behind the curtain

These are two parametric equations for forming a spirograph fractal, to understand these equations, you must consider the generalized spirograph figure.

For the math part, you can refer to the Wiki, although I’ll try to explain a little of this math in a nutshell here. If we are interested in math you can check the links. Thus, at the moment, these different curves can be drawn using a parametric equation and by varying some values ​​of this equation, we can get different fractals. So here’s the parametric equation:

where,

R is a scaling parameter and does not affect the structure of the spirograph.

and,

So now let’s try to implement this in code.

# import required libraries

import random, argparse

import math

import turtle

from PIL import Image

from datetime import datetime 

from fractions import gcd

 
# The class that draws the spirograph

class Spiro:

# constructor

def __ init __ ( self , xc, yc, col, R, r, l):

 

# create your own turtle

self . t = turtle.Turtle ()

# set cursor shape

self . t.shape ( ’turtle’ )

# set step in degrees

self . step = 5

  # install drawing completion flag

self . drawingComplete = False

  

# set options

self . setparams (xc, yc, col, R, r, l)

 

# initialize picture

self . restart ()

 

# set parameters

  def setparams ( self , xc, yc, col, R, r, l):

# spirograph parameters

self . xc = xc

self . yc = yc

self . R = int (R)

self . r = int (r)

self . l = l

self . col = col

  # reduce R / R to smallest form by dividing with GCD

gcdVal = gcd ( self . r, self . R)

self . nRot = self . r / / gcdVal

# get radius ratio

self . k = r / float (R)

# set color

self . t.color ( * col)

# current corner

self . a = 0

 

# restart picture

def restart ( self ):

# set the flag

self . drawingComplete = False

# show turtle

self . t.showturtle ()

  # go to the first point

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 ()

 

# draw it all

  def draw ( self ):

  # Draw the rest of the dots

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)

  # done - hide the turtle

  self . t.hideturtle ()

 

# one step update

  def update ( self ) :

# skip if done

if self . drawingComplete:

return

# increment angle

self . a + = self . step

# drawing step

R, k, l = self . R, self . k, self . l

  # install ugo 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)

# check if is drawing finished and set the flag

if self . a" = 360 * self . nRot:

self . drawingComplete = True

# done - hide the turtle

self . t.hideturtle ()

 

# clear all

def clear ( self ):

self . t .clear ()

 
# Class for animating spirographs

class SpiroAnimator:

# constructor

def __ init __ ( self , N):

# timer value in milliseconds

self . deltaT = 10

# get window dimensions

self . width = turtle.window_width ()

self . height = turtle.window_height ()

# create spiro objects

self . spiros = []

for i in range (N):

# generate random parameters

  rparams = self . genRandomParams ()

# set spiro options

spiro = Spiro ( * rparams)

self . spiros.append (spiro)

# call timer

turtle.ontimer ( self . update, self . deltaT)

 

  # restart drawing sprio

  def restart ( self ):

for spiro i n self . spiros:

# Clear

spiro.clear ()

# generate random parameters

rparams = self . genRandomParams ()

# set spiro parameters

spiro.setparams ( * rparams)

# restart picture

spiro.restart ()

 

# generate random parameters

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

# update all spiros

nComplete = 0

for spiro in self . spiros:

# Update

spiro.update ()

Number of completed

  if spiro.drawingComplete:

  nComplete + = 1

l = random.uniform ( 0.1 , 0.9 )

xc = random.randint ( - width / / 2 , width / / 2

Shop

Learn programming in R: courses

$

Best Python online courses for 2022

$

Best laptop for Fortnite

$

Best laptop for Excel

$

Best laptop for Solidworks

$

Best laptop for Roblox

$

Best computer for crypto mining

$

Best laptop for Sims 4

$

Latest questions

NUMPYNUMPY

psycopg2: insert multiple rows with one query

12 answers

NUMPYNUMPY

How to convert Nonetype to int or string?

12 answers

NUMPYNUMPY

How to specify multiple return types using type-hints

12 answers

NUMPYNUMPY

Javascript Error: IPython is not defined in JupyterLab

12 answers


Wiki

Python OpenCV | cv2.putText () method

numpy.arctan2 () in Python

Python | os.path.realpath () method

Python OpenCV | cv2.circle () method

Python OpenCV cv2.cvtColor () method

Python - Move item to the end of the list

time.perf_counter () function in Python

Check if one list is a subset of another in Python

Python os.path.join () method