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 (adsbygoogle = window.adsbygoogle || []).push({}); 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\$ (adsbygoogle = window.adsbygoogle || []).push({}); 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 All questions (adsbygoogle = window.adsbygoogle || []).push({}); News 13/08/2022 W4 Games called for DirectX12 support in the new version of the Godot game engine 13/08/2022 SK Hynix wants to build a chip testing and packaging plant in the US 13/08/2022 The developer showed that DDR5 memory diagnostics in the not yet presented version of MemTest86 was taken to a new level Wiki __del__ Python OpenCV | cv2.putText () method __del__ numpy.arctan2 () in Python __del__ Python | os.path.realpath () method around Python OpenCV | cv2.circle () method cvtcolor Python OpenCV cv2.cvtColor () method Python functions Python - Move item to the end of the list Counters time.perf_counter () function in Python __dict__ Check if one list is a subset of another in Python __del__ Python os.path.join () method © 2017—2022 Python Engineering Hub EN | ES | DE | FR | IT | RU | TR | PL | PT | JP | KR | CN | HI | NL Python.Engineering is a participant in the Amazon Services LLC Associates Program, an affiliate advertising program designed to provide a means for sites to earn advertising fees by advertising and linking to amazon.com Python Loops Counters NumPy NLP Regular Expressions Wiki Tech news Python Wiki StackOverflow PHP JavaScript Books All books Computations Development Cryptography For dummies Big Data document.addEventListener("DOMContentLoaded", () => { let arrayCode = document.querySelectorAll('pre'); arrayCode.forEach(element => { element.classList.add("prettyprint"); }); }); window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-Q022WLXW4X'); ```