012 – Розробка програми рисування графіка функції однієї змінної. Функція задана формулою

Розробка програми рисування графіка функції однієї змінної. Функція задана формулою

Наводиться приклад рисування на канві графіка функції однієї змінної

y = f(x)

Функція задається формулою.

 

Умова задачі

Розробити додаток, в якому будується графік функції

y = sin(x)

Графік функції повинен виводитись у окремій формі.

 

Математична постановка задачі

Для побудови будь-якого графіка функції y = f(x) потрібно задати прямокутну область екрану, в якій цей графік функції буде виводитись.

Прямокутна область екрану задається координатами крайніх точок (рис. 1):

– (x1; y1) – лівий верхній кут екрану;

– (x2; y2) – правий нижній кут екрану.

05_01_00_012_01_Рис. 1. Прямокутна область екрану

При побудові графіків функцій на екрані монітору потрібно здійснювати масштабування прямокутника з координатами (x1; y1), (x2; y2) в прямокутник з координатами екрану (xx1; yy1), (xx2; yy2) як зображено на рисунку 2.

05_01_00_012_02u

Рис. 2. Масштабування графіків

Масштабування по осях OX та OY реалізується з допомогою лінійних залежностей:

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

 

Розв’язок

1. Завантажити Borland C++ Builder.

 

Створити проект як “VCL Form Application”. Автоматично створюється основна форма додатку з іменем Form1.

Зберегти проект.

 

2. Побудова основної форми.

Розмістити на формі компоненти таких типів:

  • п’ять компонент типу TLabel. Створюються об’єкти з іменами Label1, Label2, Label3, Label4, Label5;
  • п’ять компонент типу TEdit. Створюються об’єкти з іменами Edit1, Edit2, Edit3, Edit4, Edit5;
  • один компонент типу TButton. Створюється об’єкт з іменем Button1.

Відкорегувати позиції компонент на формі так як показано на рисунку 3.

05_01_00_012_03_

Рис. 3. Розміщення компонент на формі Form1

3. Налаштування форми.

Щоб форма Form1 мала коректний вигляд, в Object Inspector потрібно зробити наступне:

  • з вкладки Action встановити властивість Caption = “Графік функції однієї змінної” (заголовок форми);
  • з вкладки Visual встановити властивість BorderStyle = “bsDialog” (рис. 4). У результаті зникнуть кнопки управління формою;
  • з вкладки Miscellaneous встановити властивість Position = “poScreenCenter” (рис. 5). Ця дія відобразить форму в центрі екрану під час виконання додатку.

05_01_00_012_04_

Рис. 4. Властивість BorderStyle форми Form1

05_01_00_012_05_

Рис. 5. Властивість Position

 

4. Налаштування властивостей та розмірів компонент, розміщених на формі.

Потрібно здійснити налаштування таких властивостей компонент:

  • у компоненті Label1 властивість Caption = ” К-сть точок по горизонталі, n =“;
  • у компоненті Label2 властивість Caption = ” Ліва межа, x1 =“;
  • у компоненті Label3 властивість Caption = “ Права межа, x2 =“;
  • у компоненті Label4 властивість Caption = “ Верхня межа, y1 = “;
  • у компоненті Label5 властивість Caption = ” Нижня межа, y2 =“;
  • у компоненті Button1 властивість Caption = “ Вивести графік …“.

Також потрібно змінити розмір і позицію компонента Button1 на формі. Приблизний вигляд форми з розміщеними компонентами зображено на рисунку 6.

05_01_00_012_06u

Рис. 6. Загальний вигляд форми Form1

 

5. Програмування події активізації форми Form1.

Під час запуску додатку на виконання необхідно запрограмувати подію OnActivate активізації основної форми додатку.

Приклад програмування події в C++ Builder описується тут.

Лістинг обробника події OnActivate має наступний вигляд:

