Programming Projects

#!/usr/bin/python3 # =================================================================== # my basic plot object # # Things to do/fix/add: # - add tickmarks # - cleanup offset origin (Ignore plot points with negative XY # coordinate. They are outside the plot area.) # - set a maximum XY axis values (not all the way to the edge) # (ignore data points not in the plot area) # - scale user data to fit the plot (scale user data range to # plot data range) # # Note: This code was for practice. For the real world use one # of the existing plot packages. They are much more capable # and sophisticated. # =================================================================== import graphics as gr # ------------------------------------------------------------------- # ---- plot class (accumulated plot functionality) # ------------------------------------------------------------------- class MyPlot: '''my basic plot object - graphics window, axes, ...''' def __init__(self, # ---- graphics window width and height win_width=801, win_height=801, # ---- graphics window title win_title='My Plot', # ---- graphics window background color win_bcolor='white', # ---- origin location in graphics window offset_origin = False, x_origin=100, y_origin=100, # ---- draw axes? draw_axes=True, # ---- draw axes labels? draw_axis_labels = False, x_axis_label = "X AXIS", y_axis_label = "Y AXIS"): self.wtitle = win_title self.wwidth = win_width self.wheight = win_height self.wbcolor = win_bcolor self.offsetorigin = offset_origin self.xorigin = x_origin self.yorigin = y_origin self.drawaxes = draw_axes self.drawaxislabels = draw_axis_labels self.xaxislabel = x_axis_label self.yaxislabel = y_axis_label if not self.offsetorigin: self.xorigin = int(win_width/2) self.yorigin = int(win_height/2) self.axislables = False self.win = gr.GraphWin(win_title,self.wwidth,self.wheight) self.win.setBackground(win_bcolor) if draw_axes: self.draw_xy_axes() # --------------------------------------------------------------- # ---- vertical string (display helper function) # --------------------------------------------------------------- def vertical_string(self,string): vstring = '' l = len(string) i = 0 while i < l: vstring = vstring + string[i] i += 1 if i >= l: break vstring = vstring + '\n' return vstring # --------------------------------------------------------------- # ---- true or false (display helper function) # --------------------------------------------------------------- def true_false(self,tf): if tf: return 'True' return 'False' # --------------------------------------------------------------- # ---- display internal state # --------------------------------------------------------------- def internal_state(self): print('----------------------------------------------------') print(f'win title = {self.wtitle}') print(f'win width = {self.wwidth:<12} (pixels)') print(f'win height = {self.wheight:<12} (pixels)') print(f'win bcolor = {self.wbcolor}') tf = self.true_false(self.offsetorigin) print(f'offset origin = {tf:<12} (flag)') print(f'x origin = {self.xorigin:<12} (win coords)') print(f'y origin = {self.yorigin:<12} (win coords)') tf = self.true_false(self.drawaxes) print(f'draw axes = {tf:<12} (flag)') tf = self.true_false(self.drawaxislabels) print(f'draw axis labels = {tf:<12} (flag)') print(f'x axis label = "{self.xaxislabel}"') print(f'y axis label = "{self.yaxislabel}"') print('----------------------------------------------------') return # --------------------------------------------------------------- # ---- get graphics window object # --------------------------------------------------------------- def get_win(self): return self.win # --------------------------------------------------------------- # ---- draw X,Y axes (also labels?) # --------------------------------------------------------------- def draw_xy_axes(self,linewidth=1,linecolor="black"): go = [] # graphics object list # ---- draw axes if self.drawaxes: if self.offsetorigin: xstart = self.xorigin - 1 xend = self.wwidth - 1 xaxis_y = self.y_coord_for_x_axis() ystart = self.wheight - self.yorigin - 1 yend = 0 yaxis_x = self.x_coord_for_y_axis() else: xstart = 0 xend = self.wwidth - 1 xaxis_y = self.y_coord_for_x_axis() ystart = self.wheight - 1 yend = 0 yaxis_x = self.x_coord_for_y_axis() ##print('---------------------------------------') ##print(f'xstart = {xstart}') ##print(f'xend = {xend}') ##print(f'xaxis y = {xaxis_y}') ##print(f'ystart = {ystart}') ##print(f'yend = {yend}') ##print(f'yaxis x = {yaxis_x}') ##print('---------------------------------------') # ---- X axis xl = gr.Line(gr.Point(xstart,xaxis_y), gr.Point(xend,xaxis_y)) xl.setWidth(linewidth) xl.setFill(linecolor) xl.draw(self.win) go.append(xl) # ---- Y axis yl = gr.Line(gr.Point(yaxis_x,ystart), gr.Point(yaxis_x,yend)) yl.setWidth(linewidth) yl.setFill(linecolor) yl.draw(self.win) go.append(yl) # ---- draw axis labels (only for offset plots) if self.drawaxislabels and self.offsetorigin: # X axis lable xaxis = gr.Text(gr.Point(self.xorigin,self.yorigin+30), self.xaxislabel) xaxis.setSize(24) xaxis.setStyle("bold") xaxis.draw(self.win) go.append(xaxis) # ---- Y axis label vstring = self.vertical_string(self.yaxislabel) yaxis = gr.Text(gr.Point(self.yorigin,self.xorigin-30), vstring) yaxis.setSize(24) yaxis.setStyle("bold") yaxis.draw(self.win) go.append(yaxis) return go # --------------------------------------------------------------- # ---- draw a point (small circle) using window coordinates # --------------------------------------------------------------- def draw_point(self,wx,wy,color='red',size=4): p = gr.Circle(gr.Point(wx,wy),size) p.setFill(color) p.setOutline('black') p.draw(self.win) return p # --------------------------------------------------------------- # ---- given XY Cartesian coordinates # ---- return their window XY coordinates # --------------------------------------------------------------- def window_xy(self,x,y): wx = round(self.xorigin + x) wy = round(self.wheight -self.yorigin - y) return (wx,wy) # --------------------------------------------------------------- # ---- Y coordinate for X axis # --------------------------------------------------------------- def y_coord_for_x_axis(self): return self.wheight - self.yorigin - 1 # --------------------------------------------------------------- # ---- X coordinate for y axis # --------------------------------------------------------------- def x_coord_for_y_axis(self): if self.offsetorigin: return self.xorigin - 1 else: return self.wheight - self.yorigin - 1 # --------------------------------------------------------------- # ---- pause - wait for mouse click # --------------------------------------------------------------- def wait_for_mouse_click(self): click = self.win.getMouse() return (click.getX(),click.getY()) # ------------------------------------------------------------------- # ---- main # ------------------------------------------------------------------- if __name__ == '__main__': import math # --------------------------------------------------------------- # ---- plot a point (main support function) # --------------------------------------------------------------- def plot_a_point(x,y): wx,wy = plt.window_xy(x,y) p = plt.draw_point(wx,wy) return p # --------------------------------------------------------------- # ---- plot a sine curve (main support function) # --------------------------------------------------------------- def plot_sine_curve(): go = [] # graphics objects x = 0 for deg in range(0,361,30): rad = math.radians(deg) y = math.sin(rad) * 100 wx,wy = plt.window_xy(x,y) p = plt.draw_point(wx,wy,color='green',size=8) go.append(p) x += 30 return go # ---- offset plot #plt = MyPlot(offset_origin=True,x_origin=100,y_origin=200) # ---- center (Cartesian) plot plt = MyPlot() plt.internal_state() plot_a_point(200,200) plot_a_point(-200,200) plot_a_point(-200,-200) plot_a_point(200,-200) plot_sine_curve() plt.wait_for_mouse_click() plt.get_win().close()