Support Functions Cheat Sheet

Table Of Contents

Coordinate Conversion
Transformation Matrix
Command Line User Interface
Draw XY Axes (3 versions)
Example: Transformation Matrix Class
Example: Create Graphics Objects
Example: Command Line Menu

Coordinate Conversion

File: coordinate_conversion.py -------------------------------------------------------------- viewer is a +Z infinity with no perspective adjustments -------------------------------------------------------------- import coordinate_conversion as cc # ---- Convert window coordinates to center (Cartesian) # ---- coordinates. Coordinates are returned as integers. cx,cy = cc.win_to_center_coords(wx,wy,win_width,win_height) # ---- Convert center (Cartesian) coordinates to window # ---- coordinates. Coordinates are returned as integers. wx,wy = cc.center_to_win_coords(cx,cy,win_width,win_height)

Transformation Matrix

File: transformation_matrix.py -------------------------------------------------------------- import transformation_matrix as tm # ----clone (deepcopy) a np.array new_ary = tm.clone_np_array(ary) # ---- return a copy of 2D or 3D identity matrix 2d_mtx = tm.get_identity_matrix_2d() 3d_mtx = tm.get_identity_matrix_3d() # ---- return a 2D or 3D translation matrix 2d_mtx = tm.get_translation_matrix_2d(dx,dy) 3d_mtx = tm.get_translation_matrix_3d(dx,dy,dz) # ---- return a 2D or 3D Z axis rotation matrix # ---- Note: angle is in degrees 2d_mtx = tm.get_z_rotation_matrix_2d(deg) 3d_mtx = tm.get_z_rotation_matrix_3d(deg): # ---- return a 3D Y axis rotation matrix # ---- Note: angle is in degrees mtx = tm.get_y_rotation_matrix_3d(deg) # ---- return a 3D X axis rotation matrix # ---- Note: angle is in degrees mtx = tm.get_x_rotation_matrix_3d(deg) # ---- return a 2D or 3D scaling matrix mtx = tm.get_scaling_matrix_2d(sx,sy) mtx = tm.get_scaling_matrix_3d(sx,sy,sz)

Command Line User Interface

File: user_interface.py -------------------------------------------------------------- import user_interface as ui # ----running Python3? tf = ui.running_python3() # ---- prompt the user for input string = ui.get_user_input(prompt) # ---- pause program ui.pause() # ---- clear the terminal screen (window) ui.clear_screen() # ---- convert a string to a float tf,num = ui.is_float(s) # ---- convert a string to an integer tf,num = ui.is_int(s): tf,num = ui.is_integer(s) # ---- is string a number (int, float, scientific notation) tf = ui.is_a_number(s)

Draw XY Axes

File: draw_xy_axes.py -------------------------------------------------------------- # ---- Note: # ---- 1. the origin (0,0,0) is assumed to be at the center # ---- of the graphics window # ---- 2. draw the full width and height of graphics window # ---- 3. default arguments: linewidth=1 and linecolor="black" # ---- 4. the viewer is assumed to be at +Z infinity -------------------------------------------------------------- import draw_xy_axes as ax ax.draw_xy_axes(win)

import graphics as gr # ------------------------------------------------------------ # ---- draw graphics window 2D axes # ---- # ---- Note: # ---- 1. the origin (0,0,0) is assumed to be at the center # ---- of the graphics window # ---- 2. draw the full width and height of graphics window # ---- 3. the viewer is assumed to be at +Z infinity # ------------------------------------------------------------ def draw_graphics_window_axes(win, width=1, color='black', labels=True, draw_obj=True): wx = win.width # window width wy = win.height # window height wcx = round(wx/2.0) # window center X wcy = round(wy/2.0) # window center Y axis_objs = [] # ---- X axis xl = gr.Line(gr.Point(0,wcy),gr.Point(wx-1,wcy)) xl.setWidth(width) xl.setFill(color) if draw_obj: xl.draw(win) axis_objs.append(xl) if labels: txt = gr.Text(gr.Point(wx-20,wcy),'X') txt.setFace('courier') txt.setSize(24) txt.setTextColor(color) if draw_obj: txt.draw(win) axis_objs.append(txt) # ---- Y axis yl = gr.Line(gr.Point(wcx,0),gr.Point(wcx,wy-1)) yl.setWidth(width) yl.setFill(color) if draw_obj: yl.draw(win) axis_objs.append(yl) if labels: txt = gr.Text(gr.Point(wcx,20),'y') txt.setFace('courier') txt.setSize(24) txt.setTextColor(color) if draw_obj: txt.draw(win) axis_objs.append(txt) return axis_objs

