Проект. Моделювання математичних функцій

Нехай потрібно побудувати графік функції, вид якої вибирається із списку. Тут потрібно  використання додаткових інтерфейсних елементів бібліотеки tkinter, а також створення власних (користувальницьких) процедур та функцій для полегшення розуміння коду.
Результат рішення завдання показано на рисунку



from tkinter import*
import math
#
# Користувальницькі процедури
#
def plot_x_axe(x0,y0,x1):
    x_axe=[]
    xx=(x0,y0)
    x_axe.append(xx)
    xx=(x1,y0)
    x_axe.append(xx)
    canvas.create_line(x_axe,fill="black",width=2)
#
def plot_y_axe(x0,y0,y1):
    y_axe=[]
    yy=(x0,y1)
    y_axe.append(yy)
    yy=(x0,y0)
    y_axe.append(yy)
    canvas.create_line(y_axe,fill="black",width=2)
#
def plot_func0(x0,x1,dx,y0,y1):
    x0i=int(x0)
    x1i=int(x1)
    y0i=int(y0)
    y1i=int(y1)
    a=y1
    b=(y0-y1)/(x1-x0)
    points=[]
    for x in range(x0i,x1i,dx):
        y=int(a+b*x)
        pp=(x,y)
        points.append(pp)
    #
    canvas.create_line(points,fill="blue",smooth=1)
    plot_y_axe(x0i,y0i,y1i)
    plot_x_axe(x0i,y0i,x1i)
#
def plot_func1(x0,x1,dx,y0,y1):
    x0i=int(x0)
    x1i=int(x1)
    y0i=int(y0)
    y1i=int(y1)
    a=y0
    b=y0-y1
    points=[]
    for x in range(x0i,x1i,dx):
        y=int(a-y1i*b/x)
        pp=(x,y)
        points.append(pp)
#
    canvas.create_line(points,fill="blue",smooth=1)
    plot_y_axe(x0i,y0i,y1i)
    plot_x_axe(x0i,y0i,x1i)
#
def plot_func2(x0,x1,dx,y0,y1):
    x0i=int(x0)
    x1i=int(x1)
    y0i=int(y0)
    y1i=int(y1)
    a=(y0-y1)/(15*x1)
    b=1+((y0-y1)/(x1-x0))
    points=[]
    for x in range(x0i,x1i,dx):
        y=y0i-int(a*(x-x0i)**b)
        pp=(x,y)
        points.append(pp)
#
    canvas.create_line(points,fill="blue",smooth=1)
    plot_y_axe(x0i,y0i,y1i)
    plot_x_axe(x0i,y0i,x1i)
#
def plot_func3(x0,x1,dx,y0,y1):
    x0i=int(x0)
    x1i=int(x1)
    y0i=int(y0)
    y1i=int(y1)
    ay=150
    y0i=150
    points=[]
    for x in range(x0i,x1i,dx):
        y=y0i-ay*math.cos(x*dx)
        pp=(x,y)
        points.append(pp)
#
    canvas.create_line(points,fill="blue",smooth=1)
    plot_y_axe(x0i,0,y0i+ay)
    plot_x_axe(x0i,y0i,x1i)

#
def DrawGraph():
    fn=func.get()
    f=fn[0]
    x0=50.0
    y0=250.0
    x1=450.0
    y1=50.0
    dx=10
#
    if f=="0":
        canvas.delete("all")
        plot_func0(x0,x1,dx,y0,y1)
    elif f=="1":
        canvas.delete("all")
        plot_func1(x0,x1,dx,y0,y1)
    elif f=="2":
        canvas.delete("all")
        plot_func2(x0,x1,dx,y0,y1)
    else:
        canvas.delete("all")
        plot_func3(x0,x1,dx,y0,y1)

# Основна частина
tk=Tk()
tk.title("Моделі математичних функцій")

# Верхня частина вікна зі списком і кнопками
menuframe=Frame(tk)
menuframe.pack({"side":"top","fill":"x"})

# Напис для списку
lbl=Label(menuframe)
lbl["text"]="Вибір:"
lbl.pack({"side":"left"})

# Ініціалізація і формування списку
func=StringVar(tk)
func.set('0 y=Ax+B')
#
fspis=OptionMenu(menuframe,func,
'0 y=Ax+B',
'1 y=A+B/x',
'2 y=Ax^B',
'3 y=A*cos(Bx)')
fspis.pack({"side":"left"})

