实验10 Bezier曲线生成

1.实验目的:

  • 了解曲线的生成原理;
  • 掌握几种常见的曲线生成算法,利用VC+OpenGL实现Bezier曲线生成算法。

2.实验内容:

(1)结合示范代码了解曲线生成原理与算法实现,尤其是Bezier曲线。
(2)调试、编译、修改示范程序。

3.实验原理:

Bezier曲线是通过一组多边形折线的顶点来定义的。如果折线的顶点固定不变,则由其定义的Bezier曲线是唯一的。在折线的各顶点中,只有第一点和最后一点在曲线上且作为曲线的起始点和终止点,其他的点用于控制曲线的形状及阶次。曲线的形状趋向于多边形折线的形状,要修改曲线,只要修改折线的各顶点就可以了。因此,多边形折线又称Bezier曲线的控制多边形,其顶点称为控制点。
三次Bezier曲线,有四个控制点,其数学表示如下:
在这里插入图片描述

4.实验代码:

教材原代码:

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

using namespace std;

struct Point
{
	int x, y;
};

Point pt[4], bz[11];
vector<Point> vpt;
bool bDraw;
int nInput;

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<Point> vpt)
{
	glPointSize(2);
	for(int i=0; i<vpt.size(); i++)
	{
		glBegin (GL_POINTS);
		glColor3f (1.0f, 0.0f, 0.0f);   
glVertex2i (vpt[i].x,vpt[i].y);
		glEnd ();
	}
}

void PolylineGL(Point *pt, int num)
{
	glBegin (GL_LINE_STRIP);
	for(int i=0;i<num;i++)
	{		
		glColor3f (1.0f, 1.0f, 1.0f);   
		glVertex2i (pt[i].x,pt[i].y);		
	}
	glEnd ();
}

void myDisplay()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f (1.0f, 1.0f, 1.0f); 
	if (vpt.size() > 0)
	{
		ControlPoint(vpt);
	}

	if(bDraw)
	{
		PolylineGL(pt, 4);
		CalcBZPoints();
		PolylineGL(bz, 11);
	}

	glFlush();
}

void Init()
{
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glShadeModel(GL_SMOOTH);

	printf("Please Click left button of mouse to input control point of Bezier Curve!\n");
}

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

void myMouse(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;
				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;
				vpt.push_back(pt[1]);
				nInput = 2;
				glutPostRedisplay();
			}
			else if (nInput == 2) 
			{
				pt[2].x = x;
				pt[2].y = 480 - y;
				vpt.push_back(pt[2]);
				nInput = 3;
				glutPostRedisplay();
			}
			else if (nInput == 3) 
			{
				pt[3].x = x;
				pt[3].y = 480 - y;
				bDraw = true;
				vpt.push_back(pt[3]);
				nInput = 0;
				glutPostRedisplay();
			}
		}
		break;
	default:
		break;
	}
}

int main(int argc, char *argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(640, 480);
	glutCreateWindow("Hello World!");

	Init();
	glutDisplayFunc(myDisplay);
	glutReshapeFunc(myReshape);
	glutMouseFunc(myMouse);
	glutMainLoop();
	return 0;
}

运行结果如图A.10(a)所示。
在这里插入图片描述

图A.10(a)Bezier曲线
整理后代码:
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
#include <vector>

using namespace std;

struct Point
{
	int c[2];
	int& x = c[0];
	int& y = c[1];

	Point() { x = 0, y = 0; }
	Point(int x0, int y0) { x = x0, y = y0; }
	Point(const Point& pt) { x = pt.x, y = pt.y; }
	int& operator[](const int i) { return c[i]; }
};

vector<Point> GctrlPt, GbzCurvePt;
int GnumSegment = 10;

void CalcBZPoints()
{
	float F0[2], F1[2], F2[2], F3[2];
	for (int i = 0; i < 2; i++)
	{
		F0[i] = GctrlPt[0][i];
		F1[i] = -3 * GctrlPt[0][i] + 3 * GctrlPt[1][i];
		F2[i] = 3 * GctrlPt[0][i] - 6 * GctrlPt[1][i] + 3 * GctrlPt[2][i];
		F3[i] = -GctrlPt[0][i] + 3 * GctrlPt[1][i] - 3 * GctrlPt[2][i] + GctrlPt[3][i];
	}

	float t = 0;
	float dt = 1 / (float)GnumSegment;
	GbzCurvePt.resize(GnumSegment + 1);
	for (int i = 0; i < GnumSegment + 1; i++)
	{
		for (int j = 0; j < 2; j++)
		{
			GbzCurvePt[i][j] = F0[j] + F1[j] * t + F2[j] * t*t + F3[j] * t*t*t;
		}
		t += dt;
	}
}

void ControlPoint(const vector<Point>& vpt)
{
	glPointSize(3);
	glBegin(GL_POINTS);
	for (unsigned int i = 0; i < vpt.size(); i++)
	{
		glVertex2f(vpt[i].x, vpt[i].y);
	}
	glEnd();
}

void PolylineGL(const vector<Point>& vpt)
{
	glBegin(GL_LINE_STRIP);
	for (unsigned int i = 0; i < vpt.size(); i++)
	{
		glVertex2i(vpt[i].x, vpt[i].y);
	}
	glEnd();
}

void myDisplay()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(1.0f, 0.0f, 0.0f);
	ControlPoint(GctrlPt);

	glColor3f(0.0f, 1.0f, 0.0f);
	PolylineGL(GctrlPt);

	if (GctrlPt.size() == 4)
	{
		glColor3f(1.0f, 1.0f, 1.0f);
		CalcBZPoints();
		PolylineGL(GbzCurvePt);
	}

	glFlush();
}

void Init()
{
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glShadeModel(GL_SMOOTH);

	printf("Please Click left button of mouse to input control point of Bezier Curve!\n");
}

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

void myMouse(int button, int state, int x, int y)
{
	Point pt;
	int cptNum = GctrlPt.size();
	switch (button)
	{
	case GLUT_LEFT_BUTTON:
		if (state == GLUT_DOWN)
		{
			pt.x = x;
			pt.y = 480 - y;

			if (cptNum != 4)
			{
				GctrlPt.push_back(pt);
				glutPostRedisplay();
			}
			else
			{
				GctrlPt.clear();
				GctrlPt.push_back(pt);
				glutPostRedisplay();
			}
		}
		break;
	default:
		break;
	}
}

int main(int argc, char *argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(640, 480);
	glutCreateWindow("Bezier Curve");

	Init();
	glutDisplayFunc(myDisplay);
	glutReshapeFunc(myReshape);
	glutMouseFunc(myMouse);
	glutMainLoop();
	return 0;
}

5.实验提高

模仿上述代码,以( 10, 5, 0 ),( 5, 10, 0 ),( -5, 15, 0 ),( -10, -5, 0 ),( 4, -4, 0 ),( 10, 5, 0 ), ( 5, 10, 0 ), ( -5, 15, 0 ), ( -10, -5, 0 ),( 10, 5, 0 )为控制点,将其转变为B样条曲线生成算法,见图A.10(b)。
在这里插入图片描述

图A.10(b)B样条曲线
  • 15
    点赞
  • 95
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图形空间

文章不错,赞赏鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值