void __fastcall TForm2::FormActivate(TObject *Sender)
{
     Edit1->Text = "30";
     Edit2->Text = "-5";
     Edit3->Text = "5";
     Edit4->Text = "-2";
     Edit5->Text = "2";
     Edit1->SetFocus(); // встановити фокус введення в Edit1
}

У обробнику події заповнюються значення полів, які є координатами прямокутної області екрану в якій виводиться графік. Прямокутна область екрану задається координатами лівого верхнього кута (x1; y1) та правого нижнього кута (x2; y2).

6. Створення нової форми виведення графіку функції.

Створити форму з іменем “Form2” за зразком, як показано на рисунку 7. Приклад створення нової форми у C++ Builder наведено тут.

Форма Form2 описується в файлах “Unit2.h” та “Unit2.cpp”.

Розмістити на формі компоненти таких типів:

– компонент типу TButton (кнопка). Автоматично створюється об’єкт з іменем Button1;

– компонент типу TImage. Створюється об’єкт з іменем Image1. У цьому компоненті буде виводитись графік функції sin(x).

05_01_00_012_07_

Рис. 7. Форма Form2 виведення графіку функції sin(x)

З допомогою Object Inspector здійснити налаштування основних властивостей компонент:

  • у компоненті Button1 властивість Caption = “OK”;
  • у компоненті Button1 властивість ModalResult = “mrOk“. Це означає, що під час кліку на кнопці Button1 форма буде закриватись з кодом повернення mrOk.


З допомогою Object Inspector здійснити налаштування властивостей форми Form2:

– з вкладки Action встановити властивість Caption = “Графік функції sin(x)“;

– з вкладки Visual властивість BorderStyle = “bsDialog”. Це означає, що вікно форми прийме вигляд діалогового вікна;

– з вкладки Miscellaneous властивість Position = “poScreenCenter”. У результаті форма буде виводитись в центрі екрану.

Також потрібно відкоригувати розміри та позиції компонентів Button1 та Image1.

У результаті виконаних дій, форма Form2 буде мати вигляд, як зображено на рисунку 8

05_01_00_012_08u

Рис. 8. Форма Form2

 

7. Програмування допоміжних функцій масштабування та обчислення sin(x).
7.1. Ввід внутрішніх змінних у модуль форми Form2.

Потрібно ввести наступні внутрішні змінні у текст модуля “Unit2.h” (рис. 9).

Для цього виконується така послідовність дій.

  1. Перейти у заголовочний файл “Unit2.h” (рис. 9).
  1. У розділі private класу TForm2 ввести чотири змінні:
int xx1, xx2, yy1, yy2;

Ці змінні відповідають екранним координатам (див. рис. 2 б).

  1. У розділі public класу TForm2 ввести п’ять змінних:
float x1, x2, y1, y2;
int n;

Ці змінні відповідають фактичним координатам (рис. 2 а) прямокутної області, в якій виводиться графік. Змінна n задає кількість точок, що будуть з’єднані лініями. Чим більше значення n, тим плавніше виглядає графік на екрані.

Значення цих змінних заповнюється з основної форми Form1. Тому вони розміщуються в розділі public.

05_01_00_012_09_

Рис. 9. Вигляд файлу модуля “Unit2.h”

Поки що лістинг файлу “Unit2.h” наступний:

//------------------------------------------------
#ifndef Unit2H
#define Unit2H
//------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>
//------------------------------------------------

class TForm2 : public TForm
{
__published:  // IDE-managed Components
     TImage *Image1;
     TButton *Button1;

private: // User declarations
     int xx1, xx2, yy1, yy2;

public:       // User declarations
     __fastcall TForm2(TComponent* Owner);
     float x1, x2, y1, y2; // фактичні координати прямокутної області
     int n;  // кількість точок, які з'єднуються лініями
};

//--------------------------------------------------
extern PACKAGE TForm2 *Form2;
//--------------------------------------------------
#endif

 

7.2. Додавання функцій перетворення та функції обчислення у клас TForm2.