# Кнопка управління рисуванням
btnOk=Button(menuframe)
btnOk["text"]="Нарисувати"
btnOk["command"]=DrawGraph
btnOk.pack({"side":"left"})

# Кнопка закриття додатку

button=Button(menuframe)
button["text"]="Закрити"
button["command"]=tk.quit
button.pack({"side":"right"})

# Область рисування (полотно)
canvas=Canvas(tk)
canvas["height"]=360
canvas["width"]=480
canvas["background"]="#eeeeff"
canvas["borderwidth"]=2
canvas.pack({"side":"bottom"})

tk.mainloop()

Основна частина програми (інтерфейсна) починається з моменту створення кореневого вікна (інструкція tk = Tk ()). У цьому вікні розміщуються два інтерфейсних елементи - рамка (Frame) і холст (полотно - Canvas). Рамка є «контейнер» для інших інтерфейсних елементів - текстового напису (мітки - Label), розкриває список варіантів (OptionMenu) та двома кнопками.
Як видно, кнопка закриття стала об'єктом рамки, а не кореневого вікна, але як завжди
закриває все вікно.

Для отримання потрібного розміщення елементів метод pack() використовується з вказівкою, як саме розміщувати елементи інтерфейсу (до якої сторони елемента контейнера їх потрібно «притискати»).

Є деякі тонкощі в створенні розкриваючого списку. Для успішного виконання цієї операції необхідно попередньо сформувати рядок (а точніше, об'єкт StringVar ()) і визначити для цього об'єкта значення по замовчуванню (це значення показується func.set('0 y=Ax+B')в тільки що запущеному додатку ). Потім в елементі OptionMenu() список значень доповнюється. При виборі елемента списку змінюється значення саме цього рядка і для подальшої роботи потрібно його аналізувати, що і виконується у процедурах DrawGraph().

Обчислювальна частину, а саме, всі процедури та функції, що забезпечують обчислення  координат точок і рисування ліній, винесено в початок тексту програми.

Визначення кожної користувальницької процедури або функції забезпечується оператором def. Функції займаються тільки рисуванням, вони не повертають ніяких значень (тобто результати виконання цих функцій не присвоюються змінним).

Процедура рисування графіка DrawGraph() викликається при натисканні кнопки «Нарисувати», і ім'я цієї функції є командою, яка відповідає кнопці.

Ця процедура бере значення зі списку (метод get ()), вибирає перший символ рядка, що утворився і в залежності від цього символу викликає процедури і функції для побудови конкретних графіків із встановленими  масштабними коефіцієнтами.

Перед рисуванням наступного графіка математичної функції полотно очищується командою canvas.delete ("all").

Для побудови графіка кожної функції обчислюються власні масштабні коэффициенты, тому їх обчислення включено в код відповідної процедури. Крім того, для графіка потрібні значення координат, тому в кожній процедурі виконуються відповідні перетворення за допомогою функції int().

Для кожного графіка потрібно зобразити осі. Дії по рисуванні осей також винесені в окремі процедури.Виявляється, що програму потрібно читати «з кінця», і писать теж.

Завдання
1. Виконати код програми
2. Зробити скриншоти графіків чотирьох функцій
3. Доповнити код програми коментарями

Запитання
1. Які можливості надає модуль tkinter ?
2. Навіщо потрібно імпортувати модуль math ?
3. Яке призначення функцій plot_x_axe і plot_y_axe ?
4. Яке призначення функції:
    а) plot_func0(x0,x1,dx,y0,y1)
    б) plot_func1(x0,x1,dx,y0,y1)
    в) plot_func2(x0,x1,dx,y0,y1)
    г) plot_func3(x0,x1,dx,y0,y1)
5. З допомогою якої процедури здійснюється остаточна побудова графіка вибраної функції ?
6. З допомогою якого метода здійснюється очищення полотна ?
7. З допомогою якого методу здійснюється кріплення віджета до полотна ?
8. З допомогою якого методу кнопку пов'язують з функцією ?
9. З допомогою якого методу створено випадаючий список ? 
10. Яке призначення має змінна-об'єкт StringVar(tk)?
11. Яке призначення методу set() ?







Комментариев нет:

Отправить комментарий