用三次Beizer曲线连续做图

关键代码: 
Bezier曲线:
void CalcBZPoints(){
       float a0,a1,a2,a3,b0,b1,b2,b3;
       a0=pt[0].x;
       a1=-3*pt[0].x+3*pt[1].x;
       a2=3*pt[0].x-6*pt[1].x+3*pt[2].x;
       a3=-pt[0].x+3*pt[1].x-3*pt[2].x+pt[3].x;
       b0=pt[0].y;
       b1=-3*pt[0].y+3*pt[1].y;
       b2=3*pt[0].y-6*pt[1].y+3*pt[2].y;
       b3=-pt[0].y+3*pt[1].y-3*pt[2].y+pt[3].y;
       float t = 0;
       float dt = 0.01;
       for(int i = 0; t<1.1; t+=0.1, i++){
              bz[i].x = a0+a1*t+a2*t*t+a3*t*t*t;
              bz[i].y = b0+b1*t+b2*t*t+b3*t*t*t;           
       }
}
画点函数:
void ControlPoint(vector vpt){
       glPointSize(2);//点的粗细
       for(int i=0; i 0) {
              ControlPoint(vpt);
       }
       if(bDraw){ 
              CalcBZPoints();
              PolylineGL(bz, 11);//画曲线
       }
       glFlush();
}
初始:
void Init(){
	glClearColor(1.0, 1.0, 1.0, 0.0);//背景颜色
	glClear(GL_COLOR_BUFFER_BIT);//清除当前帧的颜色-黑色
	glShadeModel(GL_SMOOTH);
	printf("Please Click left button of mouse to input control point of Bezier Curve!\n");
}
鼠标控制四个控制点:
void mouse(int button, int state, int x, int y){
switch (button){
	case GLUT_LEFT_BUTTON:
	if (state == GLUT_DOWN){
	if (nInput == 0){
	pt[0].x = x;
	pt[0].y = 480 - y;
	printf("(%.3f,%.3f)",pt[0].x/640.0,pt[0].y/480.0);//输出控制顶点坐标0
	nInput = 1;
	vpt.clear();
	vpt.push_back(pt[0]);
	bDraw = false;
	glutPostRedisplay();
	}
	else if (nInput == 1){
	pt[1].x = x;
	pt[1].y = 480 - y;
	printf("(%.3f,%.3f)",pt[1].x/640.0,pt[1].y/480.0);//输出控制顶点坐标1
	vpt.push_back(pt[1]);
	nInput = 2;
	glutPostRedisplay();//
	}
	else if (nInput == 2){
	pt[2].x = x;
	pt[2].y = 480 - y;
	printf("(%.3f,%.3f)",pt[2].x/640.0,pt[2].y/480.0);//输出控制顶点坐标2
	vpt.push_back(pt[2]);
	nInput = 3;
	glutPostRedisplay();//
	}
	else if (nInput == 3){
	pt[3].x = x;
	pt[3].y = 480 - y;
	printf("(%.3f,%.3f)\n",pt[3].x/640.0,pt[3].y/480.0);//输出控制顶点坐标3
	bDraw = true;
	vpt.push_back(pt[3]);
	nInput = 0;
	glutPostRedisplay();
	}
	}
	break;
	default:
	break;
	}
}
void KeyboardFunc(unsigned char Key,int x,int y){
if(Key == 'w' || Key == 'W'){ //按键清屏
        glClear(GL_COLOR_BUFFER_BIT);//清屏
		printf("清屏一次\n");
    }
	if(Key == 'x' || Key == 'X'){ //按键清除上次所画区域——将所画曲线变为背景色
        glColor3f (1.0f, 1.0f, 1.0f);
		if (vpt.size() > 0) {
		ControlPoint(vpt);
		}
		if(bDraw){
			CalcBZPoints();
			glBegin (GL_LINE_STRIP);
			for(int i=0;i<101;i++){
				glColor3f (1.0f, 1.0f, 1.0f);//线颜色
				glVertex2i (bz[i].x,bz[i].y);
			}
			glEnd ();
		}
		glFlush();
		printf("取消上次所画内容\n");
    }
}

由于作业要求,数据会每点击一下,输出一个坐标点。

取消上次所画内容是为了画起来方便点,不过只能取消一次。其实就是给覆盖了。看着网上有说用异或会比较好,但是现在还不会用,以后会试着改进。

 

int main(int argc, char *argv[])
{
	printf("清屏请按w或W\n取消上次所画内容x或X(仅限于清除线)\n注意不能连续取消代码!\n");
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(640, 480);
	glutCreateWindow("Hello World!");
	Init();
    glutKeyboardFunc(KeyboardFunc);//数字、字母键的按键检测的回调函数
	glutDisplayFunc(myDisplay);
	glutReshapeFunc(Reshape);
	glutMouseFunc(mouse);
	glutMainLoop();
	return 0;
}


    其中glutKeyboardFunc(KeyboardFunc);需要写在glutDisplayFunc(myDisplay);前面,不能写最后!

 

所画如图:用三次Beizer曲线连续做图_第1张图片这个图是照着个海报画的,水平一般尝试做画

用三次Beizer曲线连续做图_第2张图片周围会看到一些点。有颜色的话做图比较方便但美观性可能差一些

你可能感兴趣的:(图形学,C)