#!/usr/bin/python3
# ==============================================================
# draw a Theodorus spiral (a square root spiral)
# ==============================================================
import graphics as gr
import coordinate_conversion as cc
import math
import sys
DEBUG = False
# --------------------------------------------------------------
# ---- convert polar to Cartesian coordinates
# ---- convert Cartesian to polar coordinates
# --------------------------------------------------------------
def polar2cart(rho:[int|float],phi:[int|float]) -> tuple:
'''
convert polar to Cartesian coordinates
'''
x = rho * math.cos(phi)
y = rho * math.sin(phi)
return (x,y)
def cart2polar(x,y):
'''
convert Cartesian to polar coordinates
'''
rho = np.sqrt(x**2 + y**2)
phi = np.arctan2(y,x)
return (rho,phi)
# --------------------------------------------------------------
# ---- create a graphics window
# --------------------------------------------------------------
def create_a_graphics_window(width:[int|float],
height:[int|float],
axes:bool=False,
title:str='Graph') -> gr.GraphWin:
'''
create graphics window and maybe Cartesian axes
'''
# ---- create window
win = gr.GraphWin(title,width,height)
win.setBackground("white")
# ---- draw axes?
if axes:
# ---- X,Y axes origin in window coordinates
xaxis = round(width/2.0)
yaxis = round(height/2.0)
# ---- draw X axis (line)
xl = gr.Line(gr.Point(0,yaxis),gr.Point(width-1,yaxis))
xl.setWidth(1)
xl.setFill("black")
xl.draw(win)
# ---- draw Y axis (line)
yl = gr.Line(gr.Point(xaxis,0),gr.Point(xaxis,height-1))
yl.setWidth(1)
yl.setFill("black")
yl.draw(win)
return win
# --------------------------------------------------------------
# ---- create a list of points on a square root spiral
# ---- return polar coordinates:
# ---- distance, angle (radians), angles (degrees)
# --------------------------------------------------------------
# ----
# ---- + sin(x) = a/h
# ---- /| cos(x) = b/h
# ---- / |
# ---- h / | a h = math.sqrt(a**2 + b**2)
# ---- / |
# ---- / |
# ---- / x |
# ---- +------+
# ---- b
# ----
# --------------------------------------------------------------
def create_square_root_spiral_points(loops:int=16) -> list:
'''
create a list of points on a square root spiral
(polar coordinates)
'''
# ---- list of spiral point
pts = []
# ---- initial (starting) point (special case)
a = 1 # triangle side - opposite the angle
b = math.sqrt(1.0) # triangle side - adjacent the angle
angle_rad = 0.0 # initial angle - radians
angle_deg = 0.0 # initial angle - degrees
pts.append((math.sqrt(1.0),angle_rad,angle_deg))
# ---- calculate each of the remaining spiral points
for loop in range(loops):
# ---- calculate hypotenuse
h = math.sqrt(a**2 + b**2)
angle_rad += math.asin(a/h)
angle_deg += math.degrees(angle_rad)
if DEBUG:
print()
print(f'loop {loop}')
print(f'a = {a:.6f}')
print(f'b = {b:.6f}')
print(f'h = {h:.6f}')
print(f'sin = {a/h:.6f}')
print(f'angle rad = {angle_rad:.6f}')
print(f'angle deg = {angle_deg:.6f}')
pts.append((h,angle_rad,angle_deg))
# ---- the hypotenuse becomes side 'b' for the
# ---- next triangle (side 'a' does not change)
b = h
return pts
# --------------------------------------------------------------
# ---- draw the spiral
# ---- (this code is incomplete. finish drawing the lines.)
# --------------------------------------------------------------
def draw_spiral(win:gr.GraphWin,pts:list) -> None:
'''
draw the Theodorus (square root) spiral's lines
'''
for pt in pts:
# ---- convert polar coords to Cartesian coords
x,y = polar2cart(pt[0],pt[1])
x = x*100 # scale the coordinate
y = y*100 # scale the coordinate
# ---- convert Cartesian coords to window coords
cx1,cy1 = cc.center_to_win_coords(x,y,
win.width,win.height)
cx2,cy2 = cc.center_to_win_coords(0.0,0.0,
win.width,win.height)
# ---- draw a line (from point to origin)
l = gr.Line(gr.Point(cx1,cy1),gr.Point(cx2,cy2))
l.setWidth(1)
l.setFill('black')
l.draw(win)
return
# --------------------------------------------------------------
# ---- main
# --------------------------------------------------------------
if __name__ == '__main__':
# ---- Theodorus (square root) spiral points
pts = create_square_root_spiral_points()
# ---- graphics window
win = create_a_graphics_window(801,801,
title="Theodorus (Square Root) Spiral")
# ---- draw a Theodorus (square root) spiral
draw_spiral(win,pts)
# ---- wait for a mouse click in the graphics window,
# ---- then close the window and exit
click = win.getMouse()
win.close()
sys.exit()