У модулі форми Form2 потрібно створити дві функції перетворення фактичних координат в екранні координати. Функції мають імена ZoomX() та ZoomY().

Також потрібно додати функцію обчислення sin(x). Ім’я цієї функції func().

Спочатку додається опис функцій в модуль “Unit2.h”. Опис додається в розділ public.

Фрагмент лістингу файлу “Unit2.h” буде мати наступний вигляд:

...

class TForm2 : public TForm
{
__published:  // IDE-managed Components
     TImage *Image1;
     TButton *Button1;

private: // User declarations
     int xx1, xx2, yy1, yy2;

public:       // User declarations
     __fastcall TForm2(TComponent* Owner);
     float x1, x2, y1, y2;
     int n;
     int ZoomX(float x);
     int ZoomY(float y);
     float func(float x);
};

...

Наступним кроком потрібно перейти в файл “Unit2.cpp” (рис. 10). У цьому файлі описується реалізація класу TForm2.

У кінець файлу додається такий програмний код:

int TForm2::ZoomX(float x)
{
     int ret;
     ret = xx1 + (int)((x-x1)*(xx2-xx1)/(x2-x1));
     return ret;
}

int TForm2::ZoomY(float y)
{
     int ret;
     ret = yy2 + (int)((y-y1)*(yy1-yy2)/(y2-y1));
     return ret;
}

float TForm2::func(float x)
{
     float ret;
     ret = sin(x); // функція, для якої будується графік
     return ret;
}

У наведеному вище лістингу функції ZoomX() та ZoomY() отримують вхідними параметрами відповідно значення x та y, які є фактичними координатами. Потім здійснюється перетворення за формулами, які наведені у математичній постановці задачі.

Функція func() отримує вхідним параметром значення у локальній змінній x. У тілі функції обчислюється значення sin(x). У це місце можна вставити будь-яку іншу власну функцію.

05_01_00_012_10_Рис. 10. Файл “Unit2.cpp” з введеними функціями ZoomX(), ZoomY() та func()

На даний момент лістинг файлу Unit2.cpp наступний:

//-------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Unit2.h"
#include <math.h>

//-------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

TForm2 *Form2;

//-------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
     : TForm(Owner)
{
}

//-------------------------------------------------------

int TForm2::ZoomX(float x)
{
     int ret;
     ret = xx1 + (int)((x-x1)*(xx2-xx1)/(x2-x1));
     return ret;
}

int TForm2::ZoomY(float y)
{
     int ret;
     ret = yy2 + (int)((y-y1)*(yy1-yy2)/(y2-y1));
     return ret;
}

float TForm2::func(float x)
{
     float ret;
     ret = sin(x);
     return ret;
}

Щоб використовувати функцію sin(x), у файлі (модулі) “Unit2.cpp” додається рядок

#include <math.h>

У цьому рядку підключається бібліотека стандартних математичних функцій. У цій бібліотеці є функція обчислення sin(x).

 

8. Програмування події активізації форми Form2.

Графік функції виводиться у формі Form2 одразу після кліку на кнопці “Вивести графік…” форми Form1. Тому, доцільно запрограмувати виведення графіку у події OnActivate форми Form2. Обробник події реалізований у файлі “Unit2.cpp”.

Лістинг обробника події OnActivate форми Form2 наступний:

