Пришла пора создать тестовую поверхность у = f (x,
z), которую мы будем демонстрировать по
умолчанию, то есть до того, как пользователь
обратился к файловому диалогу и выбрал файл с
данными, которые он хочет отобразить в окне
OpenGL Функция Def aultGraphic, коды которой вы
должны вставить в файл ChildView,cpp, задает
поверхность, описываемую уравнением:
Yi,j=[3*п*(i-Nz/2)/2*Nz]*SIN[3*п*(j-Nx/2)/2*Nx]
Здесь п. обозначает количество ячеек
сетки вдоль оси Z, а пх —
количество ячеек вдоль оси X. Индексы i (0 < i <
пz) и j (0 < j < nx)
выполняют роль дискретных значений координат
(Z, X) и обозначают местоположение текущей
ячейки при пробеге по всем ячейкам сетки в
порядке, описанном выше. Остальные константы
подобраны экспериментально так, чтобы видеть
полтора периода изменения гармонической функции.
Мы собираемся работать с двоичным файлом и
хранить в нем информацию в своем формате. Формат
опишем словесно: сначала следуют два целых числа
m_xsize и m_zSize (размеры сетки), затем
последовательность значений функции у = f (х, z)
в том же порядке, в котором они были созданы.
Перед тем как записать данные в файл, мы
поместим их в буфер, то есть временный массив
buff, каждый элемент которого имеет тип BYTE, то
есть unsigned char. В буфер попадают значения
переменных разных типов, что немного усложняет
кодирование, но зато упрощает процесс записи и
чтения, который может быть выполнен одной
командой, так как мы пишем и читаем сразу весь
буфер. В процессе размещения данных в буфер
используются указатели разных типов, а также
преобразование их типов:
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+l] ;
//====== Показываем на него указателем целого
типа
UINT *p = (UINT*)buff;
//====== Размещаем данные целого типа
*р++
= m_xSize;
*р++
= m_zSize;
//====== Меняем тип указателя, так как дальше
//====== собираемся записывать вещественные
числа
float
*pf = (float*)?;
//=== Предварительно вычисляем коэффициенты
уравнения
double
fi = atan(l.)*6,
kx = fi/nx,
kz = fi/nz;
//====== В двойном цикле пробега по сетке узлов
//=== вычисляем и помещаем в буфер данные типа
float
for
(UINT i=0; i<ra_zSize;
for
(UINT j=0; j<m_xSize;
{
*pf++ = float (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;
}
В процессе создания, открытия и записи в файл мы
пользуемся API-функциями CreateFile, WriteFile и
CloseHandle, которые предоставляют значительно
больше возможностей управлять файловых
хозяйством, чем, например, методы класса CFile
или функции из библиотек stdio.h или iostream.h.
Обратитесь к документации, для того чтобы
получить представление о них. |