Informatica / lab_delphi / Gr
.docЛабораторная работа
Построение графика функции
в Delphi
Задание
Создать проект приложения, предназначенного для построения на экране дисплея графика функции y=f(x) на отрезке . Функция y=f(x) задается в виде подпрограммы-функции. Пользователь должен ввести значения a, b и параметра n, определяющего детальность и гладкость прорисовки графика.
Вид формы приведен на рисунке ниже.
В данном проекте используются 4 объекта Label для вывода сообщений, 3 объекта Edit для ввода значений a, b и n, и кнопки Button и BitBtn в контейнере Panel. Компонент Image помещен в рамку Bevel.
Теоретическая часть
Для рисования на экране графических объектов и фигур используется компонент TImage (группа Additional). На форме этот элемент представлен как прямоугольник, имеющий размеры Image1.Width (ширина) и Image1.Height (высота). Полезным свойством компонента TImage является Canvas (Канва, или Холст), которое включает, в частности, свойства Pen (Перо) и Brush (Кисть). Canvas (Канва) имеет методы MoveTo (используется для перемещения невидимого графического курсора в заданную точку) и LineTo (позволяет рисовать отрезок прямой, соединяющей точку текущего положения курсора с заданной точкой). Эти методы и будем использовать для рисования графика функции y=f(x) в виде ломаной, состоящей из n звеньев. Задавая достаточно большое значение n, мы получим на экране достаточно гладкую кривую.
При рисовании линий координаты точек нужно задавать в пикселях в экранной системе координат элемента TImage. Начало этой системы координат находится в левом верхнем углу прямоугольника, ось Ox направлена горизонтально слева направо, а ось Oy – горизонтально сверху вниз. Поэтому при построении графика необходимо выполнить пересчет физических координат (x,y) в экранные (X,Y). Формулы пересчета выглядят следующим образом
X=Mx*x+Nx, Y=My*y+Ny, где значения коэффициентов Mx, My, Nx, Ny определяются областью изменения исследуемой функции y=f(x) и аргумента x, т.е. зависят от значений a, b, , и должны вычисляться в программе.
В качестве примера рассмотрим расчет значений Mx и Nx, если a < 0 <b .
Xn Xk X
a 0 b x
Mx и Nx можно найти, исходя из того, что должны выполниться соотношения
,
где Xn и Xk – экранные координаты левой и правой границы области, отведенной для графика.
Эти соотношения приводят к системе уравнений
для определения значений Mx и Nx.
Решая эту систему, найдем
Формулы для определения значений Mx, My, Nx и Ny для других возможных соотношений [0 и {a, b}] и [0 и {ymin, ymax}] выводятся аналогично.
Указания к выполнению работы
1. Значения величин a и b могут быть действительными числами. Поэтому зададим общий обработчик событий OnKeyPress в строчных редакторах Edit1 и Edit2 в виде
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
if Key=#13 then
if Sender= Edit1 then Form1.ActiveControl:=Edit2
else Form1.ActiveControl:=Edit3;
if not (Key in ['0'..'9','-',',','E','e',#8]) then Key:=#0
end;
Таким образом, мы вводим фильтр, ограничивающий ввод символов цифрами, знаком ‘-‘, разделителем ‘,’ (запятая) для ввода дробей, символа #8 (Backspace) и символов ‘E’ и ‘e’ для возможности задания значений a и b в форме чисел с плавающей точкой.
При нажатии клавиши Enter ( #13) , будет передаваться фокус на следующий объект.
Аналогично нужно задать обработчик событий OnKeyPress в строчном редакторе Edit3 для ввода значений n, учтя при этом, что n – натуральное число, а после нажатия клавиши Enter нужно перейти на кнопку Button1 (Расчет).
2. Для вывода текста на рисунке используйте процедуру TextOut(x,y,'Text') (Здесь x,y – экранные координаты положения точки вывода, а ‘Text’ – выводимый текст).
Построение графика реализовать как обработчик события OnClick кнопки Button1 (Расчет). Ниже приведен текст соответствующей процедуры.
procedure TForm1.Button1Click(Sender: TObject);
var a,b:real;
n,nx,ny,xm,ym,xn,xk,yn,yk:integer;
mx,my:real;
x,y,ymax,ymin,h:real;
xi,yi,i:integer;
function f(x:real):real;
begin
f:=sin(x)
end;
begin
{Прорисовка фона рисунка}
Image1.Canvas.Brush.Color:=clWhite;
Image1.Canvas.Rectangle(0,0,xm,ym);
n:=StrToInt(Edit3.Text);
a:=StrToFloat(Edit1.Text); b:=StrToFloat(Edit2.Text);
{Проверка выполнения условия a<b }
if a>=b then
begin
Label4.Caption:='Введите a<b !';
Image1.Canvas.Rectangle(0,0,xm,ym); exit
end
else Label4.Caption:=' ' ;
xm:=Image1.Width; ym:=Image1.Height;
xn:=10; xk:=xm-xn ; yn:=10;yk:=ym-yn;
{Определение диапазона изменения функции [ymin,ymax] }
x:=a; h:=(b-a)/n; ymax:=f(a); ymin:=f(a);
for i:=1 to n do
begin
x:=x+h; y:=f(x);
if y>ymax then ymax:=y;
if y<ymin then ymin:=y
end;
{ Вычисление коэффициентов пересчета координат }
if a>=0 then
begin
nx:=xn;mx:=(xk-xn)/b
end;
if b<=0 then
begin
mx:=(xn-xk)/a ; nx:= xk
end;
if (a<0)and(b>0) then
begin
mx:=(xk-xn)/(b-a) ; nx:=xn-round(mx*a)
end;
if ymin>=0 then
begin
my:= (yn-yk)/ymax; ny:= yk
end;
if ymax<=0 then
begin
my:=(yk-yn)/ymin ; ny:= 10
end;
if (ymin<0)and(ymax>0) then
begin
my:=(yk-yn)/(ymin-ymax) ; ny:= yn-round(my*ymax)
end;
{Задание параметров карандаша для прорисовки осей}
Image1.Canvas.Pen.Color:=clBlack;
Image1.Canvas.Pen.Width:=1;
{Прорисовка осей}
Image1.Canvas.MoveTo(xn,ny);
Image1.Canvas.LineTo(xk,ny); Image1.Canvas.TextOut(xk,ny,' x ') ;
Image1.Canvas.MoveTo(nx,yn);
Image1.Canvas.LineTo(nx,yk); Image1.Canvas.TextOut(nx,yn,' y ') ;
{Задание параметров карандаша для прорисовки графика }
Image1.Canvas.Pen.Color:=clRed;
Image1.Canvas.Pen.Width:=2;
{Рисование графика}
x:=a;y:=f(x);
xi:=nx+round(mx*x); yi:=ny+round(my*y);
Image1.Canvas.MoveTo(xi,yi);
for i:=1 to n do
begin
x:=x+h; y:=f(x);
xi:=nx+round(mx*x); yi:=ny+round(my*y);
Image1.Canvas.LineTo(xi,yi);
end;
end;