Bezier曲线的数学表达
这是普通三次多项式曲线的参数表达式:
这是贝塞尔曲线的参数表达式:(可以上下参照记忆)
用C语言实现Bezier曲线的绘制
我们采用逼近的手法达到近似的效果,通过程序计算出多个p(u),并用直线连接相邻两个点
以下代码转自(46条消息) 图形算法:贝塞尔曲线_陈小默的博客-CSDN博客_贝塞尔曲线算法
#include<GL/glut.h> #include<math.h>
typedef struct { int length; int* arr; }intArray;//系数坐标 typedef struct { float x, y,z; } point3D;//存储二维坐标 typedef struct { int length; point3D* arr; }pointArray;
pointArray ctrlPts_;
//计算二项式系数
//接受一个数组对象的引用 void binomialCoefficient(intArray& Cin) { int j, n = Cin.length - 1; for (int k = 0; k <= n; k++) {//计算n+1个二项式系数 Cin.arr[k] = 1;//初始化 for (j = n; j > n-k; j--) { Cin.arr[k] *= j;//连乘 } for (j = k; j > 1; j--) { Cin.arr[k] /= j;//连除 } } }
//保存贝塞尔曲线单点结果
//接受的第一个参数为规律u,第二个参数为将要存放位置点的指针,第三个参数为所有控制点坐标数组,第四个参数为系数数组)
void computeBezPt(float u, point3D& bezPt, pointArray& ctrlPts, intArray& Cin) { int n = ctrlPts.length - 1; float bezFcn;//保存n次贝塞尔多项式的计算结果cin*u^i*(1-u)^(n-i) bezPt.x = bezPt.y = bezPt.z = 0;//初始化 for (int k = 0; k <= n; k++) {//计算p(u) bezFcn = Cin.arr[k] * pow(u, k) * pow ((double)1-(double)u, (double)n-(double)k); bezPt.x += ctrlPts.arr[k].x * bezFcn; bezPt.y += ctrlPts.arr[k].y * bezFcn; bezPt.z += ctrlPts.arr[k].z * bezFcn; } }
void bezier(pointArray& ctrlPts, int precision) { intArray Cin; Cin.length = ctrlPts.length; Cin.arr = new int[Cin.length];//根据控制点个数得到系数个数 binomialCoefficient(Cin);//计算系数 pointArray bezPts;//保存贝塞尔曲线的每个点 bezPts.length = precision + 1; bezPts.arr = new point3D[bezPts.length]; float u; for (int k = 0; k <= precision; k++) { u = float(k) / float(precision); computeBezPt(u, bezPts.arr[k], ctrlPts, Cin);//得出每个点的坐标 } glBegin(GL_LINE_STRIP); for (int i = 0; i < bezPts.length; i++) { //连接点 glVertex3f(bezPts.arr[i].x, bezPts.arr[i].y, bezPts.arr[i].z); } glEnd(); delete[] bezPts.arr; delete[] Cin.arr; }
以下是用OpenGL的glut实现直线的绘制
void renderScene(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glColor3f(0, 1, 0); glOrtho(-5, 5, -5, 5, -5, 5); bezier(ctrlPts_, 100); //双缓存交换缓存以显示图像 glutSwapBuffers(); //每次更新显示 glutPostRedisplay(); }
int main(int argc, char** argv) { point3D ctrlPts[4] = { {1,2,3 },{2, 3, 4},{4, 5, 1},{0, 0, 0}}; ctrlPts_.length = 4; ctrlPts_.arr = ctrlPts; glutInit(&argc, argv); //初始化glut glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); //设置窗口的模式-深度缓存,单缓存,颜色模型 glutInitWindowPosition(100, 100); //设置窗口的位置 glutInitWindowSize(800, 800); //设置窗口的大小 glutCreateWindow("3D Tech - GLUT Tutorial"); //创建窗口并赋予title glutDisplayFunc(renderScene);//调用renderScene把绘制传送到窗口 glutMainLoop(); //进入事件循环等待 return 0; }