Рисуем график функции

В этой статье мы рассмотрим несколько способов нарисовать график какой-нибудь функции. Рисовать график мы будем на канве компонента image.

Рисование по пикселам

Рисовать на канве можно разными способами. Первый вариант - рисовать по пикселям. Для этого используется свойство канвы pixels. Это свойство представляет собой двумерный массив, который отвечает за цвета канвы. Например canvas.pixels[10,20] - соответствует цвету пикселя с координатами (10,20). С массивом пикселей можно обращаться, как с любым свойством: изменять цвет, задавая пикселю новое значение, или определять его цвет, по хранящемуся в нем значению. На примере ниже мы зададим черный цвет пикселю с координатами (10,20):


canvas.pixels[10,20]:=clblack;  

Теперь мы попробуем нарисовать график функции f(x), если известен диапазон ее изменений ymax и ymin, и диапазон изменения аргумента xmax и xmin. Для этого мы напишем пользовательскую функцию, которая будет вычислять значение функции f в точке x, а также будет возвращать максимум и минимум функции и ее аргумента.


function tform1.f(x:real; var xmax,xmin,ymax,ymin:real):real;  
begin  
f:=sin(x);  
xmax:=4*pi;  
xmin:=0;  
ymax:=1;  
ymin:=-1;  
end;  

Не забудьте также указать заголовок этой функциии в разделе public:


public  
{ public declarations }  
function f(x:real; var xmax,xmin,ymax,ymin:real):real;  

Здесь для ясности мы просто указали диапазон изменения функции sin(x) и ее аргумента, ниже эта функция будет описана целиком. Параметры xmax, xmin, ymax, ymin - описаны со словом var потому что они являются входными-выходными, т.е. через них функция будет возвращать значения вычислений этих данных в основную программу. Поэтому надо объявить xmax, xmin, ymax, ymin как глобальные переменные в разделе implementation:


implementation  
var xmax,xmin,ymax,ymin:real;  

Теперь поставим на форму кнопку и в ее обработчике события onclick напишем следующий код:


procedure tform1.button1click(sender: tobject);  
var x,y:real;  
px,py:longint;  
begin  
for px:=0 to image1.width do  
begin  
x:=xmin+px*(xmax-xmin)/image1.width;  
y:=f(x,xmax,xmin,ymax,ymin);  
py:=trunc(image1.height-(y-ymin)*image1.height/(ymax-ymin));  
image1.canvas.pixels[px,py]:=clblack;  
end;  
end;  

В этом коде вводятся переменные x и y, являющиеся значениями аргумента и функции, а также переменные px и py, являющиеся координатами пикселей, соответствующих x и y. Сама процедура состоит из цикла по всем значениям горизонтальной координаты пикселей px компонента image1. Сначала выбранное значение px пересчитывается в соответствующее значение x. Затем производится вызов функции f(x) и определяется ее значение y. Это значение пересчитывается в вертикальную координату пикселя py

Рисование с помощью пера pen

У канвы имеется свойство pen - перо. Это объект в свою очередь имеющий ряд свойств. Одно из них свойство color - цвет, которым наносится рисунок. Второе свойство width - ширина линии, задается в пикселах (по умолчанию 1).

Свойство style определяет вид линии и может принимать следующие значения:

pssolid Сплошная линия
psdash Штриховая линия
psdot Пунктирная линия
psdashdot Штрих пунктирная линия
psdashdotdot Линия, чередующая штрих и два пунктира
psclear Отсутствие линии
psinsideframe Сплошная линия, но при width > 1 допускающая цвета, отличные от палитры windows

Все стили со штрихами и пунктирами доступны только при толщине линий равной 1. Иначе эти линии рисуются как сплошные.

У канвы имеется свойство penpos, типа tpoint. Это свойство определяет в координатах канвы текущую позицию пера. Перемещение пера без прорисовки осуществляется методом moveto(x,y). После вызова этого метода канвы точка с координатами (x,y) становится исходной, от которой методом lineto(x,y) можно провести линию, в любую точку с координатами (x,y).

Давайте теперь попробуем нарисовать график синуса пером. Для этого добавим перед циклом оператор:


image1.canvas.moveto(0,image1.height div 2);  

А перед заключительным end цикла добавьте следующий оператор:


image1.canvas.lineto(px,py);  

Таким образом у Вас должен получиться такой код


procedure tform1.button1click(sender: tobject);  
var x,y:real;  
px,py:longint;  
begin  
image1.canvas.moveto(0,image1.height div 2);  
for px:=0 to image1.width do  
begin  
x:=xmin+px*(xmax-xmin)/image1.width;  
y:=f(x,xmax,xmin,ymax,ymin);  
py:=trunc(image1.height-(y-ymin)*image1.height/(ymax-ymin));  
image1.canvas.pixels[px,py]:=clblack;  
image1.canvas.lineto(px,py);  
end;  
end;  

Как Вы уже успели заметить, если запустили программу, качество рисования графика пером, намного лучше, чем рисования по пикселям.

Как обещал сейчас напишу пример программы которая находит максимум и минимум функции. Я маленько изменил структуру процедур и функций, чтобы было яснее. Вот готовый код программы:


...  
type  
tform1 = class(tform)  
button1: tbutton;  
image1: timage;  
procedure button1click(sender: tobject);  
private  
{ private declarations }  
public  
function f(x:real):real;  
procedure extrem1(xmax,xmin:real; var ymin:real);  
procedure extrem2(xmax,xmin:real; var ymax:real);  
{ public declarations }  
end;  
  
var  
form1: tform1;  
  
implementation  
const e=1e-4;//точность одна тысячная  
var xmax,xmin,ymax,ymin:real;  
{$r *.dfm}  
function tform1.f(x:real):real;  
begin  
f:=sin(x);  
end;  
  
//поиск минимума функции  
procedure tform1.extrem1(xmax,xmin:real; var ymin:real);  
var x,h:real; j,n:integer;  
begin  
n:=10;  
repeat  
x:=xmin;  
n:=n*2;  
h:=(xmax-xmin)/n;  
ymin:=f(xmin);  
for j:=1 to n do begin  
if f(x)then ymin:=f(x);  
x:=x+h;  
end;  
until abs(f(ymin)-f(ymin+h))  
end;  
  
//поиск максимума функции  
procedure tform1.extrem2(xmax,xmin:real; var ymax:real);  
var x,h:real; j,n:integer;  
begin  
n:=10;  
repeat  
x:=xmin;  
n:=n*2;  
h:=(xmax-xmin)/n;  
ymax:=f(xmin);  
for j:=1 to n do begin  
if f(x)>=ymax then ymax:=f(x);  
x:=x+h;  
end;  
until abs(f(ymax)-f(ymax+h))  
end;  
  
  
procedure tform1.button1click(sender: tobject);  
var x,y:real;  
px,py:longint;  
begin  
//здесь необходимо указать диапазон изменения x  
xmax:=8*pi;  
xmin:=0;  
  
//вычисляем экстремумы функции  
extrem1(xmax,xmin,ymin);  
extrem2(xmax,xmin,ymax);  
  
//рисуем график функции  
image1.canvas.moveto(0,image1.height div 2);  
for px:=0 to image1.width do  
begin  
x:=xmin+px*(xmax-xmin)/image1.width;  
y:=f(x);  
py:=trunc(image1.height-(y-ymin)*image1.height/(ymax-ymin));  
image1.canvas.pixels[px,py]:=clblack;  
image1.canvas.lineto(px,py);  
end;  
end;  
end.  
Теги:
график функции
Добавлено: 26 Июля 2018 20:58:52 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...