void __fastcall TForm2::FormActivate(TObject *Sender)
{
     TCanvas * canv; // додаткова змінна
     int tx, ty;
     int i;
     float x, y, h;

     canv = Image1->Canvas;

     // 1. Задавання меж екранних координат
     xx1 = 0;
     yy1 = 0;
     xx2 = Image1->Width;
     yy2 = Image1->Height;

     // 2. Рисування графіку
     canv->Pen->Color = clBlue;
     canv->Brush->Color = clWhite;
     canv->Rectangle(0, 0, Image1->Width, Image1->Height);

     // 2.1. Побудова осей координат
     canv->Pen->Color = clBlack;

     // 2.2. Взяти екранну точку початку координат X
     tx = ZoomX(0);
     ty = ZoomY(y1);
     canv->MoveTo(tx,ty);

     // провести лінію осі координат X
     tx = ZoomX(0);
     ty = ZoomY(y2);
     canv->LineTo(tx,ty);

     // 2.3. Точка початку координат Y
     canv->Pen->Color = clBlack;
     tx = ZoomX(x1);
     ty = ZoomY(0);
     canv->MoveTo(tx,ty);

     // нарисувати вісь Y
     tx = ZoomX(x2);
     ty = ZoomY(0);
     canv->LineTo(tx,ty);

     // 3. Рисування графіка функції
     canv->Pen->Color = clRed; // колір
     canv->Pen->Width = 2; // товщина лінії

     // координати першої точки
     x = x1;
     y = func(x);
     h = (x2-x1)/n;
     tx = ZoomX(x);
     ty = ZoomY(y);
     canv->MoveTo(tx,ty);

     // цикл перебору точок і рисування з'єднувальних ліній
     for (i = 0; i < n; i++)
     {
         x = x + h;
         y = func(x);
         tx = ZoomX(x);
         ty = ZoomY(y);
         canv->LineTo(tx,ty);
     }
}

У скороченому вигляді файл “Unit2.cpp” має вигляд:

#include <vcl.h>
#pragma hdrstop

#include "Unit2.h"
#include <math.h>

//-----------------------------------------------------------

#pragma package(smart_init)
#pragma resource "*.dfm"

TForm2 *Form2;

//-----------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
     : TForm(Owner)
{
}
//----------------------------------------------------------

int TForm2::ZoomX(float x)
{
     ...
}

int TForm2::ZoomY(float y)
{
     ...
}

float TForm2::func(float x)
{
     ...
}

void __fastcall TForm2::FormActivate(TObject *Sender)
{
     ...
}
//--------------------------------------------------------------

 

9. Програмування події кліку на кнопці “Вивести графік…” форми Form1.

Останнім етапом є програмування події кліку на кнопці виведення графіку.

Для цього потрібно виконати такі дії.

9.1. Підключення форми Form2 до форми Form1.

Приклад створення нової форми та виклику її з основної форми програми детально описується тут.

Щоб підключити форму Form2 до форми Form1 потрібно у верхній частині файлу “Unit1.cpp” потрібно додати рядок:

#include "Unit2.h"

Після цього методи класу TForm2 стають доступними з форми Form1.

Поки що лістинг файлу “Unit2.cpp” наступний:

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "Unit2.h"
//---------------------------------------------------------------

#pragma package(smart_init)
#pragma resource "*.dfm"

TForm1 *Form1;

//---------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
     : TForm(Owner)
{
}

//---------------------------------------------------------------
void __fastcall TForm1::FormActivate(TObject *Sender)
{
     Edit1->Text = "30";
     Edit2->Text = "-5";
     Edit3->Text = "5";
     Edit4->Text = "-2";
     Edit5->Text = "2";
     Edit1->SetFocus(); // встановити фокус введення в Edit1
}

//---------------------------------------------------------------

 

9.2. Програмування події кліку на кнопці “Вивести графік…“.

Обробник події Button1Click() кліку на кнопці “Вивести графік…” наступний:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
     Form2->n = StrToInt(Edit1->Text);
     Form2->x1 = StrToFloat(Edit2->Text);
     Form2->x2 = StrToFloat(Edit3->Text);
     Form2->y1 = StrToFloat(Edit4->Text);
     Form2->y2 = StrToFloat(Edit5->Text);
     Form2->ShowModal();
}

У обробнику формуються змінні n, x1, x2, y1, y2.

 

10. Запуск додатку на виконання.

Після цього можна запускати додаток на виконання (рис. 11).

05_01_00_012_11u

Рис. 11. Результат роботи додатку