Canvas没有画点的函数,我们就用某一点到其右下相邻点的连线来代替。然后自定义一个函数Graph(),把给定函数f(x)在指定区间里的点 (x, f(x)) 依次画出,步进间隔小到一定程度就会连成f(x)对应的曲线。
for ... in range()的步进值只能是整数,所以引入numpy库的arange(),其步进可以是小数,例: for i in numpy.arange(0,2,0.01) # 表示区间[0,1)上步进0.01,共循环200次。
函数解析式的图像
import tkinter as tk
import pyautogui as ag
from math import *
from numpy import arange as np
def Window_Open(W, H):
X, Y = ag.size()
winSize = str(W)+"x"+str(H)
winPos = winSize + "+" + str((X - W) // 2)
winPos += "+" + str((Y - H) // 2)
win.geometry(winPos)
win.resizable(False, False)
title = u'桌面分辨率:' + str(X) + "x" + str(Y)
title += ' ' * 5 + u'窗体大小:' + winSize
win.title(title)
win.update()
def Graph(func,x0,y0,xmin,xmax,w,h,c='blue',step=0.001):
'xmin,xmax 自变量的取值范围; c 图像颜色'
'x0,y0 原点坐标 w,h 横纵轴半长 step 步进'
coord = x0-w,y0,x0+w,y0
tCanvas.create_line(coord,fill='black')
coord = x0,y0-h,x0,y0+h
tCanvas.create_line(coord,fill='black')
w1,w2=100,120 # w1,w2为自变量和函数值在横纵轴上的放大倍数
for x in np(xmin,xmax+step,step):
y = func(x)
coord = x0+w1*x,y0-w2*y,x0+w1*x+1,y0-w2*y+1
if abs(x*w1)<w and abs(y*w2)<h:
tCanvas.create_line(coord,fill=c)
tCanvas.update()
if __name__ == '__main__':
win = tk.Tk()
Window_Open(800,480)
tCanvas = tk.Canvas(win, width=win.winfo_width(), height=480, bg='white')
tCanvas.pack(side="top")
x0,y0=400,240 # 原点坐标
xmax=pi*2 # 自变量最大值,超过横坐标最大值被截短
w,h=380,220 # 横纵轴的正向最大值
fx1 = lambda x : sin(x)+cos(x)
fx2 = lambda x : sin(x)*cos(x)
gx1 = lambda x : exp(abs(x/4))-2
gx2 = lambda x : (x/2)**3-2*(x/2)**2+x/2-1
Graph(sin,x0,y0,-xmax,xmax,w,h)
Graph(cos,x0,y0,-xmax,xmax,w,h,'red')
Graph(fx1,x0,y0,-xmax,xmax,w,h,'lime')
Graph(fx2,x0,y0,-xmax,xmax,w,h,'orange')
Graph(gx1,x0,y0,-xmax,xmax,w,h,'magenta')
Graph(gx2,x0,y0,-xmax,xmax,w,h,'limegreen')
win.mainloop()
效果图:
心形曲线参数方程的图像
把Graph()函数稍作改进,就能画出参数方程对应的曲线图像,如下例:心形曲线的图像
import tkinter as tk
import pyautogui as ag
from math import *
from numpy import arange as np
def Window_Open(W, H):
X, Y = ag.size()
winSize = str(W)+"x"+str(H)
winPos = winSize + "+" + str((X - W) // 2)
winPos += "+" + str((Y - H) // 2)
win.geometry(winPos)
win.resizable(False, False)
title = u'桌面分辨率:' + str(X) + "x" + str(Y)
title += ' ' * 5 + u'窗体大小:' + winSize
win.title(title)
win.update()
def Graph(funcx,funcy,x0,y0,tmin,tmax,w,h,c='blue',step=0.001):
'xmin,xmax 自变量的取值范围; c 图像颜色'
'x0,y0 原点坐标 w,h 横纵轴半长 step 步进'
coord = x0-w,y0,x0+w,y0
tCanvas.create_line(coord,fill='black')
coord = x0,y0-h,x0,y0+h
tCanvas.create_line(coord,fill='black')
w1,w2=100,110 # w1,w2为自变量和函数值在横纵轴上的放大倍数
for t in np(tmin,tmax+step,step):
x = funcx(t)
y = funcy(t)
coord = x0+w1*x,y0-w2*y,x0+w1*x+1,y0-w2*y+1
if abs(x*w1)<w and abs(y*w2)<h:
tCanvas.create_line(coord,fill=c)
tCanvas.update()
if __name__ == '__main__':
win = tk.Tk()
Window_Open(480,480)
tCanvas = tk.Canvas(win, width=win.winfo_width(), height=480, bg='white')
tCanvas.pack(side="top")
x0,y0=240,240 # 原点坐标
a = 0.7
fx = lambda t : a*(2.0*sin(t)-sin(2*t))
fy = lambda t : a*(1.6*cos(t)-cos(2*t))+0.5
Graph(fx,fy,x0,y0,-pi,pi,220,200,c='red')
win.mainloop()
效果图:
椭圆、双曲线、抛物线的图像
import tkinter as tk
import pyautogui as ag
from math import *
from numpy import arange as np
def Window_Open(W, H):
X, Y = ag.size()
winSize = str(W)+"x"+str(H)
winPos = winSize + "+" + str((X - W) // 2)
winPos += "+" + str((Y - H) // 2)
win.geometry(winPos)
win.resizable(False, False)
title = u'桌面分辨率:' + str(X) + "x" + str(Y)
title += ' ' * 5 + u'窗体大小:' + winSize
win.title(title)
win.update()
def Graph(funcx,funcy,x0,y0,tmin,tmax,w,h,c='blue',step=0.001):
'xmin,xmax 自变量的取值范围; c 图像颜色'
'x0,y0 原点坐标 w,h 横纵轴半长 step 步进'
coord = x0-w,y0,x0+w,y0
tCanvas.create_line(coord,fill='black')
coord = x0,y0-h,x0,y0+h
tCanvas.create_line(coord,fill='black')
w1,w2=100,100 # w1,w2为自变量和函数值在横纵轴上的放大倍数
for t in np(tmin,tmax+step,step):
x = funcx(t)
y = funcy(t)
coord = x0+w1*x,y0-w2*y,x0+w1*x+1,y0-w2*y+1
if abs(x*w1)<w and abs(y*w2)<h:
tCanvas.create_line(coord,fill=c)
tCanvas.update()
if __name__ == '__main__':
win = tk.Tk()
Window_Open(480,480)
tCanvas = tk.Canvas(win, width=win.winfo_width(), height=480, bg='white')
tCanvas.pack(side="top")
x0,y0=240,240
a,b = 1,1.2
p = 0.5
f1x = lambda t : a*cos(t)
f1y = lambda t : b*sin(t)
f2x = lambda t : a/cos(t)
f2y = lambda t : b*tan(t)
f3x = lambda t : 2*p*t**2
f3y = lambda t : 2*p*t
Graph(f1x,f1y,x0,y0,-pi,pi,220,200)
Graph(f2x,f2y,x0,y0,-pi,pi,220,200,c='red')
Graph(f3x,f3y,x0,y0,-pi,pi,220,200,c='green')
win.mainloop()
效果图:
附:圆锥曲线的参数方程
椭圆
x = a*cost
y = b*sint
双曲线
x = a*sect
y = b*tant
抛物线
x = 2*p*t²
y = 2*p*t