Создание тестовой поверхности, чтение данных из
файла и хранение этих данных в контейнере мы
будем делать так же, как и в проекте MFC. Для
разнообразия используем другую формулу для
описания поверхности по умолчанию, то есть того
графика, который увидит пользователь элемента
ActiveX при его инициализации в рамках окна
контейнера. Вот эта формула:
Yi,j=exp[-(i+20*j)/256]*SIN[3*п*
(i-Nz/2)/Nz]*SIN[3*п*(j-Nx/2)/Nx]
Приведем тело функции Def aultGraphic, которая
генерирует значения этой функции над дискретной
сеткой узлов в плоскости X-Z и записывает их в
файл с именем «expidat». В теле этой функции мы
вызываем другую вспомогательную функцию
SetGraphPoints, которая наполняет контейнер
точек типа CPointSD. При этом, как вы помните,
она генерирует недостающие две координаты (z, x)
и масштабирует ординаты (у) так, чтобы соблюсти
разумные пропорции изображения графика на
экране:
void
COGView::DefaultGraphic()
{
//====== Размеры сетки узлов
m_xSize = m_zSize =
33;
//====== число ячеек на единицу меньше числа
узлов
UINTnz = m_zSize -
1, nx = m_xSize - 1;
// Размер файла в байтах для хранения значений
функции
DWORD nSize =
m_xSize * m_zSize * sizeof(float) + 2*sizeof
(UINT);
//====== Временный буфер для хранения данных
BYTE *buff = new
BYTE[nSize+1];
//====== Показываем на него указателем целого
типа
UINT *p = (UINT*)buff;
// Размещаем данные целого типа
*р++
= m_xSize;
*р++
= m_zSize;
//===== Меняем тип указателя, так как дальше
//====== собираемся записывать вещественные
числа
float
*pf = (float*)p;
// Предварительно вычисляем коэффициенты
уравнения
double
fi = atan(l.)*12, kx=fi/nx, kz=fi/nz;
//=== В двойном цикле пробега по сетке узлов
//=== вычисляем и
помещаем в буфер данные типа float
for
(UINT i=0; i<m_zSize;
for
(UINT j=0; j<m_xSize;
*pf++ = float (exp(-(i+20.*j)/256.)
*sin(kz* (i-nz/2. ) ) *sin(kx* (j-nx/2.)
) ) ;
//=== Переменная для того, чтобы узнать сколько
//=== байт было реально записано в файл DWORD
nBytes;
//=== Создание и открытие файла данных sin.dat
HANDLE hFile = CreateFile(_T("sin.dat") ,
GENERIC_WRITE,
0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0)
//===
Запись в файл всего буфера
WriteFile(hFile, (LPCVOID)buff,
nSize,SnBytes, 0) ;
CloseHandle(hFile);
// Закрываем файл
//=== Создание
динамического массива m cPoints
SetGraphPoints (buff,
nSize);
//=== Освобождаем временный буфер
delete
[] buff;
}
Коды функций SetGraphPoints, ReadData и DoRead
возьмите из MFC-ГфИЛО-ження OG, которое мы
разработали ранее. При этом не забудьте изменить
заголовки функций. Например, функция
SetGraphPoints теперь является членом класса
COpenGL, а не COGView, как было ранее. Кроме
того, метод ReadData теперь стал экспонируемым,
а это означает, что он описывается как
STDMETHODIMP COpenGL: : ReadData (void) и должен
возвращать значения во всех ветвях своего
алгоритма. В связи с этими изменениями приведем
полностью код функции ReadData.
STDMETHODIMP
COpenGL::ReadData(void)
{
//=== Строка, в которую будет помещен файловый
путь
TCHAR szFile[MAX_PATH]
= { 0 };
//=== Строка фильтров демонстрации файлов
TCHAR *szFilter =
TEXT("Graphics Data
Files (*.dat)\0")
TEXT("*.dat\0")
TEXT("All FilesX()")
TEXT("*.*\0");
//===
Выявляем текущую директорию
TCHAR
szCurDir[MAX_PATH];
::GetCurrentDirectory(MAX_PATH-l,szCurDir) ;
// Структура данных, используемая файловым
диалогом
OPENFILENAME ofn;
ZeroMemory(&ofn,sizeof(OPENFILENAME));
//=== Установка параметров будущего диалога
ofn.lStructSize =
sizeof(OPENFILENAME) ;
//=== Окно-владелец диалога
ofn.hwndOwner =
GetSafeHwnd();
ofn.IpstrFilter =
szFilter;
//=== Индекс строки фильтра (начиная с единицы)
ofn.nFilterlndex=
1;
ofn.IpstrFile =
szFile;
ofn.nMaxFile =
sizeof(szFile);
//===
Заголовок окна диалога
ofn.IpstrTitle = _Т("Найдите
файл с данными");
ofn.nMaxFileTitle =
sizeof (ofn.IpstrTitle);
//=== Особый стиль диалога (только в Win2K)
ofn.Flags =
OFN_EXPLORER;
//=== Создание и вызов диалога
// В случае неудачи GetOpenFileName возвращает О
if
(GetOpenFileName(&ofn))
{
// Попытка открыть файл, который должен
существовать
HANDLE hFile = CreateFile(ofn.IpstrFile, GENERIC
READ, FILE SHARE READ, 0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, 0) ;
//===== В случае неудачи CreateFile возвращает
-1
if
(hFile == (HANDLE)-1)
{
MessageBox(_T("He
удалось открыть файл"));
return
S_FALSE;
}
//=== Попытка прочесть данные о графике
if
(IDoRead(hFile))
return
S_FALSE;
//======
Создание нового изображения
DrawScene();
//======
Перерисовка окна
OpenGL
Invalidate(FALSE);
}
return S_OK;
}
Если вы используете операционную систему Windows
2000, то файловый диалог, который создает
функция GetOpenFileName, должен иметь другой
стиль. Он задан флагом OFN_EXPLORER. |