import graphics as gr # ------------------------------------------------------------ # ---- draw XYZ 3D axes # ---- # ---- Note: # ---- 1. axes Cartesian coordinates # ---- 2. draw defined XYZ axes # ---- 3. the origin (0,0,0) is assumed to be at the center # ---- of the graphics window # ---- 4. the viewer is assumed to be at +Z infinity # ------------------------------------------------------------ AXES = (((-300,0,0),(300,0,0)), # X axis ((0,-300,0),(0,300,0)), # Y axis ((0,0,-300),(0,0,300))) # Z axis def draw_xyz_axes(win, mtrx, axes, width=2, color='black', draw_z_axis=True, draw_obj=True): axis_objs = [] # ---- draw X axis (line) xaxis = axes[0] x0 = cc.center_to_win_coords(xaxis[0][0],xaxis[0][1], win.width,win.height) x1 = cc.center_to_win_coords(xaxis[1][0],xaxis[1][1], win.width,win.height) lobj = gr.Line(gr.Point(x0[0],x0[1]), gr.Point(x1[0],x1[1])) lobj.setWidth(width) lobj.setFill(color) if draw_obj: lobj.draw(win) axis_objs.append(lobj) # ---- draw Y axis (line) yaxis = axes[1] y0 = cc.center_to_win_coords(yaxis[0][0],yaxis[0][1], win.width,win.height) y1 = cc.center_to_win_coords(yaxis[1][0],yaxis[1][1], win.width,win.height) lobj = gr.Line(gr.Point(y0[0],y0[1]), gr.Point(y1[0],y1[1])) lobj.setWidth(width) lobj.setFill(color) if draw_obj: lobj.draw(win) axis_objs.append(lobj) # ---- draw Z axis (line) if draw_z_axis: zaxis = axes[2] z0 = cc.center_to_win_coords(zaxis[0][0],zaxis[0][1], win.width,win.height) z1 = cc.center_to_win_coords(zaxis[1][0],zaxis[1][1], win.width,win.height) lobj = gr.Line(gr.Point(z0[0],z0[1]), gr.Point(z1[0],z1[1])) lobj.setWidth(width) lobj.setFill(color) if draw_obj: lobj.draw(win) axis_objs.append(lobj) return axis_objs

Example: A Transformation Matrix Class

import coordinate_conversion as cc import transformation_matrix as tm # ------------------------------------------------------------ # ---- class - 3D transformation matrix # ---- notes: # ---- 1. Cartesian coordinates # ------------------------------------------------------------ class TransformationMatrix3D: # ---- initialize the class (create an identity matrix) def __init__(self): self.mtrx = np.identity(4) # ---- reset matrix to initial condition # ---- (identity matrix) def reset(self): self.mtrx = np.identity(4) # ---- transform a point's coordinates using the # ---- transformation matrix def transform_coords(self,x,y,z): p = self.mtrx @ [x,y,z,1] return (p[0],p[1],p[2]) # ---- modify transformation matrix # ---- change the location (coordinates) of a point # ---- Note: DX,DY,DZ are the change in a point's # ---- current X,Y,Z coordinates def translate_to_location(self,dx,dy,dz): m = tm.get_translation_matrix_3d(dx,dy,dz) mm = m @ self.mtrx self.mtrx = mm # ---- modify transformation matrix # ---- move a point to the origin (0,0,0) # ---- Note: X,Y,Z are a point's current coordinates def translate_to_origin(self,x,y,z): m = tm.get_translation_matrix_3d(-x,-y,-z) mm = m @ self.mtrx self.mtrx = mm # ---- modify transformation matrix # ---- rotate around the X axis def rotate_around_x_axis(self,degrees): m = tm.get_x_rotation_matrix_3d(degrees) mm = m @ self.mtrx self.mtrx = mm # ---- modify transformation matrix # ---- rotate around the Y axis def rotate_around_y_axis(self,degrees): m = tm.get_y_rotation_matrix_3d(degrees) mm = m @ self.mtrx self.mtrx = mm # ---- modify transformation matrix # ---- rotate around the Z axis def rotate_around_z_axis(self,degrees): m = tm.get_z_rotation_matrix_3d(degrees) mm = m @ self.mtrx self.mtrx = mm # ---- modify transformation matrix # ---- scale a point's coordinates in the X,Y,Z # ---- directions def scale_xyz(self,sx,sy,sz): m = tm.get_scaling_matrix_3d(sx,sy,sz) mm = m @ self.mtrx self.mtrx = mm # ---- return a deepcopy of the current # ---- transformation matrix def deepcopy_matrix(self): return copy.deepcopy(self.mtrx) # ---- return a copy of the current # ---- transformation matrix def copy_matrix(self): return copy.copy(self.mtrx) # ---- return the current transformation matrix def get_matrix(self): return self.mtrx # ---- display the current transformation matrix def display_matrix(self): print(self.mtrx) # ------------------------------------------------------------ # ---- main -------------------------------------------------- # ------------------------------------------------------------ if __name__ == '__main__': # ---- create 3D coordinate transformation matrix mtrx = TransformationMatrix3D() # ---- rotate around X axis 45 degrees mtrx.rotate_around_x_axis(45) # ---- rotate around Y axis -30 degrees mtrx.rotate_around_y_axis(-30) # ---- modify point (100,100,100) coordinates using # ---- transformation matrix p = mtrx.transform_coords(100.0,100.0,100.0) print(f'new coordinate is x={p[0]},y={p[1]},z={p[2]}')

