![]() |
![]() |
![]() |
График
по умолчанию
Пришла пора создать тестовую поверхность у = f (x, z), которую мы будем демонстрировать по умолчанию, то есть до того, как пользователь обратился к файловому диалогу и выбрал файл с данными, которые он хочет отобразить в окне OpenGL Функция Def aultGraphic, коды которой вы должны вставить в файл ChildView,cpp, задает поверхность, описываемую уравнением:
Y
i,j
=[3*п*(i-N
z
/2)/2*N
z
]*SIN
[3*п*(j-N
x/
2)/2*N
x
]
Здесь
п.
обозначает количество ячеек сетки вдоль оси Z, а
п
х
—
количество
ячеек вдоль оси X. Индексы i (0 < i < п
z
) и j (0 < j <
n
x
)
выполняют роль дискретных значений координат (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. Обратитесь к документации, для того чтобы получить представление о них.
![]() |
![]() |
![]() |