关闭

OpenGL绘制Bezier曲线

标签: opengl
4830人阅读 评论(0) 收藏 举报
分类:


项目要求:

– 使用鼠标在屏幕中任意设置控制点,并生成曲线

– 使用鼠标和键盘的交互操作实现对曲线的修改。

项目总体介绍

本项目利用Bezier曲线生成算法生成可由用户自定义的曲线。可实现核心功能如下:

  1. 用户用鼠标左击屏幕任意处产生记录点。

  2. 鼠标右击屏幕任意处由先前的任意个数记录点和其先后关系生成Bezier曲线。

另有辅助输入功能:

  1. 按键盘C键可清除所有记录点。

  2. 按键盘R键可清除上一个记录点。

  3. 按键盘Q键可推出程序。

 

 

项目设计思路

1Bezier曲线介绍:

贝塞尔曲线就是这样的一条曲线,它是依据四个位置任意的点坐标绘制出的一条光滑曲线。在历史上,研究贝塞尔曲线的人最初是按照已知曲线参数方程来确定四个点的思路设计出这种矢量曲线绘制法。1962年,法国数学家Pierre Bézier第一个研究了这种矢量绘制曲线的方法,并给出了详细的计算公式,因此按照这样的公式绘制出来的曲线就用他的姓氏来命名是为贝塞尔曲线。

2、生成公式:

1线性公式(只有两个点情况)

给定点P0P1,线性贝兹曲线只是一条两点之间的直线。这条线由下式给出:

且其等同于线性插值。

2二次方公式(三个点组成)

二次方贝兹曲线的路径由给定点P0P1P2的函数Bt)追踪:

 

TrueType字型就运用了以贝兹样条组成的二次贝兹曲线。

3三次方公式(四个点)

P0P1P2P3四个点在平面或在三维空间中定义了三次方贝兹曲线。曲线起始于P0走向P1,并从P2的方向来到P3。一般不会经过P1P2;这两个点只是在那里提供方向资讯。P0P1之间的间距,决定了曲线在转而趋进P3之前,走向P2方向的“长度有多长”。

曲线的参数形式为:

现代的成象系统,如PostScriptAsymptoteMetafont,运用了以贝兹样条组成的三次贝兹曲线,用来描绘曲线轮廓。

 

 

4一般参数公式n个点)

阶贝兹曲线可如下推断。给定点P0P1、…、Pn,其贝兹曲线即:

 


N阶的贝兹曲线,即N-1阶贝兹曲线之间的插值。

#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#include<GL/glut.h>
//定义控制点数目的最大值
#define MAX_CPTX 25  
int ncpts=0;//实际控制点个数
static int width=600,height=600;//窗口大小
typedef struct
{
	GLfloat x,y;
} POINT;
POINT cpts[MAX_CPTX];//存储控制点坐标
//求n!
int JieCheng(int n)
{
	if(n==1||n==0)
	{
		return 1;
	}
	else
	{
		return n*JieCheng(n-1);
	}
}
//求组合排列
double C(int n,int i)
{
	return ((double)JieCheng(n))/((double)(JieCheng(i)*JieCheng(n-i)));
}
//求一个数u的num次方
double N(double u,int n)
{
	double sum=1.0;
	if (n==0)
	{
		return 1;
	}
	for(int i=0;i<n;i++)
	{
		sum*=u;
	}
	return sum;
}

//绘制bezier曲线
void drawBezier(POINT *p)
{    
	void display();
	if(ncpts<=0) return;	

	POINT *p1;
	p1=new POINT[1000];
	GLfloat u=0,x,y;
	int i,num=1;
	p1[0]=p[0];
	for(u=0;u<=1;u=u+0.001)
	{   
		x=0;
		y=0;
		for(i=0;i<ncpts;i++)
		{	
	      x+=C(ncpts-1,i)*N(u,i)*N((1-u),(ncpts-1-i))*p[i].x;
	      y+=C(ncpts-1,i)*N(u,i)*N((1-u),(ncpts-1-i))*p[i].y;
		}
		p1[num].x=x;
		p1[num].y=y;
		num++;
	}	

	    glPointSize(4.0);
	    glColor3f(0.0,0.0,0.0);
	    glBegin(GL_LINE_STRIP);
	    for(int k=0;k<1000;k++)
		  glVertex2f(p1[k].x,p1[k].y);
	    glEnd();
	    glFlush();
		return;
}



//输入新的控制点
static void mouse(int button, int state,int x,int y)
{
void display();
float wx,wy;
//鼠标未按下左键,不做响应
if(state!=GLUT_DOWN)
   return;
else 
	{if(button==GLUT_LEFT_BUTTON)
	{
//转换坐标
wx=(2.0*x)/(float)(width-1)-1.0;
wy=(2.0*(height-1-y))/(float)(height-1)-1.0;
//判断控制点数目是否超过最大值
if(ncpts==MAX_CPTX)
	return;
//存储控制点
cpts[ncpts].x=wx;
cpts[ncpts].y=wy;
ncpts++;
//绘制控制点
glColor3f(0.0,0.0,0.0);
glPointSize(5.0);
glBegin(GL_POINTS);
glVertex2f(wx,wy);
glEnd();
glFlush();
}
if(button==GLUT_RIGHT_BUTTON)
{
display();
drawBezier(cpts);
}
}
}
void display(void)
{
	int i;
    glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(0.0,0.0,0.0);
    glPointSize(5.0);
    glBegin(GL_POINTS);
    for (i = 0; i < ncpts; i++)
        glVertex2f(cpts[i].x,cpts[i].y);
    glEnd();
    glFlush();

}
//键盘回调函数
void keyboard(unsigned char key,int x,int y)
{
	switch (key)
    {
        case 'q': case 'Q':
            exit(0);
            break;
        case 'c': case 'C':
			ncpts = 0;
			glutPostRedisplay();
            break;
		case 'r': case 'R':
			ncpts--;
			glutPostRedisplay();
			break;
    }
}