Example: Create Graphics Objects

import graphics as gr import coordinate_conversion as cc #------------------------------------------------------------- # ---- create a point graphics object # ---- convert center (Cartesian) 3D coordinates to # ---- 2D graphics window coordinates. assume the viewer # ---- is at +Z infinity. # ------------------------------------------------------------ def create_point_graphics_object(win,x,y,z, color='red', draw_obj=True): # ---- convert Cartesian coords to window coords xy = cc.center_to_win_coords(x,y, win.width,win.height) # ---- point (window pixel) graphics object pobj = gr.Point() pobj.setFill(color) if draw_obj: pobj.draw(win) return pobj #------------------------------------------------------------- # ---- create a line graphics object # ---- convert center (Cartesian) 3D coordinates to # ---- 2D graphics window coordinates. assume the viewer # ---- is at +Z infinity. # ------------------------------------------------------------ def create_line_graphics_object(win, x0,y0,z0,x1,y1,z1, width=2, color='black', draw_obj=True): # ---- convert Cartesian coords to window coords xy0 = cc.center_to_win_coords(x0,y0, win.width,win.height) xy1 = cc.center_to_win_coords(x1,y1, win.width,win.height) # ---- line graphics object lobj = gr.Line(gr.Point(xy0[0],xy0[1]), gr.Point(xy1[0],xy1[1])) lobj.setWidth(width) lobj.setFill(color) if draw_obj: lobj.draw(win) return lobj # ------------------------------------------------------------ # ---- create a circle graphics object # ---- convert center (Cartesian) 3D coordinates to # ---- 2D graphics window coordinates. assume the viewer # ---- is at +Z infinity. # ------------------------------------------------------------ def create_circle_graphics_object(win, x,y,z, width=2, radius=4, color='white', draw_obj=True): # ---- convert Cartesian coords to window coords wx,wy = cc.center_to_win_coords(x,y, win.width,win.height) # ---- circle graphics object cobj = gr.Circle(gr.Point(wx,xy),radius) cobj.setOutline('black') cobj.setWidth(width) cobj.setFill(color) if draw_obj: cobj.draw(win) return cobj # ------------------------------------------------------------ # ---- create a rectangle graphics object # ---- convert center (Cartesian) 3D coordinates to # ---- 2D graphics window coordinates. assume the viewer # ---- is at +Z infinity. # ------------------------------------------------------------ def create_rectangle_graphics_object(win, x0,y0,z0,x1,y1,z1, width=2, color='white', draw_obj=True): # ---- convert Cartesian coords to window coords xy0 = cc.center_to_win_coords(x0,y0, win.width,win.height) xy1 = cc.center_to_win_coords(x1,y1, win.width,win.height) # ---- rectangle graphics object robj = gr.Rectangle(gr.Point(xy0[0],xy0[1]), gr.Point(xy1[0],xy1[1])) robj.setOutline('black') robj.setWidth(width) robj.setFill(color) if draw_obj: robj.draw(win) return robj # ------------------------------------------------------------ # ---- create a polygon graphics object # ---- convert center (Cartesian) 3D coordinates to # ---- 2D graphics window coordinates. assume the viewer # ---- is at +Z infinity. # ------------------------------------------------------------ # ---- Example: # ---- # ---- POLYGONPOINTS = [ (-100, 100, 0), ( 100, 100, 0), # ---- ( 200, -100, 0), (-200, -100, 0) ] # ------------------------------------------------------------ def create_polygon_graphics_object(win,poly_points width=2, color='green', draw_obj=True): # ---- convert transformed coords to window coords window_polygon_points = [] for pp in poly_points: wx,wy = cc.center_to_win_coords(pp[0],pp[1], win.width,win.height) window_polygon_points.append(gr.Point(wx,wy)) # ---- create polygon graphics object polyobj = gr.Polygon(window_polygon_points) polyobj.setOutline('black') polyobj.setWidth(width) polyobj.setFill(color) if draw_obj: polyobj.draw(win) return polyobj

