计算机图形学贝塞尔曲线的实现 本项目仅供参考学习交流使用,未经授权禁止用于商业活动,侵权必究.如有不足或错误之处,欢迎在下方留言………… 升阶意思是增加控制点,但保持原曲线不变 由于通过贝塞尔方程计算太过复杂,所以提出了递推法,方程如下
贝塞尔曲线
定义实现bezier曲线
定义
B(t)=i=0∑nPi∁niti(1−t)n−i,其中[tϵ(0,1]]
不要被这么一坨公式给吓到,它求的其实是
t为定值
时贝塞尔曲线上的点的坐标,而
Pi则表示第
i个控制点的作用.不同的
t值可以画出不同的点,这些点就连成了贝塞尔曲线.一阶贝塞尔曲线
B(t)=(1−t)P0+tP1
二阶贝塞尔曲线
B(t)=(1−t)2P0+2t(1−t)P1+t2P2
三阶贝塞尔曲线
B(t)=i=0∑3Pi∁3iti(1−t)n−i
贝塞尔曲线升阶
Pi∗=n+1iPi−1+(1−n+1i)Pi,(i=0,1,2...,n+1)代码实现
#include <GL/glut.h> #include <stdlib.h> #include <math.h> GLfloat xwcMin = -250.0, xwcMax = 250.0; GLfloat ywcMin = -250.0, ywcMax = 250.0; class WcPt3d { public: GLfloat x, y, z; }; // 画点 void plotPt(WcPt3d point) { glBegin(GL_POINTS); glVertex3f(point.x,point.y,point.z); glEnd(); } // 初始化背景色 void init(void) { glClearColor(1.0, 1.0, 1.0, 0.0); } // 计算二项式的系数 *** void BinomialCoeffi(GLint *C, GLint ctrlNums) { GLint k, j; for ( k = 0; k <= ctrlNums; k++) { C[k] = 1; // n!/(k!(n-k)!) for ( j = ctrlNums; j >= k+1 ; j--) // n!/k! { C[k] *= j; } for (j = ctrlNums - k; j >= 2; j--) // (n-k)! { C[k] /= j; } } } void computeBezierPts(GLfloat t, WcPt3d * bezierCurvePt,GLint ctrlNums,GLint* C,WcPt3d* ctrlPts) { GLint k, n = ctrlNums - 1; GLfloat bezierCurveFcn; bezierCurvePt->x = bezierCurvePt->y = bezierCurvePt->z = 0; for ( k = 0; k < ctrlNums; k++) { bezierCurveFcn = C[k] * pow(t, k) * pow(1 - t, n - k); bezierCurvePt->x += ctrlPts[k].x * bezierCurveFcn; bezierCurvePt->y += ctrlPts[k].y * bezierCurveFcn; bezierCurvePt->z += ctrlPts[k].z * bezierCurveFcn; } } // 绘制连接线段 void plotLines(WcPt3d* points, GLint Ptnums) { glBegin(GL_LINE_STRIP); for (GLint i = 0; i < Ptnums; i++) { glVertex3f(points[i].x, points[i].y, points[i].z); } glEnd(); } // Bezier曲线的算法 void Bezier(WcPt3d *ctrlPts, GLint bezierCurveNums, GLint ctrlNums){ WcPt3d bezierCurvePt; GLint k, *C; // 获取控制点的数目 GLfloat t; C = new GLint[ctrlNums]; // 获取多项式的各项系数 BinomialCoeffi(C, ctrlNums - 1); // 计算各项的系数,并存储 for ( k = 0; k <= bezierCurveNums; k++) { t = (GLfloat)k / (GLfloat)bezierCurveNums; computeBezierPts(t, &bezierCurvePt, ctrlNums,C,ctrlPts); plotPt(bezierCurvePt); } // 绘制线段 plotLines(ctrlPts, ctrlNums); delete[] C; } // 贝塞尔曲线的升阶 void ascendingBezier(WcPt3d* oldPts,GLint oldPtnums, GLint bezierCurveNums) { GLint newPtNums = oldPtnums + 1; WcPt3d* newPts = new WcPt3d[newPtNums]; GLint i; // P[i]' = i/(n+1) P[i-1] + (n+1-i)/(n+1) Pi; for (i = 0; i < newPtNums; i++) { GLfloat x = 0, y = 0, z= 0; if (i==0) { x = oldPts[i].x; y = oldPts[i].y; z = oldPts[i].z; } else if(i==newPtNums - 1){ x = oldPts[i - 1].x; y = oldPts[i - 1].y; z = oldPts[i - 1].z; } else { x = (GLfloat) oldPts[i - 1].x * i / oldPtnums + oldPts[i].x * (oldPtnums - i) / oldPtnums; y = (GLfloat)oldPts[i - 1].y * i / oldPtnums + oldPts[i].y * (oldPtnums - i) / oldPtnums; z = (GLfloat)oldPts[i - 1].z * i / oldPtnums + oldPts[i].z * (oldPtnums - i) / oldPtnums; } newPts[i] = { x,y,z }; } Bezier(newPts, bezierCurveNums, newPtNums); } // 初始化数据并进行绘制 void displayFcn1(void) { WcPt3d ctrlPts[7] = { {-140,-40,0}, {-60,-80,0},{90,100,0},{120,200,0},{180,160,0},{200,130,0},{230,10,0}}; GLint bezierCurveNums = 2000 , ctrlNums = 7; glClear(GL_COLOR_BUFFER_BIT); glPointSize(2); glColor3f(0, 0, 0); // 将控制点,绘制精度代入 Bezier(ctrlPts,bezierCurveNums,ctrlNums); glColor3f(1, 1, 0); // 升阶 ascendingBezier(ctrlPts, ctrlNums,bezierCurveNums); glFlush(); } // 对绘图窗口进行缩放 void winReshapeFcn(GLint newWidth, GLint newHeight) { glViewport(0, 0, newHeight, newHeight); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(xwcMin, xwcMax, ywcMin, ywcMax); glClear(GL_COLOR_BUFFER_BIT); } // 主函数 int main(int argc, char **argv){ glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowPosition(50, 50); glutInitWindowSize(600, 600); glutCreateWindow("贝塞尔曲线"); init(); glutDisplayFunc(displayFcn1); glutReshapeFunc(winReshapeFcn); glutMainLoop(); }
效果图
通过de Casteljau
de Casteljau递推法
Pik=={Pi(1−t)Pik−1+tPi+1k−1k=0x!=0
代码实现
#include <GL/glut.h> #include <math.h> #include <stdlib.h> class WcPt3D { public: GLfloat x, y, z; }; GLfloat xwcMin = -250.0, xwcMax = 250.0; GLfloat ywcMin = -250.0, ywcMax = 250.0; void plotPt(WcPt3D pt) { glBegin(GL_POINTS); glVertex3f(pt.x, pt.y, pt.z); glEnd(); } // 当为1阶时 void oneCasteljau(WcPt3D* points, GLfloat t) { WcPt3D point; point.x = points[0].x * (1 - t) + points[1].x * t; point.y = points[0].y * (1 - t) + points[1].y * t; point.z = points[0].z * (1 - t) + points[1].z * t; plotPt(point); } // 当为n阶时 void nCasteljau(WcPt3D* Points, GLint n, GLfloat t) { // 绘制的点 , 阶数 = 点数 -1, t 目前的比值 if (n > 1) { WcPt3D* newCtrls = new WcPt3D[n]; // 获取n-1阶的点 GLint k; for ( k = 0; k < n; k++) { newCtrls[k].x = Points[k].x * (1 - t) + Points[k + 1].x * t; newCtrls[k].y = Points[k].y * (1 - t) + Points[k + 1].y * t; newCtrls[k].z = Points[k].z * (1 - t) + Points[k + 1].z * t; } nCasteljau(newCtrls, n - 1, t); } else { oneCasteljau(Points,t); } } // 绘制连接线段 void plotLines(WcPt3D* points, GLint Ptnums) { glBegin(GL_LINE_STRIP); for (GLint i = 0; i < Ptnums; i++) { glVertex3f(points[i].x, points[i].y, points[i].z); } glEnd(); } // 使用算法绘制曲线 void deCasteljau(WcPt3D* ctrlPts, GLint ctrlNums, GLint bezierCurveNums) { GLint k; for ( k = 0; k <bezierCurveNums; k++) { GLfloat t = (GLfloat)k / (GLfloat)bezierCurveNums; nCasteljau(ctrlPts, ctrlNums - 1, t); } // 绘制线段 plotLines(ctrlPts, ctrlNums); } void displayFcn() { WcPt3D ctrlPts[7] = { {-140,-40,0}, {-60,-80,0},{90,100,0},{120,200,0},{180,160,0},{200,130,0},{230,10,0} }; GLint bezierCurveNums = 2000, ctrlNums = 7; glClear(GL_COLOR_BUFFER_BIT); glPointSize(2); glColor3f(0, 0, 0); deCasteljau(ctrlPts, ctrlNums, bezierCurveNums); glFlush(); } // 对绘图窗口进行缩放 void winReshapeFcn(GLint newWidth, GLint newHeight) { glViewport(0, 0, newHeight, newHeight); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(xwcMin, xwcMax, ywcMin, ywcMax); glClear(GL_COLOR_BUFFER_BIT); } void init() { glClearColor(1.0, 1.0, 1.0, 0.0); } int main( int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowPosition(50, 50); glutInitWindowSize(600, 600); glutCreateWindow("deCasteljau使用"); init(); glutDisplayFunc(displayFcn); glutReshapeFunc(winReshapeFcn); glutMainLoop(); }
效果图
代码地址.
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算