ПРИМЕР ПРОГРАММЫ ГЕНЕРАЦИИ КРИВЫХ БЕЗЬЕ
В приведенной ниже программе реализован расчет стыковочных функций Безье и генерация двухмерного кубического сплайна Безье. На плоскости ху определены четыре контрольные точки, и на кривой отмечено 1000 положений пикселей, причем ширина пикселя равна 4. Значения биномиальных коэффициентов вычисляются в процедуре binoraialCoef f s, а положения точек на кривой вычисляются в процедуре computeBezPt. Данные значения передаются процедуре bezier, и пиксели отмечаются на кривой с использованием процедур OpenGL вывода точек на экран. Кроме того, траекторию кривой можно аппроксимировать прямыми отрезками, используя при этом меньшее число точек. Более эффективные методы генерации точек вдоль сплайновой кривой рассматриваются в разделе 8.17. В приведенном примере наложены условия внешней системы координат, поэтому отображаются только точки кривой, находящиеся в окне просмотра (рис. 8.34). Если дополнительно требуется изобразить положения контрольных точек, контрольный граф или выпуклую оболочку, отсекающее окно нужно расширить во внешней системе координат.
Рис. 8.34. Кривая Безье, изображенная программой-примером
♦include <GL/glut.h>
♦include <stdlib.h>
♦include <math.h>
/* Задается исходный размер окна на экране дисплея. */ GLsizei winWidth = 600, winHeight * 600;
/* Задается размер отсекающего окна во внешних
* координатах.
*/
GLfloat xwcMin = -50.0, xwcMax = 50.0;
GLfloat ywcMin = -50.0, ywcMax = 50.0;
class wcPt3D { public:
GLfloat x, y, z;
};
void init (void)
{
/* Цвет окна выбирается белым. */ glClearColor (1.0, 1.0, 1.0, 0.0);
}
void plotPoint (wcPt3D bezCurvePt)
{
glBegin (GL_POINTS);
glVertex2f (bezCurvePt.x, bezCurvePt.y); glEnd ( );
}
/* Вычисляются биномиальные коэффициенты С для данного
* значения п.
*/
void binomialCoeffs (GLint п, GLint * С) {
GLint k, j;
for (k = 0; k <= n; k++) {
/* Вычисляется n!/(k!(n - k)!). */
С [k] = 1;
for (j = n; j >= k + 1; j-)
С [k] *= j; for (j = n - k; j >= 2; j -)
С [k] /= j;
}
}
void computeBezPt (GLfloat u, wcPt3D * bezPt, GLint nCtrlPts,
wcPt3D * ctrlPts, GLint * C)
{
GLint k, n = nCtrlPts - 1;
GLfloat bezBlendFcn;
bezPt->x = bezPt->y = bezPt->z = 0.0;
/* Вычисляются стыковочные функции и контрольные
* точки соединений.
*/
for (к = 0; к < nCtrlPts; к++) {
bezBlendFcn = С [к] * pow (и, к) * pow (1 - и, п - к);
bezPt->x += ctrlPts [к].х * bezBlendFcn;
bezPt->y += ctrlPts [к].у * bezBlendFcn;
bezPt->z += ctrlPts [k].z * bezBlendFcn;
}
}
void bezier (wcPt3D * ctrlPts, GLint nCtrlPts,
GLint nBezCurvePts)
{
wcPt3D bezCurvePt;
GLfloat u;
GLint *C, k;
/* Распределяется память для биномиальных коэффициентов.*/ С = new GLint [nCtrlPts];