Example: Command Line Menu

# ------------------------------------------------------------ # ---- command line main menu # ------------------------------------------------------------ import user_interface as ui def main_menu(): extra_menu_items = False menu = ''' ------------------------------------------------ ---------- test Transformation Matrix ---------- Negative rotation angles rotate objs clockwise. Positive angles rotate objs counterclockwise. DX, DY, DZ are changes in an obj's current location, not an absolute location. ------------------------------------------------ q = quit i = reset to initial conditions d = draw wireframe m = display transformation matrix c = clear the graphics window (undraw) --------- Build Transformation Matrix ---------- rx angle = rotate around X axis (deg) ry angle = rotate around Y axis (deg) rz angle = rotate around Z axis (deg) t dx dy dz = move graphics object s sx sy sz = scale graphics object''' extra_menu = ''' o move to origin rip rotate in place all toggle display extra menu''' # ---- menu support function - oops! def _oops(s): print() print(f'OOPS! unknown/bad command ({s})') ui.pause() # ---- graphics object lists ax_objs = [] # axis graphics objects gr_objs = [] # other graphics objects # ---- create graphics window win = GraphWin('wireframe Transformation Test', WINWIDTH, WINHEIGHT) win.setBackground('white') # ---- create X,Y,Z coordinate transformation matrix mtrx = TransformationMatrix3D() # ---- draw X,Y,Z coordinate axes ##ax_objs = draw_xyz_axes(win,mtrx,AXES) ax_objs = draw_graphics_window_axes(win) # ---- display the menu # ---- ask the user to make a selection # ---- process the selection while True: ##ui.clear_screen() print(menu) if extra_menu_items: print(extra_menu) # ---- ask the user to make a selection print() s = ui.get_user_input('Enter command: ') if not s: break # empty string? # ---- lowercase the user's input ss = s.lower() # ---- quit if ss[0] == 'q': break # ---- display transformation matrix if ss[0] == 'm': print('-'*44) mtrx.display_matrix() print('-'*44) ui.pause() continue # ---- create/draw wireframe if ss[0] == 'd': objs = draw_wireframe(win,mtrx,WIREFRAME_LNS) gr_objs += objs continue # ---- special test case for a polygon if ss == 'poly': objs = draw_polygon(win,mtrx,POLYGONPOINTS) gr_objs += objs continue if ss == 'spoly': # small polygon objs = draw_polygon(win,mtrx, S_POLYGONPOINTS,color='yellow') gr_objs += objs continue # ---- reset matrix to initial state if ss[0] == 'i': mtrx.reset() continue # ---- clear graphics window if ss == 'c': ##clear_graphics_window(ax_objs) clear_graphics_window(gr_objs) continue # ---- add rotation to transformation matrix if ss[0] == 'r': x = ss.replace(',', ' ').split() if len(x) != 2: _oops(s) continue tf,deg = ui.is_float(x[1]) if not tf: _oops(s) continue if x[0][1] == 'x': print('rotate around X axis') mtrx.rotate_around_x_axis(deg) continue if x[0][1] == 'y': print('rotate around Y axis') mtrx.rotate_around_y_axis(deg) continue if x[0][1] == 'z': print('rotate around Z axis') mtrx.rotate_around_z_axis(deg) continue _oops(s) # ---- add X,Y,Z movement to transformation matrix if ss[0] == 't': x = ss.replace(',', ' ').split() if len(x) != 4: _oops(s) continue tf,dx = ui.is_float(x[1]) # DX if not tf: _oops(s) continue tf,dy = ui.is_float(x[2]) # DY if not tf: _oops(s) continue tf,dz = ui.is_float(x[3]) # DZ if not tf: _oops(s) continue mtrx.translate_to_location(dx,dy,dz) continue # ---- add scaling to transformation matrix if ss[0] == 's': print() print('Add your scaling code here. This') print('is an exercise for the student.') ui.pause() continue # ---- move to origin if ss[0] == 'o': print('exercise for the student') continue # ---- rotate in place if ss[0] == 'rip': print('exercise for the student') continue # ---- toggle the display of extra menu items if ss == 'all' or ss == 'extra': extra_menu_items = not extra_menu_items continue # ---- OOPS! _oops(s) # ---- close graphics window win.close() # ------------------------------------------------------------ # ---- main # ------------------------------------------------------------ if __name__ == '__main__': main_menu() print()