计算机图形学 实验7 《复杂图形绘制-Bezier曲线与Hermite曲线》

计算机图形学 实验7 《复杂图形绘制-Bezier曲线与Hermite曲线》

一、实验目的

学习样条曲线的绘制。

二、实验内容

1、绘制Bezier曲线;
2、绘制Hermite曲线。

三、实验方法

Hermite曲线是给定曲线段的两个端点坐标以及两端点处的切线矢量来描述的曲线。平面上一条三次参数曲线可以表示为:


四、实验步骤

1、设定Bezier曲线的四个控制点的位置,结果存储在数组中;
2、根据样条法处端点不断拟合曲线;
3、将制作好的成果刷新在显示区域。

五、实验结果

实验输出图
1、Bezier曲线:


2、Hermite曲线


六、实验结论

1、Bezier曲线的绘制

代码:

#include <GL/glut.h>
#include <stdlib.h>

GLfloat ctrlpoints[4][3] = {
	{ -4.0, -4.0, 0.0}, { -2.0, 4.0, 0.0}, 
	{2.0, -4.0, 0.0}, {4.0, 4.0, 0.0}};

void init(void) {
   glClearColor(0.0, 0.0, 0.0, 0.0);
   glShadeModel(GL_FLAT);
   
   glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]);
   
   glEnable(GL_MAP1_VERTEX_3);
}

void display(void) {
   int i;

   glClear(GL_COLOR_BUFFER_BIT);
   glColor3f(1.0, 1.0, 1.0);
   
   glBegin(GL_LINE_STRIP);
      for (i = 0; i <= 30; i++) 
         glEvalCoord1f((GLfloat) i/30.0);
   glEnd();
  
   /* The following code displays the control points as dots. */
   glPointSize(5.0);
   glColor3f(1.0, 1.0, 0.0);
   glBegin(GL_POINTS);
      for (i = 0; i < 4; i++) 
         glVertex3fv(&ctrlpoints[i][0]);
   glEnd();
   glFlush();
}

void reshape(int w, int h) {
   glViewport(0, 0, (GLsizei) w, (GLsizei) h);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   if (w <= h)
      glOrtho(-5.0, 5.0, -5.0*(GLfloat)h/(GLfloat)w, 
               5.0*(GLfloat)h/(GLfloat)w, -5.0, 5.0);
   else
      glOrtho(-5.0*(GLfloat)w/(GLfloat)h, 
               5.0*(GLfloat)w/(GLfloat)h, -5.0, 5.0, -5.0, 5.0);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
}

void keyboard(unsigned char key, int x, int y) {
   switch (key) {
      case 27:
         exit(0);
         break;
   }
}

int main(int argc, char** argv) {
   glutInit(&argc, argv);
   glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
   glutInitWindowSize (500, 500);
   glutInitWindowPosition (100, 100);
   glutCreateWindow (argv[0]);
   init ();
   glutDisplayFunc(display);
   glutReshapeFunc(reshape);
   glutKeyboardFunc (keyboard);
   glutMainLoop();
   return 0;
}

2、Hermite曲线的绘制

代码:

#include <math.h>
#include <gl/glut.h>
#include <iostream>
using namespace std;

struct  Point2 {
	double x;
	double y;

	Point2(int px, int py) { x = px; y = py; }
};

Point2 P0(100, 200);
Point2 P1(350, 200);
Point2 derP0(200, 200);
Point2 derP1(200, 200);

bool mouseLeftDown = false;
bool mouseRightDown = false;

/* 计算Hermite曲线 */
void Hermit(int n) {
	float f1, f2, f3, f4;

	double deltaT = 1.0 / n;

	glBegin(GL_LINE_STRIP);
	for (int i = 0; i <= n; i++) {

		double T = i * deltaT;

		f1 = 2.0 * pow(T, 3) - 3.0 * pow(T, 2) + 1.0;
		f2 = -2.0 * pow(T, 3) + 3.0 * pow(T, 2);
		f3 = pow(T, 3) - 2.0 * pow(T, 2) + T;
		f4 = pow(T, 3) - pow(T, 2);

		glVertex2f(f1 * P0.x + f2 * P1.x + f3 * derP0.x + f4 * derP1.x,
			f1 * P0.y + f2 * P1.y + f3 * derP0.y + f4 * derP1.y);
	}
	glEnd();
}

/* 用鼠标进行绘制,完成后可改变控制点,拖动即可 */
void display() {
	glClear(GL_COLOR_BUFFER_BIT);

	glLineWidth(1.5);
	glColor3f(1.0, 0.0, 0.0);
	glBegin(GL_LINES);
	glVertex2f(P0.x, P0.y);
	glVertex2f(P0.x + derP0.x / 4, P0.y + derP0.y / 4);
	glVertex2f(P1.x, P1.y);
	glVertex2f(P1.x - derP1.x / 4, P1.y - derP1.y / 4);
	glEnd();

	glColor3f(0.0, 0.0, 1.0);
	glPointSize(10.0f);

	glBegin(GL_POINTS);
	glVertex2f(P0.x, P0.y);
	glVertex2f(P0.x + derP0.x / 4, P0.y + derP0.y / 4);
	glVertex2f(P1.x, P1.y);
	glVertex2f(P1.x - derP1.x / 4, P1.y - derP1.y / 4);
	glEnd();

	Hermit(20);

	glFlush();
	glutSwapBuffers();
}

void init() {
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glShadeModel(GL_FLAT);
}

void myReshape(int w, int h) {
	glViewport(0, 0, (GLsizei)w, (GLsizei)h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0.0, (GLsizei)w, (GLsizei)h, 0.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void mouse(int button, int state, int x, int y) {
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
		mouseLeftDown = true;

	if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
		mouseLeftDown = false;

	if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
		mouseRightDown = true;

	if (button == GLUT_RIGHT_BUTTON && state == GLUT_UP)
		mouseRightDown = false;
}

double distance(int x1, int y1, int x2, int y2) {
	return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}

void motion(int x, int y) {
	if (mouseLeftDown) {
		if (distance(P0.x + derP0.x / 4, P0.y + derP0.y / 4, x, y) < 20) {
			derP0.x = (x - P0.x) * 4;
			derP0.y = (y - P0.y) * 4;
		}

		if (distance(P1.x - derP1.x / 4, P1.y - derP1.y / 4, x, y) < 20) {
			derP1.x = (P1.x - x) * 4;
			derP1.y = (P1.y - y) * 4;
		}
	}

	glutPostRedisplay();
}

int  main(int argc, char** argv) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowSize(450, 450);
	glutInitWindowPosition(200, 200);
	glutCreateWindow("Hermite");
	init();
	glutDisplayFunc(display);
	glutReshapeFunc(myReshape);
	glutMouseFunc(mouse);
	glutMotionFunc(motion);
	glutMainLoop();
	return 0;
}

七、实验小结

Bezier曲线只是B样条的一个特例,可以通过改变一个控制点的位置来改变曲线的形状,这种曲线生成方式比较直观和灵活,只需要放置控制点,然后调整控制点的位置来得到想要的曲线,这就避免了和复杂的数学方程打交道。对于Hermite曲线,最终的曲线在靠近第一个关键点的位置,会更接近第一个基函数加权的量,最终的曲线在靠近第二个关键点的位置,会更接近影响第二个基函数的值。

  • 7
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值