/*输入点的个数是可以手动改动的,此程序中输入点的最大值设置为. *同时,程序实现了键盘的交互,用来控制程序运行过程中的退出、重画等 */ #include<GL/glut.h> #include<stdlib.h> int W,H; //屏幕的大小 int N =-1; //贝赛尔曲线的幂次 GLfloat Bfunc[15]={0.0}; //Bernstein多项式的值的数组 GLfloat point[15][2]={0.0}; //存储控制点的坐标 void Init() { //设置清除颜色为白色 glClearColor(1.0f,1.0f,1.0f,1.0f); } void ChangeSize(int w, int h) { GLfloat nRange = 1.0f; if(h == 0) h = 1; glViewport(0, 0, w, h); W = w; H = h; glMatrixMode(GL_PROJECTION); glLoadIdentity(); // 设置修剪空间 if (w <= h) glOrtho (0.0, 0.0, -nRange*h/w, nRange*h/w, 0.0, 0.0); else glOrtho (-nRange*w/h, nRange*w/h, 0.0, 0.0, 0.0, 0.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void Bezier() { int i,j,t; GLfloat u; //使用的绘制点坐标 GLfloat DPoint1[2]; GLfloat DPoint2[2]; //先将第一个控制点赋给第二个点,为后面的循环做准备 for(i=0;i<2;i++) DPoint2[i]=point[0][i]; glClear(GL_COLOR_BUFFER_BIT); //设置控制点的颜色 glColor3f(1.0f,0.0f,0.0f); //设置控制点的大小 glPointSize(5); //绘制控制点 glBegin(GL_POINTS); for(i=0;i<=N;i++) { glVertex2fv(point[i]); } glEnd(); //设置连接控制点线的颜色 glColor3f(0.0f, 0.0f, 0.0f); //设置连线的宽度 glLineWidth(3); //绘制连线 glBegin(GL_LINE_STRIP); for(i=0;i<=N;i++) glVertex2fv(point[i]); glEnd(); //设置Bezier曲线的颜色 glColor3f(1.0f, 0.0f, 0.0f); //设置线宽 glLineWidth(2); for(i=0;i<=1000;i++) { //获得u值 u =i / 1000.0; //初始化Bfunc数组 for(t=0;t<=N;t++) Bfunc[t]=1.0; //第一个点的坐标等于第二个点的坐标,方便下面的绘制 DPoint1[0]=DPoint2[0]; DPoint1[1]=DPoint2[1]; //将第二个坐标的x,y设置为 DPoint2[0]=0.0; DPoint2[1]=0.0; //循环、递推计算Bezier基函数的值 for(j=0;j<=N;j++) { if(j==0) { //V0处的Bezier基函数 Bfunc[j] = 1; for(t=N;t>j;t--) Bfunc[j] = Bfunc[j]*(1-u); } else { if(i != 1000) Bfunc[j]=(1.0 * ( N - j + 1 ) / j ) * ( u / ( 1 - u ) ) * Bfunc[j-1]; else { //Bfunc[N]处的Bezier基函数 if(j == N) for(t=0;t<N;t++) Bfunc[j]=Bfunc[j]*u; else Bfunc[j]=0.0; } } //获得第二个点的坐标值 DPoint2[0] = DPoint2[0]+Bfunc[j]*point[j][0]; DPoint2[1] = DPoint2[1]+Bfunc[j]*point[j][1]; } //连接两点 if(N>=1) { glBegin(GL_LINES); glVertex2fv(DPoint1); glVertex2fv(DPoint2); glEnd(); } } glFlush(); } //鼠标事件获得控制点的坐标 void InitMouse(int button,int state,int x,int y) { //如果不是点击鼠标左键的状态,则不获得坐标值 if(button !=GLUT_LEFT_BUTTON||state !=GLUT_DOWN) return; if( N < 14 ) { N++; //获得鼠标点击的坐标 point[N][0] = (2.0*x)/(float)(W-1)-1.0; point[N][1] = (2.0*(H-y))/(float)(H)-1.0; //重绘 glutPostRedisplay(); } } //键盘响应 void keyboard(unsigned char key,int x,int y) { switch(key) { //退出运行系统 case'q':case'Q': exit(0); break; //重画曲线 case'c':case'C': N = 0; glutPostRedisplay(); break; //刷新 case'e':case'E': glutPostRedisplay(); break; } } void main(int argc,char* argv[]) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowPosition(50,100); glutInitWindowSize(800,600); glutCreateWindow("Bezier曲线绘制"); glutReshapeFunc(ChangeSize); Init(); glutDisplayFunc(Bezier); glutMouseFunc(InitMouse); glutKeyboardFunc(keyboard); glutMainLoop(); }
/*程序实现根据鼠标输入的点进行次B样条曲线的绘制,程序中鼠标 *输入点的个数是可以手动改动的,此程序中输入点的最大值设置为. *同时,程序实现了键盘的交互,用来控制程序运行过程中的退出、重画等 */ #include<GL/glut.h> int W,H; //屏幕的大小 int N = -1; //控制点的个数 GLfloat point[25][2]={0.0}; //存储控制点坐标的数组 void Init() { //设置清除颜色为白色 glClearColor(1.0f,1.0f,1.0f,1.0f); } void ChangeSize(int w, int h) { GLfloat nRange = 1.0f; if(h == 0) h = 1; // 设置视区尺寸 glViewport(0, 0, w, h); W = w; H = h; glMatrixMode(GL_PROJECTION); glLoadIdentity(); // 设置修剪空间 if (w <= h) glOrtho (0.0, 0.0, -nRange*h/w, nRange*h/w, 0.0, 0.0); else glOrtho (-nRange*w/h, nRange*w/h, 0.0, 0.0, 0.0, 0.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void BSpline() { int i; glClear(GL_COLOR_BUFFER_BIT); //设置控制点的颜色 glColor3f(1.0f, 0.0f, 0.0f); //设置控制点的大小 glPointSize(5); //绘制控制点 glBegin(GL_POINTS); for(i=0;i<=N;i++) glVertex2fv(point[i]); glEnd(); //设置连接控制点的线的颜色 glColor3f(0.0f, 0.0f, 0.0f); //设置连线的宽度 glLineWidth(3); //绘制连线 glBegin(GL_LINE_STRIP); for(i=0;i<=N;i++) glVertex2fv(point[i]); glEnd(); int j,k; float a,b,c,d; glColor3f(1.0,0.0,0.0); //3次B样条曲线,由个控制点控制,循环画出每一段曲线 for(j=0;j<=N-3;j++) { glBegin(GL_LINE_STRIP); for(k=0; k<=100;k++) { float x,y,t; t = k/100.0; //求基函数的值 a=(1-t)*(1-t)*(1-t)/6.0; b=(3.0*t*t*t-6.0*t*t+4.0)/6.0; c=(3.0*t*(1.0+t-t*t)+1.0)/6.0; d=t*t*t/6.0; //求出曲线上点的坐标 x=a*point[j][0]+b*point[j+1][0]+c*point[j+2][0]+d*point[j+3][0]; y=a*point[j][1]+b*point[j+1][1]+c*point[j+2][1]+d*point[j+3][1]; glVertex2f(x, y); } glEnd(); } glFlush(); } //鼠标事件获得点的坐标 void InitMouse(int button,int state,int x,int y) { if(button !=GLUT_LEFT_BUTTON||state !=GLUT_DOWN) return; if( N < 25 ) { N++; //获得鼠标点击的坐标 point[N][0] = (2.0*x)/(float)(W-1)-1.0; point[N][1] = (2.0*(H-y))/(float)(H)-1.0; //重绘 glutPostRedisplay(); } } //键盘响应 void keyboard(unsigned char key,int x,int y) { switch(key) { //退出运行系统 case'q':case'Q': exit(0); break; //重画曲线 case'c':case'C': N = 0; glutPostRedisplay(); break; //刷新 case'e':case'E': glutPostRedisplay(); break; } } void main(int argc,char* argv[]) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowPosition(50,100); glutInitWindowSize(800,600); glutCreateWindow("B样条绘制"); glutReshapeFunc(ChangeSize); Init(); glutDisplayFunc(BSpline); glutMouseFunc(InitMouse); glutKeyboardFunc(keyboard); glutMainLoop(); }