#!/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 ORIGIN_LINES = False # -------------------------------------------------------------- # ---- convert polar to Cartesian coordinate systems # ---- # ---- ## Cartesian to polar # ---- def cart2polar(x,y): # ---- rho = np.sqrt(x**2 + y**2) # ---- phi = np.arctan2(y,x) # ---- return (rho,phi) # -------------------------------------------------------------- def polar2cart(rho:[int|float],phi:[int|float]) -> tuple: ''' polar to cartesian ''' x = rho * math.cos(phi) y = rho * math.sin(phi) return (x,y) # -------------------------------------------------------------- # ---- 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 # ---- # ---- format (tuple): # ---- [0] radial distance # ---- [1] triangle polar angle (degrees) # ---- [2] triangle polar angle (radians) # ---- [3] triangle hypotenuse using a and b # ---- (next triangle's b value) # -------------------------------------------------------------- # ---- angle x # ---- # ---- + sin(x) = a/h # ---- /| cos(x) = b/h # ---- / | # ---- h / | a h = math.sqrt(a**2 + b**2) # ---- / | # ---- / | x = atan(a/b) x = atan2(x,y) # ---- / x | x = asin(a/h) # ---- +------+ x = acos(b/h) # ---- b # ---- # -------------------------------------------------------------- def create_square_root_spiral_points(loops:int=17) -> list: ''' create a list of points on a square root spiral ''' pts = [] # list of spiral point # ---- calculate each of the sprial points for loop in range(0,loops): # ---- loop == 0 is the initial spiral point # ---- on the x axes if loop == 0: a = 0.0 b = 1.0 hyp = 1.0 rad = 0.0 deg = 0.0 dst = 1.0 else: a = 1.0 b = math.sqrt(loop) hyp = math.sqrt(a**2 + b**2) rad = math.asin(a/hyp) deg = math.degrees(rad) dst = math.sqrt(loop + 1) if DEBUG: print() print(f'loop {loop}') print(f'a ={a:.6f} b={b:.6f} hyp={hyp:.6f}') print(f'dst={dst:.6f} deg={deg:.6f} rad={rad:.6f}') pts.append((dst,rad,deg,hyp)) return pts # -------------------------------------------------------------- # ---- draw a spiral (this code is incomplete. finish it.) # -------------------------------------------------------------- def draw_spiral(win:gr.GraphWin,pts:list) -> None: accmulated_angle = 0.0 previous_point = None for pt in pts: accmulated_angle += pt[1] x,y = polar2cart(pt[0],accmulated_angle) x = x*75 # scale the coordinate y = y*75 # scale the coordinate # ---- convert point cartesian coords to window coords wx1,wy1 = cc.center_to_win_coords(x,y, win.width,win.height) # ---- draw a line (from point to point) if previous_point is not None: l = gr.Line(gr.Point(wx1,wy1),previous_point) l.setWidth(1) l.setFill('black') l.draw(win) # ---- draw a line (from point to origin) if ORIGIN_LINES: wx2,wy2 = cc.center_to_win_coords(0.0,0.0, win.width,win.height) l = gr.Line(gr.Point(wx1,wy1),gr.Point(wx2,wy2)) l.setWidth(1) l.setFill('black') l.draw(win) # ---- draw a point (circle) c = gr.Circle(gr.Point(wx1,wy1),4) c.setFill('red') c.draw(win) # ---- save the current point previous_point = gr.Point(wx1,wy1) return # -------------------------------------------------------------- # ---- main # -------------------------------------------------------------- if __name__ == '__main__': # ---- square root spirial plot/drawing points pts = create_square_root_spiral_points() # ---- graphics window win = create_a_graphics_window(801,801,axes=False, title="Theodorus (Square Root) Spiral") # ---- draw a Theodorus (square root) spiral draw_spiral(win,pts) # ---- wait for a mouse click in window, then exit click = win.getMouse() win.close() sys.exit()