Откройте файл ChildView.cpp, который содержит
коды реализации методов класса CChildView. Его
имя содержит ложный намек на происхождение от
CView. На самом деле он происходит от класса
CWnd и инкапсулирует функциональность окна,
оккупирующего клиентскую область окна рамки,
которое управляется классом CMainFrame. Простое
окно, как вы помните, для перерисовки своего
содержимого, вместо метода OnDraw использует
метод OnPaint. Найдите этот метод в классе
CChildView и убедитесь, что в нем контекст
устройства создается, а не приходит в качестве
параметра от каркаса приложения, как это было в
приложениях, поддерживающих архитектуру документ
— представление. Вставьте внутрь этого метода
вызов конструктора класса CGraph с последующим
сообщением Draw:
void
CChildView::OnPaint() {
CPaintDC dc(this);
CGraph(m_Points,
"Field Distribution", "x[m]","Field").Draw(&dc);
}
Класс CGraph разработаем позже. Он будет
создавать двухмерный график функции — решения
краевой задачи, автоматически масштабируемый и
подстраивающийся под текущий размер окна
CChildView. Перейдите к файлу с определением
оконного класса (ChildFrame.h) и введите
следующие коррективы:
# pragma once
#include
"Graph.h"
Class
CChildView : public CWnd
{
// Вспомогательные классы будут пользоваться
данными
friend class
CParamDlg;
friend class
CGraph;
private:
//=====
Контейнер координат точек графика
vector<CDPoint> m_Points;
//===== Вектор источников и свойств среды (см. f
и р)
vector<double>
m_f, m_r;
//===== Размерность задачи (см. N)
int
m_n;
//===== Параметры
double
m_k, // Коэффициент
k
m_L, //
Протяженность расчетной области
m_g0, // Коэффициенты, задающие ГУ слева
m_d0,
m_gn, //
Коэффициенты, задающие ГУ справа m_dn ;
CParamDlg *m_pDlg;
// Немодальный диалог параметров
public:
CChildView();
virtual
-CChildViewO;
virtual
BOOL PreCreateWindow(CREATESTRUCT& cs);
//===== Изменение размерности задачи
void
Resize();
//===== Решение системы методом прогонки
void
Solve();
protected:
afx_msg void
OnPaint();
DECLARE_MESSAGE_MAP()
};
Точки графика будем хранить в контейнере
объектов класса CDPoint, который мы неоднократно
использовали, так как исследователи реальных
систем работают с вещественными координатами.
Переход к экранным координатам будет произведен
в классе CGraph. Инициализацию данных проведите
в конструкторе оконного класса:
CChildView: :CChildView()
{
m_n = 200;
m_k = -0.0005;
m_L = 200.;
//====== Слева ГУ первого рода Uo=100
m_g0 = 0.;
m_d0 =100.;
m_gn = 0.;
m_dn = 0.;
Resize () ;
m_pDlg = 0;
}
В деструктор вставьте коды освобождения памяти,
занимаемой контейнерами:
CChildView::~CChildView()
{
m_Points.clear();
m_f.clear();
m_r.clear();
}
При работе с диалогом по управлению параметрами
пользователь будет иметь возможность изменять
количество узлов разбиения расчетной области,
поэтому мы должны изменять размерность
используемых контейнеров:
void
CChildView::Resize ()
{
//===== Число узлов равно N+1 (с учетом 0-го
узла)
int n = m n + 1;
m_Points.resize(n,
CDPoint(0.,0.));
m_f.resize(n, 0.);
m_r.resize(n, 1.);
}
Функция Solve решает систему уравнений методом
прогонки:
void
CChildView::Solve()
{
Resize () ;
int
n = m_n + 1;
//======= Коэффициенты разностных уравнений
vector<double> a(n),
b(n), c(n);
//======= Коэффициенты прогонки
vector<double> d(n),
e(n);
double h = m L /
m_n, // Размер шага вдоль оси х
hh = h * h;
// Квадрат шага
//======= Коэффициенты с 0-м индексом не
используются
а[0] = 0.;
b[0] = 0.;
с[0] = 0.;
//=== Вычисляем координаты х и коэффициенты
уравнений
m_Points[0].х
= 0.;
for
(int i=1; i < m_n; i++)
{
m_Points[i],x = i *
h;
//=======
Смотри формулы
(4)
a[i] = m_r[i-l]/hh;
c[i] = m_r[i]/hh;
b[i] = - a[i] - c[i]
+ m_k;
}
m_Points[m_n].x =
m_L;
//======== -Прямой
ходпрогонки
d[0] = m_gO; //ГУ
слева e[0] * m_d0; double den;
for
(i=1; i < m_n; 1++)
{
//=======
Общий знаменатель
den = a[i) * d[i-l] + b[i] ; d[i] = -c[i] / den;
e[i] = <m_f[i] -
a[i] * e[i-l]) / den;
}
//======= Готовимся к обратному ходу
den = 1. - m_gn * d[m_n-l];
//======= Случай некорректно поставленной задачи
if
(den==0.)
{
MessageBox ("ГУ
заданы некорректно", "Ошибка-",МВ_ОК) ;
return;
}
//====== Два последних узла используют ГУ справа
//======= Смотри формулы (13)
m_Points[m_n-l].у =
(e[m_n-l] + m_dn * d[m_n-l])/den;
m_Points[m_n].y = (m_dn
+ m_gn* e[m_n-l])/den;
//======= Обратный ход прогонки
for
(i = m_n-2; i >= 0; i--)
m_Points[i].y = d[i)
* m_Points[i+1].у
+ e[i]; Invalidate();
}
С помощью инструментов Studio.Net введите в
класс CChildView реакцию на сообщение о создании
окна WM_CREATE и вставьте в нее единственную
строку, которая вызывает функцию Solve. Она
формирует и решает систему разностных уравнений,
определенную данными по умолчанию. Позже мы
создадим диалог по изменению этих данных:
int
CChildView::OnCreate(LPCREATESTRUCT
IpCreateStruct)
{
if
(CWnd::OnCreate(IpCreateStruct) == -1)
return
-1;
//======= Решаем систему, определенную по
умолчанию
Solved;
return 0;
} |