Theodorus (Square Root) Spiral

#!/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()