//重绘函数
void reshape(int w,int h)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0,1.0,-1.0,1.0,-1.0,1.0);
glMatrixMode(GL_MODELVIEW);
glViewport(0,0,w,h);//调整视口
width=w;
height=h;
}
int main(int argc, char **argv)
{
//初始化
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGB);
glutInitWindowSize(width,height);
glutCreateWindow("zjc2012211763");
//注册回调函数
glutDisplayFunc(display);
glutMouseFunc(mouse);
glutKeyboardFunc(keyboard);
glutReshapeFunc(reshape);
glClearColor(1.0,1.0,1.0,1.0);
glColor3f(0.0,0.0,0.0);
glutMainLoop();
}






张竞成

www.zjc18.com

1
0
查看评论

OpenGL入门2——曲线生成算法

一、DDA算法       数字微分分析仪()
  • xiaoxiaoyusheng2012
  • xiaoxiaoyusheng2012
  • 2014-11-02 20:53
  • 2846

OPENGL绘制贝塞尔曲线

最终效果图:通过3个点形成一条贝塞尔曲线1. 鼠标问题在使用鼠标获取坐标的时候,要知道鼠标获取的坐标和屏幕坐标是不同的; openGL使用右手坐标 从左到右,x递增 从下到上,y递增 从远到近,z递增 而鼠标是从左到右增x,同时从上到下也是增y所以在求 y 的时候,用(屏幕大小...
  • qq_28057541
  • qq_28057541
  • 2016-05-03 16:02
  • 2657

OpenGL画曲线

void CShape::drawCurve() { glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_LINES); glPointSize(10.0f); glColor3f(0.0f, 1.0f, 0.0f); glVer...
  • ganpengjin1
  • ganpengjin1
  • 2014-05-29 11:20
  • 4825

OpenGL程序绘制贝塞尔曲线

  • 2014-05-06 11:02
  • 1.76MB
  • 下载

Bezier曲线原理

一、原理:        贝塞尔曲线于1962年,由法国工程师皮埃尔·贝塞尔(Pierre Bézier)所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计。贝塞尔曲线最初由Paul de Caste...
  • Joogle
  • Joogle
  • 2012-09-13 15:10
  • 22757

iOS开发之贝塞尔曲线绘制图形

UIBezierPath类可以创建基于矢量的路径,可以定义简单的形状,如椭圆或者矩形,或者有多个直线和曲线段组成的形状。 一、UIBezierPath使用: 1、创建path; 2、添加路径到path; 3、将path绘制出来; 1 //创建path 2 path = [UIBe...
  • wang_Bo_JustOne
  • wang_Bo_JustOne
  • 2017-07-29 15:04
  • 474

OpenGL绘制Bezier曲线

 项目要求: – 使用鼠标在屏幕中任意设置控制点,并生成曲线 – 使用鼠标和键盘的交互操作实现对曲线的修改。 项目总体介绍 本项目利用Bezier曲线生成算法生成可由用户自定义的曲线。可实现核心功能如下: 用户用鼠标左击屏幕任意处产生记录点。 ...
  • zjccoder
  • zjccoder
  • 2015-01-17 18:57
  • 4830

利用de Casteljau算法绘制Bezier曲线

之前直接用基计算的Bezier曲线,现在用de Casteljau再次对其进行实现,其主要原因是目前本人对递归的理解非常的不深。。然后之后在CAGD中又要用到大量的递归算法,那么还是从最简单的开始
  • lafengxiaoyu
  • lafengxiaoyu
  • 2016-05-02 14:54
  • 3547

贝塞尔曲线生成算法

Bezier曲线分为一次/二次/三次/多次贝塞尔曲线,之所以这么分是为了更好的理解其中的内涵。 一次贝塞尔曲线(线性Bezier),实际上就是一条连接两点的直线段。 二次贝塞尔曲线,就是两点间的一条抛物线,利用一个控制点来控制抛物线的形状。 三次贝塞尔曲线,则需要一个起点,一个终点,两个控...
  • devillixin
  • devillixin
  • 2014-10-08 17:32
  • 13995

利用MATLAB绘制Bezier曲线

暂时放弃了用opengl绘图。因为数据结构略复杂,暂时投奔了MATLAB的怀抱,下面利用MATLAB改写绘制Bezier曲线的代码 直接上代码,首先是直接利用基函数的绘制 function bezier( vertices ) %BEZIER 绘制Bezier曲线 Dim=size(vertice...
  • lafengxiaoyu
  • lafengxiaoyu
  • 2017-02-20 20:43
  • 3134
    个人资料
    • 访问:138677次
    • 积分:1883
    • 等级:
    • 排名:千里之外
    • 原创:37篇
    • 转载:8篇
    • 译文:2篇
    • 评论:44条
    我的个人介绍
    博客专栏