I was reading a book on artificial intelligence and in the book it mentioned the Archimedes spiral. There was a drawing that was fairly interesting. So I decided to see if I could draw it on the screen using a Python script. After some reading on Wikipedia about different kinds of spirals, and some work, the result was the program below.
But first, some pictures of the results. The first one is a set of Lituus curves.
This next one is a set of logarithmic spirals.
And a final taste, an Archimedean spiral:
The code below allows you to vary the color of the lines, the number of spirals displayed and what type. The types include the ones shown above plus Fermat's spiral and hyperbolic spirals.
# Draws spirals on a canvas
from Tkinter import *
from math import *
from random import randint
from time import sleep
class App:
"""This class is derived, I think, from a TK class and is designed to
work with the TK environment.
Requires imports from Tkinter, math, random and time"""
def __init__(self, master):
"""This class is the whole of the application """
# Necessary Frames
frame = Frame(master)
control_frame = Frame(frame)
control_frame.grid(row = 0, column = 0, sticky = N)
canvas_frame = Frame(frame)
canvas_frame.grid(row =0, column = 1, rowspan=2)
status_frame = Frame(frame)
status_frame.grid(row = 1, column =0, sticky = S)
#Entry box variables
self.cmd_var = IntVar()
self.parm1_var = DoubleVar()
self.parm2_var = DoubleVar()
self.parm1_var.set(12.0)
self.color_code = 0
# 0 = random
# 1 = blue
# 2 = black
# 3 = red
# 4 = green
self.spiral_type = 5
# 1 = normal,
# 2 = logarithmic,
# 3 = Hyperbolic
# 4 = Fermat's spiral
# 5 = Lituus spiral
#Control FrameWidgets
self.tmpstr = 'Number of spirals:\n'+str(self.parm1_var.get())
self.lab = Label(control_frame, text=self.tmpstr)
self.lab.pack(side = TOP)
# The Canvas
self.canvas = Canvas(canvas_frame, width = 800, height = 800)
self.canvas.config(bg='white')
self.canvas.pack()
self.clear()
frame.pack()
#Menu's
menubar = Menu(root)
menu_1 = Menu(menubar, tearoff=0)
menu_1.add_command(label='Quit',command=root.destroy)
menubar.add_cascade(label='File', menu=menu_1)
menu_2 = Menu(menubar, tearoff=0)
menu_2.add_command(label='2', command=self.menu_2)
menu_2.add_command(label='3', command=self.menu_3)
menu_2.add_command(label='4', command=self.menu_4)
menu_2.add_command(label='5', command=self.menu_5)
menu_2.add_command(label='6', command=self.menu_6)
menu_2.add_command(label='7', command=self.menu_7)
menu_2.add_command(label='8', command=self.menu_8)
menu_2.add_command(label='9', command=self.menu_9)
menu_2.add_command(label='10', command=self.menu_10)
menu_2.add_command(label='11', command=self.menu_11)
menu_2.add_command(label='12', command=self.menu_12)
menubar.add_cascade(label='Spirals', menu=menu_2)
master.config(menu=menubar)
menu_3 = Menu(menubar, tearoff=0)
menu_3.add_command(label='Archimedean', command=self.set_normal)
menu_3.add_command(label='Logarithmic', command=self.set_log)
menu_3.add_command(label='Hyperbolic', command=self.set_hyp)
menu_3.add_command(label='Fermat', command=self.set_fermat)
menu_3.add_command(label='Lituus', command=self.set_lituus)
menubar.add_cascade(label='Type', menu = menu_3)
menu_4 = Menu(menubar, tearoff = 0)
menu_4.add_command(label='Random', command=self.color_ran)
menu_4.add_command(label='Blue', command=self.color_blue)
menu_4.add_command(label='Black', command=self.color_black)
menu_4.add_command(label='Red', command=self.color_red)
menu_4.add_command(label='Green', command=self.color_grn)
menubar.add_cascade(label='Color', menu=menu_4)
def color_grn(self):
"""This function sets the color of th elines to green and then
refreshes the screen."""
self.color_code=4
self.clear()
def color_red(self):
"""This function sets the color of the lines to red and then
refreshes the screen."""
self.color_code=3
self.clear()
def color_black(self):
"""This function sets the color of the lines to black and then
refreshes the screen."""
self.color_code=2
self.clear()
def color_ran(self):
"""This function sets the color of the lines to random and then
refreshes the screen."""
self.color_code = 0
self.clear()
def color_blue(self):
"""This function sets the color of the lines to blue and then
refreshes the screen."""
self.color_code = 1
self.clear()
def set_lituus(self):
"""This function sets the spiral type to Lituus and then
refreshes the screen."""
self.spiral_type = 5
self.clear()
def set_fermat(self):
"""This function sets the spiral type to Fermat and then refreshes
the screen."""
self.spiral_type = 4
self.clear()
def set_hyp(self):
"""This function sets the spiral type to hyperbolic and then
refreshes the screen"""
self.spiral_type=3
self.clear()
def set_normal(self):
"""This function sets the spiral type to Archimedean and then
refreshes the screen"""
self.spiral_type=1
self.clear()
def set_log(self):
"""This function sets the spiral type to Logarithmic and then
refreshes the screen"""
self.spiral_type=2
self.clear()
def clear(self):
"""This function clears the screen, calls the appropriate drawing
function, and updates the message."""
self.canvas.delete(ALL)
if self.spiral_type ==1:
self.draw_spiral()
elif self.spiral_type ==2:
self.draw_log()
elif self.spiral_type ==3:
self.draw_hyp()
elif self.spiral_type ==4:
self.draw_fermat()
else:
self.draw_lituus()
self.tmpstr = 'Number of spirals:\n'+str(self.parm1_var.get())+\
"\nType of Spirals:\n"
types = ['Archimedean','Logarithmic','Hyperbolic',
'Fermat','Lituus']
self.tmpstr = self.tmpstr + types[self.spiral_type -1]
self.lab.config(text=self.tmpstr)
def draw_spiral(self):
"""This is the drawing function for the Archimedean spiral"""
for k in range(0,int(self.parm1_var.get())):
x=0
y=0
if self.color_code == 0:
tk_rgb = "#%02x%02x%02x" % (randint(0,255), randint(0,255),
randint(0,255))
else:
tk_rgb = ['null','blue','black','red','green'][self.color_code]
for r in range(0,400): #scaled 100 = pi
theta = r*2*pi/200.0 - 2*k*pi/self.parm1_var.get()
new_x = r*sin(theta)
new_y = r*cos(theta)
self.canvas.create_line(x+400,y+400,new_x+400,new_y+400,
fill=tk_rgb)
x = new_x
y = new_y
sleep(0.1)
self.canvas.update()
for k in range(0,int(self.parm1_var.get())):
x=0
y=0
if self.color_code == 0:
tk_rgb = "#%02x%02x%02x" % (randint(0,255), randint(0,255),
randint(0,255))
else:
tk_rgb = ['null','blue','black','red','green'][self.color_code]
for r in range(0,400): #scaled 100 = pi
theta = -(r*2*pi/200.0 - 2*k*pi/self.parm1_var.get())
new_x = r*sin(theta)
new_y = r*cos(theta)
self.canvas.create_line(x+400,y+400,new_x+400,new_y+400,
fill=tk_rgb)
x = new_x
y = new_y
sleep(0.1)
self.canvas.update()
def draw_log(self):
"""This is the drawing function for the logarithmic spiral"""
for k in range(0,int(self.parm1_var.get())):
x=0
y=0
if self.color_code == 0:
tk_rgb = "#%02x%02x%02x" % (randint(0,255), randint(0,255),
randint(0,255))
else:
tk_rgb = ['null','blue','black','red','green'][self.color_code]
for r in range(10,1000,10):
theta=log(r) - 2*k*pi/self.parm1_var.get()
#r = exp(theta*2*pi/100.0 + 2*k*pi/self.parm1_var.get())
new_x = r*sin(theta)*0.4
new_y = r*cos(theta)*0.4
self.canvas.create_line(x+400,y+400,new_x+400,new_y+400,
fill=tk_rgb)
x = new_x
y = new_y
sleep(0.1)
self.canvas.update()
for k in range(0,int(self.parm1_var.get())):
x=0
y=0
if self.color_code == 0:
tk_rgb = "#%02x%02x%02x" % (randint(0,255), randint(0,255),
randint(0,255))
else:
tk_rgb = ['null','blue','black','red','green'][self.color_code]
for r in range(10,1000,10):
theta=-(log(r) - 2*k*pi/self.parm1_var.get())
#r = -(exp(theta*2*pi/100.0 + 2*k*pi/self.parm1_var.get()))
new_x = r*sin(theta)*0.4
new_y = r*cos(theta)*0.4
self.canvas.create_line(x+400,y+400,new_x+400,new_y+400,
fill=tk_rgb)
x = new_x
y = new_y
sleep(0.1)
self.canvas.update()
def draw_hyp(self):
"""This is the drawing function for the hyperbolic spiral"""
for k in range(0,int(self.parm1_var.get())):
x=0
y=0
if self.color_code == 0:
tk_rgb = "#%02x%02x%02x" % (randint(0,255), randint(0,255),
randint(0,255))
else:
tk_rgb = ['null','blue','black','red','green'][self.color_code]
for r in range(1,100):
theta=30.0/r + 2*k*pi/self.parm1_var.get()
new_x = r*sin(theta)*4
new_y = r*cos(theta)*4
self.canvas.create_line(x+400,y+400,new_x+400,new_y+400,
fill=tk_rgb)
x = new_x
y = new_y
sleep(0.1)
self.canvas.update()
for k in range(0,int(self.parm1_var.get())):
x=0
y=0
if self.color_code == 0:
tk_rgb = "#%02x%02x%02x" % (randint(0,255), randint(0,255),
randint(0,255))
else:
tk_rgb = ['null','blue','black','red','green'][self.color_code]
for r in range(1,100):
theta=-(30.0/r + 2*k*pi/self.parm1_var.get())
new_x = r*sin(theta)*4
new_y = r*cos(theta)*4
self.canvas.create_line(x+400,y+400,new_x+400,new_y+400,
fill=tk_rgb)
x = new_x
y = new_y
sleep(0.1)
self.canvas.update()
def draw_fermat(self):
"""This is the drawing function for Fermat's spiral"""
for k in range(0,int(self.parm1_var.get())):
x=0
y=0
if self.color_code == 0:
tk_rgb = "#%02x%02x%02x" % (randint(0,255), randint(0,255),
randint(0,255))
else:
tk_rgb = ['null','blue','black','red','green'][self.color_code]
for r in range(0,100):
theta=(r/40.0)**2 + 2.0*k*pi/self.parm1_var.get()
new_x = r*sin(theta)*3
new_y = r*cos(theta)*3
self.canvas.create_line(x+400,y+400,new_x+400,new_y+400,
fill=tk_rgb)
x = new_x
y = new_y
sleep(0.1)
self.canvas.update()
for k in range(0,int(self.parm1_var.get())):
x=0
y=0
if self.color_code == 0:
tk_rgb = "#%02x%02x%02x" % (randint(0,255), randint(0,255),
randint(0,255))
else:
tk_rgb = ['null','blue','black','red','green'][self.color_code]
for r in range(0,100):
theta=-((r/40.0)**2 + 2.0*k*pi/self.parm1_var.get())
new_x = r*sin(theta)*3
new_y = r*cos(theta)*3
self.canvas.create_line(x+400,y+400,new_x+400,new_y+400,
fill=tk_rgb)
x = new_x
y = new_y
sleep(0.1)
self.canvas.update()
def draw_lituus(self):
"""This is the drawing function for a Lituus spiral"""
for k in range(0,int(self.parm1_var.get())):
x=0
y=0
if self.color_code == 0:
tk_rgb = "#%02x%02x%02x" % (randint(0,255), randint(0,255),
randint(0,255))
else:
tk_rgb = ['null','blue','black','red','green'][self.color_code]
for r in range(1,100):
theta=1000.0/r**2 - 2*k*pi/self.parm1_var.get()
new_x = r*sin(theta)*4
new_y = r*cos(theta)*4
self.canvas.create_line(x+400,y+400,new_x+400,new_y+400,
fill=tk_rgb)
x = new_x
y = new_y
sleep(0.1)
self.canvas.update()
for k in range(0,int(self.parm1_var.get())):
x=0
y=0
if self.color_code == 0:
tk_rgb = "#%02x%02x%02x" % (randint(0,255), randint(0,255),
randint(0,255))
else:
tk_rgb = ['null','blue','black','red','green'][self.color_code]
for r in range(1,100):
theta=-(1000.0/r**2 - 2*k*pi/self.parm1_var.get())
new_x = r*sin(theta)*4
new_y = r*cos(theta)*4
self.canvas.create_line(x+400,y+400,new_x+400,new_y+400,
fill=tk_rgb)
x = new_x
y = new_y
sleep(0.1)
self.canvas.update()
def menu_2(self):
self.parm1_var.set(2)
self.clear()
def menu_3(self):
self.parm1_var.set(3)
self.clear()
def menu_4(self):
self.parm1_var.set(4)
self.clear()
def menu_5(self):
self.parm1_var.set(5)
self.clear()
def menu_6(self):
self.parm1_var.set(6)
self.clear()
def menu_7(self):
self.parm1_var.set(7)
self.clear()
def menu_8(self):
self.parm1_var.set(8)
self.clear()
def menu_9(self):
self.parm1_var.set(9)
self.clear()
def menu_10(self):
self.parm1_var.set(10)
self.clear()
def menu_11(self):
self.parm1_var.set(11)
self.clear()
def menu_12(self):
self.parm1_var.set(12)
self.clear()
if __name__ == '__main__':
root = Tk()
root.wm_title('Various kinds of Spirals')
app = App(root)
root.mainloop()