Python tkinter库之Canvas 根据函数解析式或参数方程画出图像

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

猜你喜欢

转载自blog.csdn.net/boysoft2002/article/details/115311607