#!/usr/bin/python3 # =================================================================== # How High is the Mountain - Draw Diagram From User Input # =================================================================== import sys import draw_axes as ax import coordinate_conversion as cc import user_interface as ui import graphics as gr from math import radians, sin, cos # ---- input ranges flight_altitude_min = 10000 flight_altitude_max = 80000 measure_distance_min = 1000 measure_distance_max = 20000 angle_alpha_min = 10 angle_alpha_max = 80 angle_beta_min = 10 angle_beta_max = 80 # ---- graphics window wwidth = 801 # (pixels) window width wheight = 801 # (pixels) window height maxxy = 300 # (pixels) diagram max x,y pixels # max distance from the origin 0,0 # ---- explanation explanation = f''' This program will calculate and then draw a diagram that show the height of a mountain based on the user's input. Ridiculous input data will result in ridiculous output. {flight_altitude_min:>6} < flight altitude < {flight_altitude_max:<6} {measure_distance_min:>6} < measure distance < {measure_distance_max:<6} {angle_alpha_min:>6} < angle alpha < {angle_alpha_max:<6} {angle_beta_min:>6} < angle beta < {angle_beta_max:<6} ''' # ------------------------------------------------------------------- # ---- prompt for user input # ------------------------------------------------------------------- def user_input(min,max,prompt): while(True): print() s = ui.get_user_input(prompt) if not s: return(False,0) x,n = ui.is_float(s) if not x: print() print('unknown value enter - try again') continue if n < min: print() print(f'value must be > {min} - try again') continue if n > max: print() print('value must < {max} - try again') continue return(True,n) # ------------------------------------------------------------------- # ---- get all user input # ------------------------------------------------------------------- def get_all_user_input(explanation = None): ui.clear_screen() if explanation: print(explanation) # ---- flight altitude x,n = user_input(flight_altitude_min, flight_altitude_max, 'Enter flight altitude (ft): ') if not x: return(False,0,0,0,0) flight_altitude = n # ---- measure distance flight_altitude = n # ---- measure distance x,n = user_input(measure_distance_min, measure_distance_max, 'Enter measure distance (ft): ') if not x: return(False,0,0,0,0) measure_distance = n # ---- angle alpha x,n = user_input(angle_alpha_min, angle_alpha_max, 'Enter angle alpha (deg): ') if not x: return(False,0,0,0,0) angle_alpha = n # ---- angle beta x,n = user_input(angle_beta_min, angle_beta_max, 'Enter angle beta (deg): ') if not x: return(False,0,0,0,0) angle_beta = n # ---- return user input return(True,flight_altitude,measure_distance, angle_alpha,angle_beta) # ------------------------------------------------------------------- # ---- calculation beta angle x and y # ------------------------------------------------------------------- def calculation(flight_altitude, measure_distance, angle_alpha, angle_beta): angle_gamma = 180 - angle_alpha - angle_beta alpha_rad = radians(angle_alpha) beta_rad = radians(angle_beta) gamma_rad = radians(angle_gamma) gamma_hypotenuse = (sin(alpha_rad) * measure_distance) / sin(gamma_rad) beta_x = sin(beta_rad) * gamma_hypotenuse beta_y = cos(beta_rad) * gamma_hypotenuse return(beta_x, beta_y) # ------------------------------------------------------------------- # ---- draw diagram # ------------------------------------------------------------------- def draw_diagram(flight_altitude, measure_distance, beta_x, beta_y): # --------------------------------------------------------------- # ---- draw a point # --------------------------------------------------------------- def draw_point(win,x,y,raidus=5,color='black'): wx,wy = cc.center_to_win_coords(x,y,wwidth,wheight) c = gr.Circle(gr.Point(wx,wy),raidus) c.setFill(color) c.draw(win) # --------------------------------------------------------------- # ---- draw a line # --------------------------------------------------------------- def draw_line(win,x0,y0,x1,y1,width=3,color='black'): wx0,wy0 = cc.center_to_win_coords(x0,y0,wwidth,wheight) wx1,wy1 = cc.center_to_win_coords(x1,y1,wwidth,wheight) c = gr.Line(gr.Point(wx0,wy0),gr.Point(wx1,wy1)) c.setWidth(width) c.setFill(color) c.draw(win) # --------------------------------------------------------------- # ---- add text to window # --------------------------------------------------------------- def add_text(win,x,y,txt): wx,wy = cc.center_to_win_coords(x,y,wwidth,wheight) t = gr.Text(gr.Point(wx,wy),txt) t.setSize(20) t.draw(win) # --------------------------------------------------------------- # ---- scale coordinates to fit the diagram in the window # ---- center the diagram so that the beta angle # ---- x coordinate is 0 and the y coordinate is 1/2 of beta_y # --------------------------------------------------------------- def scale_point_coords(maxxy,measure_distance,beta_x,beta_y): # ---- calculate coordinates x0 = -(measure_distance - beta_x) y0 = beta_y / 2.0 x1 = beta_x y1 = beta_y / 2.0 x2 = 0.0 y2 = -beta_y / 2.0 # ---- calculate the scale factor to fit diagram # ---- in the graphics window max_coord = 0.0 if abs(x0) > max_coord: max_coord = abs(x0) if abs(y0) > max_coord: max_coord = abs(y0) if abs(x1) > max_coord: msx_coord = abs(x1) if abs(y1) > max_coord: max_coord = abs(y1) if abs(x2) > max_coord: max_coord = abs(x2) if abs(y2) > max_coord: max_coord = abs(y2) scale = maxxy / max_coord print(f'scale factor : {round(scale,6)}') # ---- round and scale coordinates x0 = round(x0 * scale) y0 = round(y0 * scale) x1 = round(x1 * scale) y1 = round(y1 * scale) x2 = round(x2 * scale) y2 = round(y2 * scale) return (x0,y0,x1,y1,x2,y2) # ---- create graphics window win = gr.GraphWin("How high is the mountain?",wwidth,wheight) win.setBackground("white") # ---- draw x,y axes ax.draw_xy_axes(win,True) # ---- calculate the triangle point coordinates # ---- round coordinates and scale to fit in the window x0,y0,x1,y1,x2,y2 = scale_point_coords(maxxy, measure_distance, beta_x, beta_y) print(f'point x0 : {x0:<8} (pix)') print(f'point y0 : {y0:<8} (pix)') print(f'point x1 : {x1:<8} (pix)') print(f'point y1 : {y1:<8} (pix)') print(f'point x2 : {x2:<8} (pix)') print(f'point y2 : {y2:<8} (pix)') draw_point(win,x0,y0) draw_point(win,x1,y1) draw_point(win,x2,y2) draw_line(win,x0,y0,x1,y1) draw_line(win,x1,y1,x2,y2) draw_line(win,x2,y2,x0,y0) # ---- add text to window add_text(win,0,y0+20,str(flight_altitude)+' ft') add_text(win,x0,y0+20,'alpha') add_text(win,x1,y1+20,'beta') add_text(win,x2,y2-40,'mountain top\n' + str(flight_altitude - beta_y) + ' ft') # ---- pause then proceed ui.pause() win.close() # ------------------------------------------------------------------- # ---- main # ------------------------------------------------------------------- if __name__ == '__main__': (x,flight_altitude,measure_distance, angle_alpha,angle_beta) = get_all_user_input(explanation) if not x: print() sys.exit() print() print(f'flight altitude : {flight_altitude:<8} (ft)') print(f'measure distance: {measure_distance:<8} (ft)') print(f'angle alpha : {angle_alpha:<8} (deg)') print(f'angle beta : {angle_beta:<8} (deg)') beta_x,beta_y = calculation(flight_altitude, measure_distance, angle_alpha, angle_beta) beta_x = round(beta_x,1) beta_y = round(beta_y,1) print(f'angle beta x : {beta_x:<8} (ft)') print(f'angle beta y : {beta_y:<8} (ft)') draw_diagram(flight_altitude,measure_distance,beta_x,beta_y) print()