from tkinter import * import math from R2Graph import * def func(x): return math.sin(2.0*x)*(4.0/(1.0 + 0.2*x*x)) SCALEX = 40 SCALEY = SCALEX def main(): root = Tk() root.title("Plot Function") root.geometry("800x600") panel = Frame(root) drawArea = Canvas(root, bg="white") panel.pack(side=TOP, fill=X) drawButton = Button(panel, text="Draw") clearButton = Button(panel, text="Clear") drawButton.pack(side=LEFT, padx=4, pady=4) clearButton.pack(side=LEFT, padx=4, pady=4) drawArea.pack(side=TOP, fill=BOTH, expand=True, padx=4, pady=4) root.update() points = [] mouseButtons = [] def map(t): '''Map mathematical coordinates into pixel coordinates R2Point --> (x, y)''' w = drawArea.winfo_width() h = drawArea.winfo_height() ox = w/2. oy = h/2. return (ox + t.x*SCALEX, oy - t.y*SCALEY) def invmap(p): '''Map pixel coordinates into mathematical coordinates (x, y) --> R2Point''' w = drawArea.winfo_width() h = drawArea.winfo_height() ox = w/2. oy = h/2. x = float(p[0] - ox)/SCALEX y = float(oy - p[1])/SCALEY return R2Point(x, y) def xmin(): w = drawArea.winfo_width() return (-w/2.)/SCALEX def xmax(): w = drawArea.winfo_width() return (w/2.)/SCALEX def ymin(): h = drawArea.winfo_height() return (-h/2.)/SCALEY def ymax(): h = drawArea.winfo_height() return (h/2.)/SCALEY def drawGrid(): x0 = xmin(); x1 = xmax() y0 = ymin(); y1 = ymax() # Grid for x in range(int(x0), int(x1) + 1): if x == 0: continue drawArea.create_line( map(R2Point(x, y0)), map(R2Point(x, y1)), fill="lightGray" ) for y in range(int(y0), int(y1) + 1): if y == 0: continue drawArea.create_line( map(R2Point(x0, y)), map(R2Point(x1, y)), fill="lightGray" ) # Coordinate axes drawArea.create_line( map(R2Point(x0, 0.)), map(R2Point(x1, 0.)), fill="black", width=2 ) drawArea.create_line( map(R2Point(0., y0)), map(R2Point(0., y1)), fill="black", width=2 ) def plotFunc(f): line = [] x = xmin() x1 = xmax() dx = 0.05 while x <= x1: t = R2Point(x, f(x)) line.append(map(t)) x += dx drawArea.create_line(line, fill="blue", width=3) def drawPoints(): for i in range(len(points)): t = points[i] n = mouseButtons[i] if n == 1: color = "red" elif n == 2: color = "darkGreen" else: color = "darkMagenta" dx = R2Vector(0.2, 0.) drawArea.create_line( map(t - dx), map(t + dx), fill=color, width=2 ) dy = R2Vector(0., 0.2) drawArea.create_line( map(t - dy), map(t + dy), fill=color, width=2 ) def onDraw(): drawArea.delete("all") drawGrid() plotFunc(func) drawPoints() def onClear(): points.clear() mouseButtons.clear() drawArea.delete("all") drawGrid() drawButton.configure(command = onDraw) clearButton.configure(command = onClear) def onClick(e): # print(e) p = (e.x, e.y) t = invmap(p) points.append(t) mouseButtons.append(e.num) if e.num == 1: color = "red" elif e.num == 2: color = "darkGreen" else: color = "darkMagenta" dx = R2Vector(0.2, 0.) drawArea.create_line( map(t - dx), map(t + dx), fill=color, width=2 ) dy = R2Vector(0., 0.2) drawArea.create_line( map(t - dy), map(t + dy), fill=color, width=2 ) def onConfigure(e): onDraw() drawArea.bind("", onClick) drawArea.bind("", onClick) drawArea.bind("", onClick) drawArea.bind("", onConfigure) drawGrid() plotFunc(func) root.mainloop() if __name__ == "__main__": main()