Учебник по Visual C++ .Net

         

Класс окна для отображения графика


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 OnPaintO;

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;

}


Содержание раздела