Bezier曲線的數學表達
這是普通三次多項式曲線的參數表達式:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISPrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdsATOfd3bkFGazxCMx8VesATMfhHLlN3XnxCMwEzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5CZ0ITZ5Q2MjFTYiBzNlNjZ1EGN0MWN2QTNwYWM0EjNw8CX5IzLclDMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjL3M3Lc9CX6MHc0RHaiojIsJye.png)
用C語言實作Bezier曲線的繪制
我們采用逼近的手法達到近似的效果,通過程式計算出多個p(u),并用直線連接配接相鄰兩個點
#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;
}