Редкая
научная работа обходится без графиков, поскольку график наглядно
показывает поведение исследуемой величины. Для построения графиков
можно использовать два подхода. В первом случае график строится по
точкам на поверхности, на которую программа может осуществлять вывод
графики. Этой поверхности соответствует объект Canvas. Свойство
Pixels, представляющее собой двумерный массив типа TColor, содержит
информацию о цвете каждой точки графической поверхности. Используя
свойство Pixels, можно задать цвет любой точки, т.е. например,
нарисовать красную точку по команде
Canvas->Pixels[10][10]=clRed;
Размер массива Pixels определяется реальным размером графической
поверхности формы, которая в свою очередь зависит от свойств
ClientWidth и ClientHeigth, а размер графической поверхности
компонента Image определяется свойствами Width и Height. Левой
верхней точке рабочей области формы соответствует элемент
Pixels[0][0], а правой нижней-Pixels[ClientWidth-1][ClientHeght-1].
Текст программы рисующей график функции y=2*sin(x)*exp(x/5) приведен
на листинге
/*
Строит график функции.
Демонстрирует:
- использование методов Line, MoveTo, TextOutA;
- обработку события OnFormResize
*/
#include <vcl.h>
#pragma hdrstop
#include "grf_.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
void __fastcall TForm1::FormPaint(TObject *Sender)
{
Grafik();
}
// пользователь изменил размер окна
void __fastcall TForm1::FormResize(TObject *Sender)
{
TRect rct = Rect(0,0,ClientWidth,ClientHeight);
Canvas->FillRect(rct);
Grafik();
}
#include "math.h" // для доступа к sin и exp
// функция, график которой надо построить
float f( float x)
{
return 2*sin(x)*exp(x/5);
}
void TForm1::Grafik()
{
float x1, x2; // границы изменения аргумента функции
float y1, y2; // границы изменения значения функции
float x; // аргумент функции
float y; // значение функции в точке x
float dx; // приращение аргумента
int l,b; // левый нижний угол области вывода графика
int w, h; // ширина и высота области вывода графика
float mx, my; // масштаб по осям X и Y
int x0, y0; // начало координат
// область вывода графика
l = 10; // X - координата левого верхнего угла
b = Form1->ClientHeight-20; // Y - координата левого нижнего угла
h = Form1->ClientHeight-40; // высота
w = Form1->Width - 20; // ширина
x1 = 0; // нижняя граница диапазона аргумента
x2 = 25; // верхняя граница диапазона аргумента
dx = 0.01; // шаг аргумента
// найдем максимальное и минимальное значение
// функции на отрезке [x1,x2]
x = x1;
y1 = f(x); // минимум
y2 = f(x); // максимум
do {
y = f(x);
if ( y < y1 ) y1 = y;
if ( y > y2 ) y2 = y;
x += dx;
} while (x <= x2);
// вычислим масштаб
my = (float)h/abs(y2-y1); // масштаб по оси Y
mx = w/abs(x2-x1); // масштаб по оси X
// оси
x0 = l+abs(x1*mx);
y0 = b-abs(y1*my);
Canvas->MoveTo(x0,b);Canvas->LineTo(x0,b-h);
Canvas->MoveTo(l,y0);Canvas->LineTo(l+w,y0);
Canvas->TextOutA(x0+5,b-h,FloatToStrF(y2,ffGeneral,6,3));
Canvas->TextOutA(x0+5,b,FloatToStrF(y1,ffGeneral,6,3));
// построение графика
x = x1;
do {
y = f(x);
Canvas->Pixels[x0+x*mx][y0-y*my] = clRed;
x += dx;
} while (x <= x2);
}
В раздел private: заголовочного файла необходимо поместить
объявление функции Grafik().
Для построения более сложных графиков используется компонента Chart,
которая находится на странице Additional. Компонента позволяет
строить различные диаграммы и графики и имеет множество свойств,
методов и событий. Компонент является контейнером объектов Series
серий данных. Каждый компонент может включать несколько серий.
Каждая серия соответствует одной кривой на графике. Для определения
вида графика вызывается редактор диаграмм, который появляется при
двойном щелчке на компоненте Chart. В закладке Series с помощью
кнопки Add добавляются серии и затем определяется тип графика,
например, Line. Затем пишется код, задающий данные, которые нужно
отобразить. Для задания отображаемых значений используют три
основных метода серий:
Clear- очищает серию от занесенных ранее данных.
Метод long int Add (const double AValue, const String ALabel, TColor
AColor) позволяет добавить в диаграмму новую точку. Параметр AValue
соответствует добавляемому значению, параметр ALabel –названию,
которое будет отображаться на диаграмме и в легенде, AColor- цвету.
Параметр ALabel- не обязательный, его можно задать пустым-“”.
Метод long int AddXY(const double AValue, const String ALabel,
TColor AColor) позволяет добавить новую точку в график функции.
Таким образом, для построения графиков функций синуса и косинуса
текст программы будет выглядеть так
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include "math.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
const Pi=3.14159;
Series2->Clear();
Series3->Clear();
for(int i=0;i<=100;i++)
{
Series2->AddXY(0.02*Pi*i,sin(0.02*Pi*i),"",clRed);
Series3->AddXY(0.02*Pi*i,cos(0.02*Pi*i),"",clBlue);
}
}
Отметим директиву #include "math.h" необходимую для подключения
функций синуса и косинуса из библиотеки.
Усложним задачу требованием, чтобы построенный график был сохранен в
виде файла. При сохранении графика в файл необходимо выбрать формат.
Компонент Chart позволяет сохранять картинку в bmp-формате. Для
этого в программу необходимо после цикла добавить строку
Form1->Chart1->SaveToBitmapFile("proba.bmp");
Имя файла, конечно , выбирается произвольное и при такой записи файл
будет сохранен в тот же каталог, в котором находится сама программа.
Посмотрев каталог, можно увидеть, что картинка будет размером в 400
Кб, что явно многовато. При работе в интернете графические файлы
предпочитают передавать в более компактном виде по jpg-формату.
Покажем, как преобразовать полученный bmp-файл в jpg-файл. Для этого
в заголовочный файл необходимо подключить библиотеку директивой
#include <jpeg.hpp> и в конец программы добавить следующий текст
Graphics::TBitmap *bitmapa=new Graphics::TBitmap();
TJPEGImage *jpg=new TJPEGImage();
bitmapa->LoadFromFile("proba.bmp");
jpg->Assign(bitmapa);
jpg->CompressionQuality=20;
jpg->Compress();
jpg->SaveToFile("789.jpg");
delete jpg;
delete bitmapa;
Параметр сжатия 20 дает файл размером 7 Кб, имя файла разумеется
произвольное и файл записывается в тот же каталог.