Добавил:
Tushkan
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Курсовой проект Автоколебания в химических реакциях / Исходные коды / MainUnit
.cpp/*---------------------------------------------------------------------------
Курсовая работа "Автоколебания в химических реакциях"
Автор: Захаров А. Е.
Московский Энергетический Институт (Технический Университет), 2011 г.
---------------------------------------------------------------------------*/
#include <vcl.h>
#include <math.h>
#pragma hdrstop
#include "MainUnit.h"
#include "EditUnit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "sPageControl"
#pragma link "sSkinManager"
#pragma link "sLabel"
#pragma link "sBitBtn"
#pragma link "sGroupBox"
#pragma link "sCheckBox"
#pragma link "sPanel"
#pragma link "sSkinProvider"
#pragma link "sUpDown"
#pragma link "sPageControl"
#pragma link "sColorSelect"
#pragma link "sSpeedButton"
#pragma link "acPNG"
#pragma link "sTrackBar"
#pragma link "sRadioButton"
#pragma link "sStatusBar"
#pragma resource "*.dfm"
//---------------------------------------------------------------------------
TMainForm *MainForm;
//---------------------------------------------------------------------------
__fastcall TMainForm::TMainForm(TComponent* Owner) : TForm(Owner)
{
recount();
}
/*--- Заданные функции правых частей системы --------------------------------
* x, y - концентрации реагентов X и Y
*/
double TMainForm::f1(double x, double y)
{
return Options.b * x - x * x * y;
}
double TMainForm::f2(double x, double y)
{
return Options.a - (Options.b + 1) * x + x * x * y;
}
/*--- Поиск численных решений системы методом Рунге-Кутты 3-его порядка -----
* y_prev, x_prev - предыдущие значения функций
* Результат: Значение функции в точке t + h
*/
double TMainForm::y(double x_prev, double y_prev)
{
double k1 = f1(x_prev, y_prev);
double k2 = f1(x_prev + Options.h * Options.b2 * k1, y_prev + Options.h * Options.b2 * k1);
double k3 = f1(x_prev + Options.h * (Options.b31 * k1 + Options.b32 * k2), y_prev + Options.h * (Options.b31 * k1 + Options.b32 * k2));
return y_prev + Options.h * (Options.c1 * k1 + Options.c2 * k2 + Options.c3 * k3);
}
double TMainForm::x(double x_prev, double y_prev)
{
double k1 = f2(x_prev, y_prev);
double k2 = f2(x_prev + Options.h * Options.b2 * k1, y_prev + Options.h * Options.b2 * k1);
double k3 = f2(x_prev + Options.h * (Options.b31 * k1 + Options.b32 * k2), y_prev + Options.h * (Options.b31 * k1 + Options.b32 * k2));
return x_prev + Options.h * (Options.c1 * k1 + Options.c2 * k2 + Options.c3 * k3);
}
/*--- Поиск минимума и максимума в векторе точек функции на плоскости ------
* P - вектор точкек (x,y)
*/
double maxy(vector<point> P)
{
double max = 0;
if(P.size())
{
max = P.front().y;
for(int t = 1; t < P.size(); t++)
if(P[t].y > max) max = P[t].y;
}
return max;
}
double miny(vector<point> P)
{
double min = 0;
if(P.size())
{
min = P.front().y;
for(int t = 1; t < P.size(); t++)
if(P[t].y < min) min = P[t].y;
}
return min;
}
double maxx(vector<point> P)
{
double max = 0;
if(P.size())
{
max = P.front().x;
for(int t = 1; t < P.size(); t++)
if(P[t].x > max) max = P[t].x;
}
return max;
}
double minx(vector<point> P)
{
double min = 0;
if(P.size())
{
min = P.front().x;
for(int t = 1; t < P.size(); t++)
if(P[t].x < min) min = P[t].x;
}
return min;
}
//--- Расчёт задачи --------------------------------------------------------
void TMainForm::recount()
{
double ta = Options.ta;
double tb = Options.tb;
double h = Options.h;
double x0 = Options.x0;
double y0 = Options.y0;
// Коррекция шага
h = (tb - ta) / (int((tb - ta) / h) + 1.);
// Начальные условия
Fpoints[0].clear();
Fpoints[1].clear();
Fpoints[2].clear();
point P1 = {ta, y0};
point P2 = {ta, x0};
point P3 = {y0, x0};
Fpoints[0].push_back(P1);
Fpoints[1].push_back(P2);
Fpoints[2].push_back(P3);
// Поиск точек семейства решений
vector<point> T;
int j = 0, v = -1;
Fpoints2.clear();
for (int i = 0; j < 10; i++)
if(((y0 - 1) + i * 0.2) > 0)
{
if(v == -1)
v = i;
T.clear();
point P = {ta, (y0 - 1) + double(i) * 0.2};
if(fabs(P.y) < 0.00000001)
P.y = 0;
if(fabs(P.y - y0) < 0.00000001)
P.y = y0;
T.push_back(P);
if(Fpoints2.size() < 10)
Fpoints2.push_back(T);
j++;
}
j = 0;
for (int i = v; j < 10; i++)
if(((x0 - 1) + i * 0.2) > 0)
{
T.clear();
point P = {ta, (x0 - 1) + i * 0.2};
if(fabs(P.y) < 0.00000001)
P.y = 0;
if(fabs(P.y - x0) < 0.00000001)
P.y = x0;
T.push_back(P);
if(Fpoints2.size() < 20)
Fpoints2.push_back(T);
j++;
}
for (int i = 0; i < 10; i++)
{
T.clear();
point P = {Fpoints2[i].front().y, Fpoints2[i+10].front().y};
T.push_back(P);
Fpoints2.push_back(T);
}
for(int i = 0; i < 10; i++)
{
int j = 1;
for(double t = ta + h; t <= tb; t = ta + j * h)
{
point P1 = {t, y(Fpoints2[i + 10].back().y, Fpoints2[i].back().y)};
point P2 = {t, x(Fpoints2[i + 10].back().y, Fpoints2[i].back().y)};
point P3 = {P1.y, P2.y};
Fpoints2[i].push_back(P1);
Fpoints2[i + 10].push_back(P2);
Fpoints2[i + 20].push_back(P3);
j++;
}
}
paint();
MainForm->Refresh();
}
/*--- Построение графиков функций на компаненте TImage ---------------------
* Image - указатель на объект типа TImage
* Functions - вектор структур, определяющих точки графиков функции
* и задающих параметры отрисовки графиков (цвет, стиль и т. п.)
* showGrid - определяет, рисовать сетку или нет
* zoom - координата центра области для увеличения
* zoomed - определяет, увеличивать область или нет
*/
void TMainForm::functionPaint(TImage *Image, vector<functionOptions> Functions,
point zoom, bool zoomed = false, bool showGrid = true)
{
int i, j, x, y, labelpos;
vector<point> F;
TColor color;
int width, height, gridNumX, gridNumY, gridStepX, gridStepY;
double minY, maxY, minX, maxX, kx, ky;
minX = minx(Functions.front().points);
maxX = maxx(Functions.front().points);
minY = miny(Functions.front().points);
maxY = maxy(Functions.front().points);
if(minY == maxY)
{
minY = minY - 2;
maxY = maxY + 5;
}
width = Image->Width;
height = Image->Height;
gridNumX = 10;
gridNumY = 16;
gridStepX = width / gridNumX;
gridStepY = height / gridNumY;
kx = double((maxX - minX) / (width - 2 * gridStepX));
ky = double((maxY - minY) / (height - 2 * gridStepY));
if(zoomed)
{
minX = (zoom.x - 2 * gridStepX) * kx;
maxX = zoom.x * kx;
minY = (height - zoom.y - 2.5 * gridStepY)* ky;
maxY = (height - zoom.y + 0.5 * gridStepY)* ky;
kx = double((maxX - minX) / (width - 2 * gridStepX));
ky = double((maxY - minY) / (height - 2 * gridStepY));
}
// Фон
Image->Picture->Bitmap->Height = Image->Height;
Image->Picture->Bitmap->Width = Image->Width;
Image->Canvas->Pen->Color = clBlack;
Image->Canvas->Brush->Color = clWhite;
Image->Canvas->Rectangle(0, 0, width, height);
// Сетка
if(showGrid)
{
Image->Canvas->Pen->Color = clInactiveCaption;
Image->Canvas->Pen->Style = psDot;
for(i = 1; i < gridNumX; i++)
{
Image->Canvas->MoveTo(i * gridStepX, 1);
Image->Canvas->LineTo(i * gridStepX, height - 1);
}
for(i = gridNumY - 1; i >= 1 ; i--)
{
Image->Canvas->MoveTo(1, i * gridStepY);
Image->Canvas->LineTo(width - 1, i * gridStepY);
}
}
Image->Canvas->Pen->Color = clBlack;
Image->Canvas->Pen->Style = psSolid;
for(i = 1; i < gridNumX; i++)
{
Image->Canvas->MoveTo(i * gridStepX, height - gridStepY + 3);
Image->Canvas->LineTo(i * gridStepX, height - gridStepY - 4);
}
for(i = gridNumY - 1; i >= 1 ; i--)
{
Image->Canvas->MoveTo(gridStepX - 3, i * gridStepY);
Image->Canvas->LineTo(gridStepX + 4, i * gridStepY);
}
Image->Canvas->MoveTo(gridStepX - 3, 23); Image->Canvas->LineTo(gridStepX, 10);
Image->Canvas->MoveTo(gridStepX + 3, 23); Image->Canvas->LineTo(gridStepX, 10);
Image->Canvas->LineTo(gridStepX, height - 11);
Image->Canvas->MoveTo(10, (gridNumY - 1) * gridStepY);
Image->Canvas->LineTo(width - 11, (gridNumY - 1) * gridStepY);
Image->Canvas->MoveTo(width - 11, (gridNumY - 1) * gridStepY); Image->Canvas->LineTo(width - 24, (gridNumY - 1) * gridStepY - 3);
Image->Canvas->MoveTo(width - 11, (gridNumY - 1) * gridStepY); Image->Canvas->LineTo(width - 24, (gridNumY - 1) * gridStepY + 3);
Image->Canvas->Pen->Width = 1;
// Масштаб
AnsiString xLabel, yLabel;
Image->Canvas->Pen->Color = clBlack;
Image->Canvas->Brush->Style = bsClear;
Image->Canvas->Font->Color = clBlack;
for(i = (minY != minX) ? 1 : 3; i < gridNumX; i+= 2)
{
xLabel = FloatToStrF(minX + double((fabs(minX) + fabs(maxX)) * (i - 1) / (gridNumX - 2)), ffGeneral, 6, 0);
Image->Canvas->TextOutW(i * gridStepX + 1, height - gridStepY, xLabel);
}
for(i = gridNumY - 1; i >= 1; i-= 2)
{
yLabel = FloatToStrF(maxY - double((maxY - minY) * (i - 1) / (gridNumY - 2)), ffGeneral, 6, 0);
Image->Canvas->TextOutW(gridStepX - 6.5 * strlen(yLabel.c_str()), i * gridStepY + 1, yLabel);
}
// Графики функций
for(i = 0; i < Functions.size(); i++)
{
if(Functions[i].enabled)
{
F = Functions[i].points;
color = Functions[i].color;
AnsiString label = Functions[i].label;
labelpos = Functions[i].labelpos;
Image->Canvas->Pen->Color = color;
Image->Canvas->Brush->Color = color;
Image->Canvas->Font->Color = color;
for(j = 0; j < F.size(); j++)
{
x = gridStepX + (F[j].x - minX) / kx;
y = height - gridStepY - (F[j].y - minY) / ky;
if (Functions[i].style == psDot)
Image->Canvas->Ellipse(x - 3, y - 3, x + 3, y + 3);
else
{
if (j == 0)
Image->Canvas->MoveTo(x, y);
else
Image->Canvas->LineTo(x, y);
}
if (label != ' ' && labelpos <= j * 100 / F.size())
{
Image->Canvas->Brush->Style = bsClear;
Image->Canvas->TextOutW(x + 15, y + 5, label);
Image->Canvas->Brush->Color = color;
Image->Canvas->MoveTo(x, y);
label = ' ';
}
}
}
}
// Область для увеличения
if(zoom.x > 0 && zoom.y > 0 && !zoomed)
{
Image->Canvas->Brush->Style = bsClear;
Image->Canvas->Pen->Color = clSkyBlue;
Image->Canvas->Pen->Width = 2;
Image->Canvas->Rectangle(zoom.x - gridStepX, zoom.y - 1.5 * gridStepY, zoom.x + gridStepX, zoom.y + 1.5 * gridStepY);
Image->Canvas->Pen->Width = 1;
Image->Cursor = crCross;
}
else
Image->Cursor = crDefault;
Image->Refresh();
}
//---------------------------------------------------------------------------
void TMainForm::addFunction(vector<functionOptions> &F, vector<point> P, TColor C, bool enabled = true, TPenStyle style = psDash, AnsiString label = ' ', int labelpos = 0)
{
functionOptions O;
O.points = P;
O.color = C;
O.label = label;
O.labelpos = labelpos;
O.enabled = enabled;
O.style = style;
F.push_back(O);
}
//--- Перерисовка графиков функций для заданных точек -----------------------
void TMainForm::paint()
{
vector<functionOptions> F;
if(sRadioButton1->Checked)
{
for (int i = 0; i < 10; i++)
addFunction(F, Fpoints2[i], (Fpoints2[i].front().y != Options.y0) ? sColorSelect1->ColorValue : clGreen, (Options.show_all || Fpoints2[i].front().y == Options.y0));
addFunction(F, Fpoints[0], clBlack, true, psDot);
}
if(sRadioButton2->Checked)
{
for (int i = 10; i < 20; i++)
addFunction(F, Fpoints2[i], (Fpoints2[i].front().y != Options.x0) ? sColorSelect1->ColorValue : clGreen, (Options.show_all || Fpoints2[i].front().y == Options.x0));
addFunction(F, Fpoints[1], clBlack, true, psDot);
}
if(sRadioButton3->Checked)
{
for (int i = 20; i < 30; i++)
addFunction(F, Fpoints2[i], (Fpoints2[i].front().y != Options.x0 && Fpoints2[i].front().x != Options.y0) ? sColorSelect1->ColorValue : clGreen, (Options.show_all || (Fpoints2[i].front().y == Options.x0 && Fpoints2[i].front().x == Options.y0)));
}
if(sRadioButton1->Checked || sRadioButton2->Checked || sRadioButton3->Checked)
functionPaint(Image1, F, zoom, zoomed, Options.show_grid);
}
//--- Открыть окно настроек программы ------------------------------------------------------------------------
void __fastcall TMainForm::sBitBtn1Click(TObject *Sender)
{
Application->CreateForm(__classid(TEditForm1), &EditForm1);
EditForm1->ShowModal();
}
//--- Выбор графиков для отображения ----------------------------------------
void __fastcall TMainForm::check(TObject *Sender)
{
paint();
}
//--- Область для увеличения графика ----------------------------------------
void __fastcall TMainForm::Image1MouseMove(TObject *Sender, TShiftState Shift, int X,
int Y)
{
if(!zoomed)
{
zoom.x = X;
zoom.y = Y;
sStatusBar1->Panels->Items[0]->Text = " Щёлкните мышью, чтобы увеличить график";
paint();
}
else
sStatusBar1->Panels->Items[0]->Text = " Щёлкните мышью, чтобы уменьшить график";
}
void __fastcall TMainForm::Image1MouseLeave(TObject *Sender)
{
if(!zoomed)
{
zoom.x = zoom.y = 0;
paint();
}
sStatusBar1->Panels->Items[0]->Text = " Курсовая работа \"Автоколебания в химических реакциях\"";
}
void __fastcall TMainForm::Image1Click(TObject *Sender)
{
zoomed = !zoomed;
paint();
}
//--- Смена цвета графиков функций ------------------------------------------
void __fastcall TMainForm::sColorSelectChange1(TObject *Sender)
{
paint();
}
void __fastcall TMainForm::sColorSelect1MouseEnter(TObject *Sender)
{
sStatusBar1->Panels->Items[0]->Text = " Нажмите, чтобы изменить цвет графиков функций";
}
void __fastcall TMainForm::sColorSelect1MouseLeave(TObject *Sender)
{
sStatusBar1->Panels->Items[0]->Text = " Курсовая работа \"Автоколебания в химических реакциях\"";
}
//---------------------------------------------------------------------------
Соседние файлы в папке Исходные коды