© Георгиевский Анатолий, 24.01.2008

Отображение графиков cредствами OрenGL

Научные расчеты требуют визуализации результатов. В статье рассмотрены средства двумерной векторной графики OpenGL, которые легко встраиваются в расчетные задачи. Иы пропускаем команды подготовки вывода изображения.

График функции

Прежде всего хочется наложить ряд полезных условний на предстваление данных пригодных для вывода на график.

Границы вывода изображения. На графике отображаются значения X, Y в диапазоне от -1.0 до 1.0. Однако, данные могут вылезать за пределы выделенной области отображения. Линии и точки на графике, которые вылезают за пределы области отображения должны отсекаться.

glScissor(x0,y0,width, height);

- функция задет границы прямоугольной области отображения в координатах окна: левый нижний угол прямоугольника, ширина и высота прямоугольника. Все точки которые не попадают в заданный прямоугольник не отображаются. Режим ограничения области отображения включается функицей glEnable(GL_SCISSOR_TEST) на время задания координат точек графика и выключается функцией glDisable(GL_SCISSOR_TEST) после завершения ввода данных.

Смещение нуля. Надо привязать систему координат графика к области отображения.

glTranslatef(x, y, z);

- функция смещения (параллельного переноса) координат, задет перемещение точки начала отсчета в левый нижний угол области отображения графика.

Масштабирование изображения. Исходные данные могут быть в любом масштабе. Масштабирование изображения может быть описано четырьмя параметрами: масштаб по оси X, по оси Y и смещение начала отсчета по оси X и по оси Y.

glScalef(scale_X, scale_Y, 1.0);
glTranslatef(offset_X, offset_Y, 0.0);

- функция масштабирования координат. Последовательное применение функций сдвига и масштабирования координат вызывает генерацию матрицы преобразования координат точек графика. Матрица будет применяться для пересчета координат каждой вершины. Дополнительно может быть задана операция смещения, заданная уже в координатах графика.

Задание кривой График может быть представлен сплошной линией. Данные могут быть заданы, например, в виде массива точек с координатами (X,Y). График строится в виде ломанной линии проходящей через заданные точки массива.

GLfloat white[]={1.0,1.0,1.0};
glColor3fv(white);
glEnable(GL_SCISSOR_TEST);
 glBegin(GL_LINE_STRIP);
  for (i = 0; i< length; i++)
     glVertex2f(x[i],y[i]);
 glEnd();
glDisable(GL_SCISSOR_TEST);

Маркеры

На следующем примере мы продемонстрируем использование прекомпилированных списков примитивов. Допустим, нам понадобилось изобразить множество одинаковых фигур. На графиках бывает полезно, выделить вершины, точки, через которые проведены линии. Для решения этой задачи предлагается создать примитив, "метку", состоящую из нескольких примитивов. Нампример, метки могут выглядеть как кружочки, треугольники или квадратики. Мы хотим создать новый примитив, квадратик, с уникальным индексом и запросить прорисовку примитива в нескольких точках.

 const quad_idx=1;
 glNewList(quad_idx, GL_COMPILE); // начать ввод списка
  float quad_size=0.015;
  glScalef(quad_size,quad_size,1.0); // задать масштаб изображения
  glBegin(GL_LINE_STRIP);
   glVertex2f(-1,-1); glVertex2f(-1,1);  glVertex2f(1,1);    
   glVertex2f(1,-1);  glVertex2f(-1,-1);
  glEnd();
 glEndList();  // завершить ввод списка

for (i = 0;i < length; i++){
   glPushMatrix(); // сохранить матрицу преобразования
// переместить начало отсчета в точку с координатами x,y
   glTranslatef(x[i],y[i],0); 
// изобразить фигуру по идентификатору списка
   glCallList(quad_idx); 
   glPopMatrix(); // восстановить матрицу преобразования
}

Сглаживание линий

Следующее улучшение, которое мы добавляем в процедуру рисования графиков, настройки толщины линии. Кроме этого хочется чтобы на изображении наклонные линии выглядели гладкими, а не ступнчатыми, как на предыдущей картинке.

glLineWidth(width);

- функция определяет ширину линии. Следующие функции настраивают графическую библиотеку для раскрашивания края линии полутонами.

glEnable( GL_LINE_SMOOTH);
glHint( GL_LINE_SMOOTH_HINT, GL_DONT_CARE);

Полутона содержат информацию о цвете линии и прозрачности (альфа-канал). Поэтому для нормальной работы надо включить режим сложения цветов с учетом альфа канала.

glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

Режим BLEND попиксельно производит операцию сложения с учетом альфа-канала с содержимым выходного буфера. Четвертая компонента цвета (альфа-канал) опрделеяет прозрачность пикселя.

В селдующем приближении нам не понравилось, что функция какая-то угловатая, невзрачная. Когда дело касается представления экспериментальных данных, бывает полезно построить сглаженную функцию. Для сглаживания мы применили метод построения квадратичных кривых Безье, с помошью которого строятся промежуточные точки сглаженной кривой проходящей через середины линейных сегменотов графика.

float bezier_quadratic_curve(float t, float c0,float c1,float c2)
{
   float b0,b1;
   b0 = (1.0f - t) * c0 + t * c1;
   b1 = (1.0f - t) * c1 + t * c2;
   return ((1.0f - t) * b0 + t * b1);
}

Cсылки

  • Кривые Безье, очень наглядно

    ()

  •