计算机图形学上机实验4_实现Bezier曲线和Bezier曲面的绘制
- 格式:doc
- 大小:347.50 KB
- 文档页数:10
淮阴工学院计算机科学系实验报告书课程名:《计算机图形学》题目:实验4 BEZIER曲线或B样条曲线的绘制班级:学号:姓名:评语:成绩:指导教师:批阅时间:年月日1、实验内容或题目编程实现三次BEZIER或B样条曲线的绘制。
2、实验目的与要求(1) 通过实验,进一步理解和掌握生成BEZIER或B样条曲线的算法;(2) 掌握BEZIER或B样条曲线的基本生成过程;(3) 通过编程,会在TC环境下编程实现三次BEZIER或B样条曲线的绘制。
3、实验步骤与源程序错误!未找到引用源。
实验步骤1、算法、原理清晰,有详细的设计步骤;2、依据算法、步骤或程序流程图,用C语言编写源程序;3、编辑源程序并进行调试;4、进行特殊模式的运行测试,并结合情况进行调整;5、对运行结果进行保存与分析;6、打印源程序或把源程序以文件的形式提交;7、按格式书写实验报告。
错误!未找到引用源。
源代码#include "graphics.h"float px[4]={ 50,80,120,140 };float py[4]={100,230,230,160};void Bezier(){float a0,a1,a2,a3,b0,b1,b2,b3;int k,x,y;float i,t,n=4;setcolor(15);for(k=0;k<3;k++){moveto(px[k],py[k]);lineto(px[k+1],py[k+1]);}setcolor(4);a0=px[0];a1=-3*px[0]+3*px[1];a2=3*px[0]-6*px[1]+3*px[2];a3=-px[0]+3*px[1]-3*px[2]+px[3];b0=py[0];b1=-3*py[0]+3*py[1];b2=3*py[0]-6*py[1]+3*py[2];b3=-py[0]+3*py[1]-3*py[k+2]+py[3];for(i=0;i<n;i+=0.001){t=i;x=a0+a1*t+a2*t*t+a3*t*t*t;y=b0+b1*t+b2*t*t+b3*t*t*t;if(i==0)moveto(x,y);lineto(x,y);}}void main(){int driver,mode;driver=DETECT;initgraph(&driver,&mode,"..\\bgi");Bezier();}4、测试数据与实验结果5、结果分析与实验体会通过这次实验,我初步熟悉了turboc 的运行环境。
实验四实现Bezier曲线的生成算法一、实验目的1、熟悉CDC图形程序库;2、掌握Bezier曲线的生成算法;3、掌握利用Bezier曲线生成复杂形状的曲线;二、实验性质验证性三、实验要求1、认真阅读本次实验的目的,了解本次实验要求掌握的内容;2、能够根据实验指导书的要求,完成相关的内容;四、实验内容(一)生成绘图应用程序的框架(如下图)具体实现见第一次实验,过程不再详细说明。
(二)在应用程序中增加菜单完成相关菜单的设计,具体的效果如下图所示,并设置好相关菜单消息的映射,具体的实现在前面的实验中介绍过,再此不在详细说明。
(三)在绘图函数中添加代码通过以上步骤,得到了与菜单对应的消息映射,就可以在函数中添加代码绘制图形了。
1、利用Bezier曲线的生成算法实现二次Bezier曲线的生成(算法的详细原理见教材)。
void CBezierV iew::OnBezier2(){// TODO: Add your command handler code hereCDC*pDC=GetDC();//得到绘图类指针RedrawWindow();//重绘窗口CPen bluepen(PS_SOLID,2,RGB(0,0,255));//创建画实线、线宽为2的蓝色画笔CPen *old=pDC->SelectObject(&bluepen);float x0=100,y0=100,x1=200,y1=50,x2=150,y2=250;float i,x,y,dt,t,n=30.0;dt=1/n;for(i=0;i<=n;i++){t=i*dt;x=x0*(1-t)*(1-t)+x1*2*t*(1-t)+x2*t*t;y=y0*(1-t)*(1-t)+y1*2*t*(1-t)+y2*t*t;if(i==0)pDC->MoveTo(x,y);pDC->LineTo(x,y);pDC->MoveTo(x0,y0);pDC->LineTo(x1,y1);pDC->LineTo(x2,y2);pDC->SelectObject(old);ReleaseDC(pDC);}由以上代码绘出的图形如下:2、利用Bezier曲线的生成算法实现二次Bezier曲线的生成(算法的详细原理见教材)。
实验四Bezier曲线的绘制1. 实验目的练习Bezier曲线的绘制和de Casteljau算法。
2. 实验内容和要求按要求完成如下一个作业,提交纸质实验报告,同时提交实验报告和代码的电子版。
实现Bezier曲线的de Casteljau递推算法,能够对任意介于0和1之间的参数t计算Bezier曲线上的点,然后依次连接这些点生成Bezier曲线。
要求:对[0,1]参数区间进行100等分。
控制点的数目至少为5个,即Bezier曲线的次数不低于4次。
de Casteljau算法用一个函数单独实现。
绘制Bezier曲线的同时还要绘制其控制多边形。
至少绘制两条Bezier曲线,具有不同的次数,颜色和曲线宽度。
3.算法描述Bezier Curve(贝塞尔曲线)是应用于二维图形应用程序的数学曲线。
曲线定义:起始点、终止点、控制点。
通过调整控制点,贝塞尔曲线的形状会发生变化。
1962年,法国数学家Pierre Bezier第一个研究了这种矢量绘制曲线的方法,并给出了详细的计算公式,因此按照这样的公式绘制出来的曲线就用他的姓氏来命名,称为贝塞尔曲线。
以下公式中:B(t)为t时间下点的坐标;P0为起点,Pn为终点,Pi为控制点。
一阶贝塞尔曲线如下,意义由 P0 至 P1 的连续点,描述的是一条线段:二阶贝塞尔曲线(抛物线:P1-P0为曲线在P0处的切线):原理:由 P0 至 P1 的连续点 Q0,描述一条线段。
由 P1 至 P2 的连续点 Q1,描述一条线段。
由 Q0 至 Q1 的连续点 B(t),描述一条二次贝塞尔曲线。
4. 源程序代码#include<C:\Include\GL\glut.h>#include<stdlib.h>#include<math.h>GLsizei winWidth = 600, winHeight = 600;GLfloat xwcMin = -150.0, xwcMax = 150.0;GLfloat ywcMin = -300.0, ywcMax = 300.0;class wcPt3D{public:GLfloat x, y, z; };void init(){glClearColor(1.0, 1.0, 1.0, 1.0); }void plotPoint(wcPt3D bezCurevePt){glBegin(GL_POINTS);glVertex2f(bezCurevePt.x, bezCurevePt.y);glEnd(); }void binomiaCoeffs(GLint n, GLint * C){GLint k, j;for (k = 0; k <= n; k++)C[k] = 1;for (j = n; j >= k + 1; j--)C[k] *= j;for (j = n - k; j >= 2; j--)C[k] /= j; }void computeBezPt(GLfloat u, wcPt3D * bezPt, GLint nCtrlPts, wcPt3D *CtrlPts, GLint *C){ GLint k, n = nCtrlPts - 1;GLfloat bezBlendFcn;bezPt->x = bezPt->y = bezPt->z = 0.0;for (k = 0; k<nCtrlPts; k++){bezBlendFcn = C[k] * pow(u, k) * pow(1 - u, n - k);bezPt->x += CtrlPts[k].x * bezBlendFcn;bezPt->y += CtrlPts[k].y * bezBlendFcn;bezPt->z += CtrlPts[k].z * bezBlendFcn; } }void bezier(wcPt3D * ctrlPts, GLint nCtrlPts, GLint nBezCurvePts){wcPt3D bezCurvePt;GLfloat u;GLint *C, k;C = new GLint[nCtrlPts];binomiaCoeffs(nCtrlPts - 1, C);for (k = 0; k <= nBezCurvePts; k++){u = GLfloat(k) / GLfloat(nBezCurvePts);computeBezPt(u, &bezCurvePt, nCtrlPts, ctrlPts, C);plotPoint(bezCurvePt); }delete[]C; }void displayFcn(void){GLint nCtrlPts = 5, nCtrlPts2 = 6, nBezCurvePts = 1000;wcPt3D ctrlPts[5] = { { -135.0, -59.0, 0.0 }, { -59.0, 95.0, 0.0 }, { 0.0, -40.0, 0.0 }, { 70.0, 120.0, 0.0 }, { 78, -125.0, 0.0 } };wcPt3D ctrlPts2[6] = { { -118.0, 20.0, 0.0 }, { -85.0, 45.0, 0.0 }, { -26.0, -126.0, 0.0 }, { 38.0, 88.0, 0.0 }, { 58.0, 188.0, 0.0 }, { 108.0, 98.0, 0.0 } }; glClear(GL_COLOR_BUFFER_BIT);glPointSize(6);glColor3f(0.0, 1.0, 1.0);bezier(ctrlPts, nCtrlPts, nBezCurvePts);glPointSize(5);glColor3f(1.0, 0.0, 1.0);bezier(ctrlPts2, nCtrlPts2, nBezCurvePts);glColor3f(0.0, 0.0, 1.0);glBegin(GL_LINES);glVertex2f(-135.0, -59.0);glVertex2f(-59.0, 95.0);glVertex2f(-59.0, 95.0);glVertex2f(0.0, -40.0);glVertex2f(0.0, -40.0);glVertex2f(70.0, 120.0);glVertex2f(70.0, 120.0);glVertex2f(78.0, -125.0);glVertex2f(-118.0, 20.0);glVertex2f(-85.0, 45.0);glVertex2f(-85.0, 45.0);glVertex2f(-26.0, -126.0);glVertex2f(-26.0, -126.0);glVertex2f(38.0, 88.0);glVertex2f(38.0, 88.0);glVertex2f(58.0, 188.0);glVertex2f(58.0, 188.0);glVertex2f(108.0, 98.0);glEnd();glFlush(); }void winReshapeFcn(GLint newWidth, GLint newHeight){glViewport(0, 0, newWidth, newHeight);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(xwcMin, xwcMax, ywcMin, ywcMax);glClear(GL_COLOR_BUFFER_BIT); }void main(int argc, char *argv[]){glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowPosition(50, 50);glutInitWindowSize(winWidth, winHeight);glutCreateWindow("yxl 实验四 Bezier曲线");init();glutDisplayFunc(displayFcn);glutReshapeFunc(winReshapeFcn);glutMainLoop(); }5. 实验结果6.实验体会最后一次实验报告了,老师要求我们做Bezier曲线,需要我们对函数去理解的一次实验,对于数学比较差的我来说还是很有困难的,理解起来比较吃力。
计算机图形学》实验报告(实验四,.Bezier曲线生成算法实现、实验目的及要求三次Bezier曲线及de Casteljau算法以及b样条曲线、理论基础详见教材!三、算法设计与分析Bezier 曲线生成算法int degree=3,i,x,y;float t;float coeff_x[4]={50.0,200.0,200.0,500.0};float coeff_y[4]={50.0,300.0,50.0,200.0};pDC->MoveTo(coeff_x[0],coeff_y[0];for(i=1;i<=3;i++ pDC->LineTo(coeff_x[i],coeff_y[i];for(t=0;t<=1;t+=0.001 x=hornbez(degree,coeff_x,t;y=hornbez(degree,coeff_y,t;pDC->SetPixel(x,y,RGB(0,0,0;float CMy2View::hornbez(int degree,float coeff[],float t int i,n_choose_i;float fact,t1,aux;t1=1.0-t;fact=1.0;n_choose_i=1;aux=coeff[0]*t1;for(i=1;i fact =fact*t;n_choose_i=n_choose_i*(degree-i+1/i;aux=(aux+fact*n_choose_i*coeff[i]*t1;aux=aux+fact*t*coeff[degree];return aux;de Casteljau 算法void CTuView::bezpoint(int degree,int npoints,float *coeff,float points[] float t,delt;int i;delt=1.0/(floatnpoints;t=0.0;for (i=0;i points[i]=decas(degree,coeff,t;t=t+delt;float CTuView::decas(int degree,float *coeff,float t int r,i;float t1;float coeffa[10];t1=1.0-t;for (i=0;i<=degree;i++ coeffa[i]=coeff[i];for(r=1;r<=degree;r++ for (i=0;i<=degree-r;i++ coeffa[i]=t1*coeffa[i]+t*coeffa[i+1];return coeffa[0];主函数:void CTuView::OnDraw(CDC* pDCCTuDoc* pDoc = GetDocument(;ASSERT_VALID(pDoc;// TODO: add draw code for native data here int degree=5,npoints=1000,i;float coeffx[]={10,40,265,300,400,500};float coeffy[]={20,130,160,90,300,100};float points1[1000],points2[1000];for (i=0;i pDC->MoveTo((intcoeffx[i],(intcoeffy[i];pDC->LineTo ((intcoeffx[i+1],(intcoeffy[i+1];bezpoint(degree,npoints,coeffx,points1;bezpoint(degree,npoints,coeffy,points2;for(i=0;ipDC->SetPixel((intpoints1[i],(intpoints2[i],RGB(123,12 3,123;B样条曲线void CBView::bsp(int degree,int l,float*coeff,float *knot,int dense,float *points,int *point_num int i,ii;float u;*point_num=0;for(i=degree-1;i if(knot[i+1]>knot[i] for(ii=0;iiu=knot[i]+ii*(knot[i+1]-knot[i]/dense;points[*point_num]=deboor(degree,coeff,knot,u,i;*point_num=(*point_num+1;float CBView::deboor(int degree,float *coeff,float*knot,float u,int i int k,j;float t1,t2;float coeffa[30];for (j=i-degree+1;j<=i+1;j++ coeffa[j]=coeff[j];for (k=1;k<=degree;k++ for(j=i+1;j>=i-degree+k+1;j-- t1=(knot[j+degree-k]-u/(knot[j+degree-k]-knot[j-1];t2=1.0-t1;coeffa[j]=t1*coeffa[j-1]+t2*coeffa[j];return coeffa[i+1];}主函数:void CBView::OnDraw(CDC* pDCCBDoc* pDoc = GetDocument(;ASSERT_VALID(pDoc;// TODO: add draw code for native data here int k,n; int degree,i,a;int dense=290,l=5;float coeffx[]={10,40,265,300,400,500,600};float coeffy[]={20,130,160,90,300,100,300};float points1[2000],points2[2000];float knot[]={0,0,0,0,0,1,2,2,2,2,2};int *point_num;k=5,n=5;/*n+1 个点*/ degree=5;a=0;point_num=&a;for (i=0;i<6;i++ pDC->MoveTo((intcoeffx[i],(intcoeffy[i]; pDC->LineTo ((intcoeffx[i+1],(intcoeffy[i+1];}bsp( degree,l,coeffx,k no t,de nse,poin ts1, point_num;bsp( degree,l,coeffy,k no t,de nse,poin ts2 ,point_num;for(i=0;i<2000;i++ p DC->Set Pi xel((i ntpoin ts1[i],(i ntpoin ts2[i],RGB(123,123,123;四、程序调试及结果的分析1、de Casteljau图形曲线四、实验心得及建议由于最近考试,这次的实验报告提交的比较晚。
计算机图形学作业3姓名学号班级作业内容绘制一个“Bezier”曲线效果截图关键程序(<40行) #include<gl/glut.h>void Initial(void){glClearColor(0,0,0,0);glLineWidth(1);GLfloat ControlP[4][3]={{-66,-88,0},{-44,55,0},{22,-33,0},{77,66,0}};glMap1f(GL_MAP1_VERTEX_3,0,1,3,4,*ControlP);glEnable(GL_MAP1_VERTEX_3);}void Display(void){glClear(GL_COLOR_BUFFER_BIT);glColor3f(1,0,0);glMapGrid1f(100,0,1);glEvalMesh1(GL_LINE,0,100);glFlush();}void Reshape(GLint newWidth,GLint newHeight){glViewport(0,0,newWidth,newHeight);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(-100,100,-100,100);}void main(){glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); //使用双缓存及RGB模型glutInitWindowSize(666, 488); //指定窗口的尺寸glutInitWindowPosition(288, 155); //指定窗口在屏幕上的位置glutCreateWindow("朱");Initial();glutDisplayFunc(Display);glutReshapeFunc(Reshape);glutMainLoop();}小结这一次的用OpenGL绘制贝塞尔曲线实验比上一次花了更长的时间,原来以为对OpenGL应该算是有了一些了解,这次实验过后发现,没搞明白的尚且有许多,更不用提还有许多根本不知道的应用方法。
计算机图形学课程实验 报 告实验题目 自由曲线和曲面的绘制 班 级 计算081 姓 名 杨 恒 学 号 3080811017 指导教师 胡钢 日 期 2011.6.3西安理工大学理学院应用数学系二零一一年春季学期信息与计算科学专业基础课 Computer GraphicsReport Of course experiment实验说明实验目的:掌握自由曲线和曲面(包括Bezier 曲线、曲面和B 样条曲线、曲面)的生成算法思想,并能上机编程绘制相应的曲线、曲面和利用曲线、曲面进行简单的几何造型设计。
实验地点: 教九楼401 数学系机房实验要求(Direction): 1.每个学生单独完成;2.开发语言为TurboC 或C++,也可使用其它语言;3.请在自己的实验报告上写明姓名、学号、班级;4.每次交的实验报告内容包括:题目、试验目的和意义、程序制作步骤、主程序、运行结果图以及参考文件;5. 自己保留一份可执行程序,考试前统一检查和上交。
实验内容实验题一1.1实验题目上机编写一个能绘制Bezier 曲线和B 样条曲线的通用程序,并调试成功。
具体要求为:(1)用户在运行程序时,可以根据提示信息来决定选择绘制Bezier 曲线,还是B 样条曲线;(2)两种曲线控制顶点的个数和坐标值要求可以随机输入(即Bezier 曲线和B 样条曲线的次数和位置可以随机输入);(3)当用户输入控制点的坐标位置后,屏幕上生成曲线的同时显示其特征多边形;且在特征多边形的顶点处输出该顶点坐标;(4)要求在可执行程序后附上运行结果(两种曲线都至少附上一个结果图)。
自由曲线和曲面的绘制实验41.2实验目的和意义掌握Bezier曲线和B样条曲线的绘制方法。
1.3程序制作步骤(包括算法的基本思想、流程图、设计步骤等)一、基本思想(1)Bezier曲线:是由一组折线来定义的,且第一个点和最后一个点在曲线上,第一条和最后一条折线分别表示出曲线在起点和终点处的切线方向。
Bezier 曲线绘制实验文档
2005.10
一、实验目的
编程实现中点分割法绘制Bezier曲线。
二、实现功能
实验程序通过OpenGL实现,可以通过鼠标单击左键绘制Bezier控制点,单击右键结束控制点绘制并显示Bezier曲线。
单击控制点可以选择控制点,这个时候可以通过拖拽移动控制点,同时Bezier曲线的变化也将反应;按键盘上的d可以删除控制点,i可以在这个控制点和下一个控制点的中点位置增加一个新的控制点。
按c可以清除所有内容以重新绘制。
通过上下键可以增加或者缩小阈值。
三、程序实现
1、Bezier曲线绘制算法
函数calBezier通过中点分割法绘制Bezier曲线。
利用递归的方法实现,calPiece是递归子函数。
算法伪码描述如下:
考虑到最后需要求出2n-1个控制点,因此预先将n个控制点间隔排列放到大小为2n-1的数组中。
之后对于每一层次的求解,将两个控制点的中点求出来的结果放到这两个控制点所在数组序号中间的位置即可。
如下表所示(4个控制点)。
表中红色的内容为每一个循环中需要计算的内容,使用其上一行中序号在前一位和后一位的控制点的中点。
最后结果前4项就是第一段Bezier曲线的控制点,后4项就是第二段Bezier曲线的控制点。
3、OpenGL函数
四、实验结果
在VS2003+WinXP平台下实现了程序。
计算机图形学实验报告实验名称 Bezier曲线和样条曲线的生成算法评分实验日期年月日指导教师姓名专业班级学号一、实验目的1、复习Bezier曲线和B样条曲线的参数表示法。
2、编程实现用二次Bezier曲线绘制。
3、编程实现用三次Bezier曲线绘制和分段光滑Bezier曲线图形的绘制。
4、用三次B样条函数绘制曲线。
二、实验要求1、编程实现在屏幕上绘制出两次Bezie曲线的几何图形和特征多边形图形,对于直线和曲线设置不同的线形和颜色。
2、现在屏幕上绘制出三次Bezie曲线的几何图形和特征多边形图形,对于直线和曲线设置不同的线形和颜色。
1、编程实现用分段三次Bezier曲线绘制光滑Bezier曲线图形。
1、编程实现在屏幕上绘制出三次B样条函数绘制曲线。
2、编程实现在屏幕上绘制出光滑连接的三次B样条曲线。
三、关键算法及实现原理1、二次Bezier曲线的计算公式为:P(t)=(P0-2P1+P2)t2+(-2P0+2P1)t+P0X(t)=(X0-2X1+X2)t2+(-2X0+2X1)t+X0Y(t)=(Y0-2Y1+Y2)t2+(-2Y0+2Y1)t+Y0其中P0、P1、P2为三个已知的点,坐标分别为(X0、Y0)、(X1、Y1)、(X1、Y2)。
2、次Bezier曲线的计算公式为:P(t)=(-P0+3P1-3P2+P3)t3+(3P0-6P1+3P2)t2+(-3P0+3P1)t+P0X(t)= (-X0+3X1-3X2+X3)t3+(3X0-6X1+3X2)t2+(-3X0+3X1)t+X0Y(t)= (-Y0+3Y1-3Y2+Y3)t3+(3Y0-6Y1+3Y2)t2+(-3Y0+3Y1)t+Y0其中P0、P1、P2、P3为四个已知的点,坐标分别为(X0、Y0)、(X1、Y1)、(X1、Y2) 、(X3、Y3)。
3、三次B样条函数绘制曲线的计算公式为:P(t)=[(-P0+3P1-3P2+3P3)t3+(3P0-6P1+3P2)t2+(-3P0+3P2)t+(P0+4P1+P2)]/6X(t)=[(-X0+3X1-3X2+3X3)t3+(3X0-6X1+3X2)t2+(-3X0+3X2)t+(X0+4X1+X2)]/6Y(t)=[(-Y0+3Y1-3Y2+3Y3)t3+(3Y0-6Y1+3Y2)t2+(-3Y0+3Y2)t+(Y0+4Y1+Y2)]/6其中P0、P1、P2、P3为四个已知的点,坐标分别为(X0、Y0)、(X1、Y1)、(X1、Y2) 、(X3、Y3)。
计算机图形学实验报告班级计算机工硕班学号 2011220456姓名王泽晶实验三:Bezier 曲线实验目的:通过本次试验,学生可以掌握Bezier 曲线的求值、升阶算法及Bezier 曲线绘制方法。
实验内容:1. 绘制控制多边形(使用鼠标左键指定多边形顶点,右键结束),使用白色折线段表示。
2. 绘制Bezier 曲线,使用红色,线宽为2,在右键结束控制多边形顶点指定时即执行。
Bezier 曲线是一种广泛应用于外形设计的参数曲线,它通过对一些特定点的控制来控制曲线的形状,我们称这些点为控制顶点。
现在我们来给出Bezier 曲线的数学表达式。
在空间给定1n +个点012,,,,n P P P P ,称下列参数曲线为n 次Bezier 曲线:,0()(),01ni i n i P t P B tt ==≤≤∑ 其中,()i n B t 是Bernstein 基函数,其表达式为:,!()(1)!()!i n ii n n B t t t i n i -=--,接着我们讨论3次Bezier 曲线,我们也采用将表达式改写为矩阵形式的方法,我们得到:3303!()(1)!(3)!i i ii P t P t t i i -==--∑32230123(1)3(1)3(1)t P t t P t t P t P =-+-+-+01323232323331,363,33,P P t t t t t t t t t P P ⎡⎤⎢⎥⎢⎥⎡⎤=-+-+-+-+⎣⎦⎢⎥⎢⎥⎣⎦01322313313630,,,133001000P P t t t P P --⎡⎤⎡⎤⎢⎥⎢⎥-⎢⎥⎢⎥⎡⎤=⎣⎦⎢⎥⎢⎥-⎢⎥⎢⎥⎣⎦⎣⎦试验步骤:添加成员函数,编写成员数代码为public class Al_deCasteljau {public function Al_deCasteljau(){}// de Casteljau递推算法的实现public function recursion( ctrlPts:Array, k:int , i:int ,t:Number ):Point {if ( k==0 ) return ctrlPts[i];return addPoints(multiplyNumToPoint((1 - t),recursion(ctrlPts, k-1, i, t)), multiplyNumToPoint(t , recursion(ctrlPts, k-1, i+1, t)));}public function multiplyNumToPoint(n:Number,p:Point):Point{return new Point(p.x * n,p.y * n);}public function addPoints(p1:Point,p2:Point):Point{return new Point(p1.x + p2.x,p1.y + p2.y);}public function minusPoints(p1:Point,p2:Point):Point{return new Point(p1.x - p2.x,p1.y - p2.y);}public function algorithm_deCasteljau(t:Number, ctrlPts:Array ):Point{var size:int = ctrlPts.length;return recursion( ctrlPts, size-1, 0, t );}public function upgradePoints(ctrlPts:Array):Array{var size:int = ctrlPts.length;var newPts:Array = new Array();newPts[0] = ctrlPts[0]; // i = 0for ( var i:int =1; i<size; ++i ){var factor:Number = i / size;newPts[i] = addPoints(multiplyNumToPoint( factor , ctrlPts[i-1] ) , multiplyNumToPoint((1 - factor) , ctrlPts[i]));}newPts[size] = ctrlPts[ctrlPts.length-1]; // i = n+1return newPts;}public function downgradePoints(ctrlPts:Array):Array{var size:int = ctrlPts.length;var newPts:Array = new Array();newPts[0] = ctrlPts[0]; // i = 0for ( var i:int=1; i<size-1; ++i ){var factor:Number = 1.0 /(size-1 - i);newPts[i] = multiplyNumToPoint(factor,minusPoints(multiplyNumToPoint(size-1 , ctrlPts[i]), multiplyNumToPoint(i , newPts[i-1])));}return newPts;}}编译运行得到如下结果:。
计算机图形学实验4-----HermiteBezierB样条三种曲线的绘制实验四 Hermite Bezier B样条三种曲线的绘制⼀、实验⽬的了解和学习Hermite、Bezier、B样条三种曲线算法掌握基于 Win32、Visual C++环境MFC绘制图形配置过程制过程编程实现Hermite、Bezier、B样条三种曲线的绘制⼆、实验原理三次参数曲线1.曲线段可以⽤端点、切向量和曲线段之间的连续性等约束条件来定义2.两个端点和两端点处的切向量定义Hermite曲线;3.两个端点和另外两个控制端点切向量的点定义的Bezier曲线;4.由四个控制顶点定义的样条曲线。
三、实验关键代码void CDrawYTQXView::Hermite() //绘制Hermite三次插值样条{int a[4][4] ={{2,-2,1,1},{-3,3,-2,-1},{0,0,1,0},{1,0,0,0}};//Mh 矩阵系数int b[4][2];//边界点for(int i=0;i<4;i++){b[0][0]=p1[i][0];b[0][1]=p1[i][1];//起点的坐标b[1][0]=p1[i+1][0];b[1][1]=p1[i+1][1];//终点的坐标b[2][0]=p2[i][0];b[2][1]=p2[i][1];//起点的导数b[3][0]=p2[i+1][0];b[3][1]=p2[i+1][1];//终点的导数Caculate(a,b);CClientDC dc(this);CPen MyPen,*pOldPen;MyPen.CreatePen(PS_SOLID,1,RGB(0,0,255));pOldPen=dc.SelectObject(&MyPen);dc.MoveTo(p1[i][0],p1[i][1]);for(double t=0.0;t<=1;t+=1.0/400){int x=ROUND(pow(t,3)*result[0][0]+pow(t,2)*result[1][0]+ t*result[2][0]+result[3][0]);int y=ROUND(pow(t,3)*result[0][1]+pow(t,2)*result[1][1]+ t*result[2][1]+result[3][1]);dc.LineTo(x,y);}dc.SelectObject(pOldPen);MyPen.DeleteObject();}}void CDrawYTQXView::Caculate(int a[4][4],int b[4][2])//矩阵相乘{ int i,j,k;for(i=0;i<4;i++)for(j=0;j<2;j++)result[i][j]=0; //矩阵清零for(i=0;i<2;i++)for(j=0;j<4;j++)for(k=0;k<4;k++)result[j][i]+=a[j][k]*b[k][i];}void CDrawYTQXView::DrawBezier()//绘制Bezier曲线{CClientDC dc(this);double x,y;int rate=400,n;n=CtrlPoint-1;for(double t=0;t<=1;t+=1.0/rate){x=0;y=0;for(int i=0;i<=n;i++){x+=pt[i].x*Cnk(n,i)*pow(t,i)*pow(1-t,n-i);y+=pt[i].y*Cnk(n,i)*pow(t,i)*pow(1-t,n-i);}dc.SetPixel(ROUND(x),ROUND(y),RGB(0,0,255)); //曲线颜⾊}}double CDrawYTQXView::Cnk(const int &n, const int &i)//Bernstein 第⼀项{return double(Factorial(n)/(Factorial(i)*Factorial(n-i)));}int CDrawYTQXView::Factorial(int m)//阶乘函数{int f=1;for(int i=1;i<=m;i++)f*=i;return f;}void CDrawYTQXView::DrawB3_curves() //绘制B样条曲线{CClientDC dc(this);int i,rate=10,m;long lx,ly;m=CtrlPoint-(3+1);double F03,F13,F23,F33;lx=ROUND((pt[0].x+4.0*pt[1].x+pt[2].x)/6.0); //t=0的起点x坐标ly=ROUND((pt[0].y+4.0*pt[1].y+pt[2].y)/6.0);//t=0的起点y坐标dc.MoveTo(lx,ly);CPen MyPen2,*pOldPen2;MyPen2.CreatePen(PS_SOLID,2,RGB(0,0,255)); //颜⾊设置pOldPen2=dc.SelectObject(&MyPen2);for(i=1;i{for(double t=0;t<=1;t+=1.0/rate){F03=(-t*t*t+3*t*t-3*t+1)/6;//计算F0,3(t)F13=(3*t*t*t-6*t*t+4)/6;//计算F1,3(t)F23=(-3*t*t*t+3*t*t+3*t+1)/6;//计算F2,3(t)F33=t*t*t/6;//计算B3,3(t)lx=ROUND(pt[i-1].x*F03+pt[i].x*F13+pt[i+1].x*F23+pt[i+2].x*F33 );。
昆明理工大学理学院信息与计算科学专业操作性实验报告年级: 10级姓名:刘陈学号: 201011101128 指导教师:胡杰实验课程名称:计算机图形学程序设计开课实验室:理学院机房216 实验成绩:学风(5)观察能力(15)操作能力(30)调试能力(50)其它总分实验内容:1.实验/作业题目:用计算机高级语言VC++6.0实现计算机的基本图元绘制2.实验/作业课时:2学时3.实验过程(包括实验环境、实验内容的描述、完成实验要求的知识或技能):实验环境:(1)硬件:每人一台PC机(2)软件:windows OS,VC++6.0或以上版本。
试验内容及步骤:(1)在VC++环境下创建MFC应用程序工程(单文档)(2)编辑菜单资源(3)添加菜单命令消息处理函数(4)添加成员函数(5)编写函数内容试验要求:(1)掌握Bezier曲线、Bezier曲面、及另一个曲面的算法。
(2)实现对Bezier曲线、Bezier曲面、及另一个曲面。
(3)试验中调试、完善所编程序,能正确运行出设计要求结果。
(4)书写试验报告上交。
4.程序结构(程序中的函数调用关系图)5.算法描述、流程图或操作步骤:在lab4iew.cpp文件中添加如下头文件及变量int flag_2=0;int n_change;#define M 30#define PI 3.14159 //圆周率#include "math.h" //数学头文件在lab4iew.h文件中的public内添加变量:int move;int graflag;void Tiso(float p0[3],float x0, float y0, float p[3]);void OnBezierface();在lab4iew.h文件中的protected内添加变量:int n;//控制点数const int N;//控制点数的上限CPoint* a;//控制点存放的数组double result[4][2];在lab4iew.cpp文件中的函数Clab4iew::OnDraw(CDC* pDC)下添加如下代码:int i,j;for(i=0;i<n;i++){pDC->FillSolidRect(a[i].x-2,a[i].y-2,4,4,RGB(255,55,255));}pDC->MoveTo(a[0]);for(j=0;j<n;j++){ pDC->LineTo(a[j]); }if(n<2) return;//如果控制点数少于2,则不用画CPen pen(0,2,RGB(255,0,255)),*p1;p1=pDC->SelectObject(&pen);……在Lab4iew.cpp文件中添加如下的各个消息处理函数及代码:void CLab4View::OnLButtonDown(UINT nFlags, CPoint point){ if(flag_2==0) //flag_2等于0,此时是输入控制点状态{ CClientDC dc(this); //实时输入一个控制点,在屏幕上显示此点dc.FillSolidRect(point.x-2,point.y-2,4,4,RGB(0,0,255));if(n<N){a[n++]=point;} //给控制点数组a[]赋值else {MessageBox("控制点太多!","waring",MB_OK|MB_ICONINFORMATION);}}else if(flag_2==1) //flag_2等于1,此时是修改控制点状态{ int i;for(i=0;i<n;i++) {if((abs(point.x-a[i].x)<10)&&(abs(point.y-a[i].y)<10)) //给定一个范围,如果在范围内,则选中该控制点{ n_change=i; }}CClientDC dc(this); //如果选中该点,则该点的颜色发生变化dc.FillSolidRect(a[n_change].x-2,a[n_change].y-2,4,4,RGB(255,255,0));}CView::OnLButtonDown(nFlags, point);}void CLab4View::OnLButtonUp(UINT nFlags, CPoint point){ if(flag_2==1) {a[n_change]=point; //给变换的点赋值Invalidate(true); //调用OnDraw函数,重新画控制多边形}CView::OnLButtonUp(nFlags, point);}void CLab4View::OnMouseMove(UINT nFlags, CPoint point){if(flag_2==1) {if(nFlags==MK_LBUTTON){ a[n_change]=point;Invalidate(true); }}CView::OnMouseMove(nFlags, point);}void CLab4View::Ondrawbezier(){move=0; graflag=1; Invalidate(true); flag_2=1;}void CLab4View::OnRButtonDown(UINT nFlags, CPoint point){ CRect rc; //点右键,刷新屏幕,使控制定点数归零,并且所有开关变量变为初试值GetClientRect(&rc);CClientDC dc(this);dc.Rectangle(0,0,rc.right,rc.bottom); //清屏n=0; //控制点数归零flag_2=0; //开关变量变为初试值CView::OnRButtonDown(nFlags, point);}void CLab4View::OnMove(){ move=1; flag_2=1;CClientDC dc(this);int i=0;while (i<n){ a[i].y=a[i].y+50; i++; }Invalidate(true); }void CLab4View::OnBezierface(){ Invalidate(true);UpdateWindow();CClientDC dc(this);dc.SetTextColor(RGB(0,0,255));dc.TextOut(160,160,"Bezier曲面");CPen pen1,pen2;pen1.CreatePen(PS_SOLID,1,RGB(255,0,0));pen2.CreatePen(PS_SOLID,3,RGB(0,0,255));int a[24][2]={{100,400},{110,300},{130,250},{150,350}, {200,300},{210,280},{250,200},{280,250},{300,320},{300,280},{330,180},{360,250},{400,400},{380,320},{410,200},{480,280}};int i,j;dc.SelectObject(&pen2);for(i=0;i<16;i=i+4){ dc.MoveTo(a[i][0],a[i][1]);for(j=0;j<4;j++){ dc.LineTo(a[i+j][0],a[i+j][1]); }}for(i=0;i<4;i++){ dc.MoveTo(a[i][0],a[i][1]);for(j=0;j<16;j=j+4){ dc.LineTo(a[i+j][0],a[i+j][1]); }dc.SelectObject(&pen2);}double x,y; x=a[0][0]; y=a[0][1]; dc.MoveTo(x,y);dc.SelectObject(&pen1);double u,w;for(u=0;u<1;u=u+0.01){ double U0=-u*u*u+3*u*u-3*u+1;double U1=3*u*u*u-6*u*u+3*u;double U2=-3*u*u*u+3*u*u;double U3=u*u*u;x=U0*a[0][0]+U1*a[4][0]+U2*a[8][0]+U3*a[12][0];y=U0*a[0][1]+U1*a[4][1]+U2*a[8][1]+U3*a[12][1];dc.MoveTo(x,y);for(w=0;w<1;w=w+0.01){ double W0=-w*w*w+3*w*w-3*w+1;double W1=3*w*w*w-6*w*w+3*w;double W2=-3*w*w*w+3*w*w;double W3=w*w*w;x=((U0*a[0][0]+U1*a[4][0]+U2*a[8][0]+U3*a[12][0])*W0 +(U0*a[1][0]+U1*a[5][0]+U2*a[9][0]+U3*a[13][0])*W1+(U0*a[2][0]+U1*a[6][0]+U2*a[10][0]+U3*a[14][0])*W2+(U0*a[3][0]+U1*a[7][0]+U2*a[11][0]+U3*a[15][0])*W3);y=((U0*a[0][1]+U1*a[4][1]+U2*a[8][1]+U3*a[12][1])*W0 +(U0*a[1][1]+U1*a[5][1]+U2*a[9][1]+U3*a[13][1])*W1+(U0*a[2][1]+U1*a[6][1]+U2*a[10][1]+U3*a[14][1])*W2+(U0*a[3][1]+U1*a[7][1]+U2*a[11][1]+U3*a[15][1])*W3);dc.LineTo(x,y);Sleep(1);}}for(w=0;w<1;w=w+0.01){ double W0=-w*w*w+3*w*w-3*w+1;double W1=3*w*w*w-6*w*w+3*w;double W2=-3*w*w*w+3*w*w;double W3=w*w*w;x=W0*a[0][0]+W1*a[1][0]+W2*a[2][0]+W3*a[3][0];y=W0*a[0][1]+W1*a[1][1]+W2*a[2][1]+W3*a[3][1];dc.MoveTo(x,y);for(u=0;u<1;u=u+0.01){ double U0=-u*u*u+3*u*u-3*u+1;double U1=3*u*u*u-6*u*u+3*u;double U2=-3*u*u*u+3*u*u;double U3=u*u*u;x=((U0*a[0][0]+U1*a[4][0]+U2*a[8][0]+U3*a[12][0])*W0+(U0*a[1][0]+U1*a[5][0]+U2*a[9][0]+U3*a[13][0])*W1+(U0*a[2][0]+U1*a[6][0]+U2*a[10][0]+U3*a[14][0])*W2+(U0*a[3][0]+U1*a[7][0]+U2*a[11][0]+U3*a[15][0])*W3);y=((U0*a[0][1]+U1*a[4][1]+U2*a[8][1]+U3*a[12][1])*W0+(U0*a[1][1]+U1*a[5][1]+U2*a[9][1]+U3*a[13][1])*W1+(U0*a[2][1]+U1*a[6][1]+U2*a[10][1]+U3*a[14][1])*W2+(U0*a[3][1]+U1*a[7][1]+U2*a[11][1]+U3*a[15][1])*W3);dc.LineTo(x,y);Sleep(1);}}pen2.DeleteObject();pen1.DeleteObject();}void CLab4View::OnAreaRing(){ RedrawWindow();CDC*pDC=GetDC();pDC->TextOut(200,80,"圆环曲面");floatpp0[2],p[3],pp[3],R,du=3.1415926/100,dv=3.1415926/50,x0=300,y0=100,u=0,v= 0;pp0[0]=200,pp0[1]=200,R=50;p[0]=(pp0[0]+R*sin(u))*cos(v);p[1]=(pp0[0]+R*sin(u))*sin(v);p[2]=pp0[1]+R*cos(u);Tiso(p,x0,y0,pp);pDC->MoveTo(pp[0],pp[1]);for(v=1;v<=360;v++){ for(u=1;u<=360;u++){ p[0]=(pp0[0]+R*sin(u))*cos(v);p[1]=(pp0[0]+R*sin(u))*sin(v);p[2]=pp0[1]+R*cos(u);Tiso(p,x0,y0,pp);pDC->LineTo(pp[0],pp[1]);}}ReleaseDC(pDC);}void CLab4View::Tiso(float p0[3],float x0, float y0, float p[3]) { p[0]=0.7071*(p0[0]-p0[1])+x0;p[2]=0;p[1]=-0.4082*(p0[0]+p0[1])+0.8165*p0[2]+y0;}6.实验数据和实验结果(用屏幕图形表示,可另加附页):打开Dubug内lab4.exe在工作区绘画点,再点击菜单栏“Bezier曲线”,,画出Bezier曲线。
贝塞尔曲线(Bezier Curve)和B样条(B-Spline)是计算机图形学中常用的两种曲线生成方法,它们在图形设计、动画制作、CAD软件等领域被广泛应用。
本文将从贝塞尔曲线和B样条的生成原理入手,深入探讨它们的内在机制和应用。
一、贝塞尔曲线的生成原理贝塞尔曲线是一种由法国工程师皮埃尔·贝塞尔(Pierre Bézier)于1962年在汽车工业中首次引入的曲线生成方法。
其生成原理基于一组控制点来描述曲线的形状,这组控制点通过线性插值的方式来确定曲线的路径。
贝塞尔曲线的生成过程可以简要描述如下:1. 定义控制点:从给定的控制点集合中选择若干个点作为曲线的控制点。
2. 插值计算:根据控制点的位置和权重,通过插值计算得到曲线上的点。
3. 曲线绘制:利用插值计算得到的曲线上的点,进行绘制来呈现出贝塞尔曲线的形状。
在具体应用中,贝塞尔曲线的生成可以通过线性插值、二次插值和三次插值等不同插值方式来实现,其中三次插值的贝塞尔曲线应用最为广泛,其生成原理更为复杂,但也更为灵活。
二、B样条的生成原理B样条(B-Spline)是另一种常用的曲线生成方法,在实际应用中具有一定的优势。
B样条的生成原理与贝塞尔曲线不同,它是基于多项式函数的分段插值来描述曲线的形状。
B样条的生成过程可以简要描述如下:1. 定义控制点和节点向量:B样条需要定义一组控制点和一组节点向量(Knot Vector)来描述曲线的形状。
2. 基函数计算:根据节点向量和控制点,计算出关联的基函数(Basis Function)。
3. 曲线计算:利用基函数和控制点的权重,通过计算得到曲线上的点。
相比于贝塞尔曲线,B样条更为灵活,可以更精细地描述曲线的形状,并且能够进行局部编辑,使得曲线的变形更加方便。
三、应用比较与总结贝塞尔曲线和B样条是两种常用的曲线生成方法,它们各自具有一些优势和劣势,在实际应用中需要根据具体情况做出选择。
1. 灵活性比较:B样条相对于贝塞尔曲线更加灵活,能够更精细地描述曲线的形状,并且能够进行局部编辑,使得曲线的变形更加方便。
贵州大学实验报告
学院:计算机科学与信息学院专业:计算机科学与技术班级:101记为:G=A•M
可将其简记为:
上式是三次Hermite(Ferguson)曲线的几何形式。
几何系数是P0、P1、P’0、P’1。
构成该Bézier曲线的特征多边形,
Bézier曲线
样条曲线
B样条基函数代替Bernstein
样条曲线的突出优点是对曲线的局部修改功能,因为
,所以控制多边形的顶点对曲线的控制灵活而直观。
样条曲线的次数可根据需要指定,不像Bezier曲线的次数是由控制点的个数来确定。
阶数k,控制顶点数n+1,节点个数m+1,具有以下关系: m=n+k
记T为:Tn,k={ti}(ti≤ti+1 ,i=0,1,2,…,n,…,n+k)
(5). 3次Bézier曲面的矩阵表达式:Microsoft Visual Studio 6.0
2、在zjie_BView.h文件中声明成员函数和变量:
2.点击绘制三次B样条曲线:
三.绘制Bezier曲线:
1.点击绘制Bezier曲线:
、四次Bezier曲线:
点击绘制曲面:。
《计算机图形学》实验4实验报告实验题目:参数曲线绘制实验内容:1 圆的参数曲线绘制。
2显式数学曲线描绘程序。
3贝赛尔曲线绘制。
编写程序调用验证之。
参考资料:1 circleParam.java2 explicitCurve.java3 BezierLine.java4 数学曲线绘制.ppt和实验3的参考ppt基本概念:1、圆的参数曲线绘制:圆的参数曲线绘制就是按照圆的定义,利用步长,得在显示域上每一点的位置,然后绘制。
圆是图形中经常使用的元素,圆被定义为所有离一中心位置(xc,yc)距离为给定值R的点集。
2、显示数学曲线描绘程序:显示曲线的绘制就是在已知的坐标系上,按照方程要求在固定的点画点,然后连接成一条线。
3、贝塞尔曲线的绘制:贝赛尔曲线的每一个顶点都有两个控制点,用于控制在顶点两侧的曲线的弧度。
它是应用于二维图形应用程序的数学曲线。
曲线的定义有四个点:起始点、终止点(也称锚点)以及两个相互分离的中间点。
滑动两个中间点,贝塞尔曲线的形状会发生变化。
算法设计:1、圆的算法设计:本例程体现的主要是圆的快速算法,这里的主要算法是:X=Xc +RcostY=Yc+Rsint 0<t≤2t是圆的某一点与X轴之间的夹角。
Xc和Yc分别是圆的中心,以上一个终点为下一个的起点。
改变t的值,就可以得到一个圆。
体现在代码中就是://圆的参数曲线x=f(t)private double fx(double t) {return Math.cos(t)+0.2;}//圆的参数曲线y=f(t)private double fy(double t) {return Math.sin(t)+0.2;}2、显示数学曲线绘制:利用微分方法进行绘制,将曲线x轴分割成足够小的间距,利用绘制的公式计算出每一个x所对应的y的坐标,然后在该坐标上画点(本程序绘制函数y=x*x-x-2)数图像从x=-4.0开始绘制,分割间距为0.05,即从x=-4.0绘制到x=4.0要走过160步,在该程序中用变量x表示开始绘图的x坐标,用变量deltaX表示每次分割的最小长度,即步长,利用所绘制的公式计算出y轴坐标,然后利用循环绘制出函数图像,体现在代码中就是://描绘曲线y=x^2-x-2private double f(double x) {return (x-2)*(x+1);}3、绘制:绘制分为两部分,一部分是节点的绘制,一部分是曲线线段的绘制,在该程徐序中定义了8个节点坐标,然后在该节点上绘制一个实心圆(红色表示),再绘制直线连接每两个相邻节点,共计8个节点7条线段,再利用微分的思想,将该范围内的x轴切分,该程序中是以变量t表示,切分大小为0.01,利用公式求解出对应的y轴坐标,然后利用绘制短直线的方法绘制相邻两个点之间的线段(蓝色表示),最后从最左节点绘制到最右节点坐标后结束绘制。
bezier曲线绘制算法贝塞尔曲线绘制算法贝塞尔曲线是一种常用于计算机图形学中的数学曲线,具有平滑弯曲的特性。
通过控制点的位置和数量,可以绘制出各种形状的曲线,如圆弧、曲线等。
本文将介绍贝塞尔曲线绘制算法的基本原理和实现方法。
1. 贝塞尔曲线的基本概念贝塞尔曲线由两个或多个控制点决定,通过这些控制点的位置,可以确定曲线的形状和轨迹。
其中,起始点和结束点称为锚点,而其他点称为控制点。
贝塞尔曲线的形状由控制点之间的插值和权重决定,权重决定了每个控制点对曲线形状的影响程度。
2. 二次贝塞尔曲线绘制算法二次贝塞尔曲线由三个点决定,分别是起始点P0、控制点P1和结束点P2。
绘制二次贝塞尔曲线的算法如下:(1) 将曲线分为若干个线段,每段用t从0到1进行插值。
(2) 根据插值参数t,计算控制点P0、P1和P2在x和y轴上的值。
(3) 绘制连接P0和P1的线段,连接P1和P2的线段。
3. 三次贝塞尔曲线绘制算法三次贝塞尔曲线由四个点决定,分别是起始点P0、控制点P1、P2和结束点P3。
绘制三次贝塞尔曲线的算法如下:(1) 将曲线分为若干个线段,每段用t从0到1进行插值。
(2) 根据插值参数t,计算控制点P0、P1、P2和P3在x和y轴上的值。
(3) 绘制连接P0和P1的线段,连接P1和P2的线段,以及连接P2和P3的线段。
4. 高阶贝塞尔曲线的绘制算法除了二次和三次贝塞尔曲线,还存在更高阶的贝塞尔曲线。
对于n 阶贝塞尔曲线,需要n+1个点来确定。
其绘制算法与二次和三次贝塞尔曲线类似,通过插值参数t来计算各个控制点的值,并连接相邻控制点。
5. 贝塞尔曲线的应用贝塞尔曲线在计算机图形学中有广泛的应用,常用于绘制平滑曲线、图形变形、字体设计等方面。
在计算机动画、游戏开发等领域,贝塞尔曲线的应用也非常广泛。
贝塞尔曲线是一种常用于计算机图形学中的数学曲线,通过控制点的位置和数量,可以绘制出各种形状的曲线。
本文介绍了贝塞尔曲线的基本概念,以及二次、三次和高阶贝塞尔曲线的绘制算法。
/*1.实现Bezier曲线2.数据由data.in读入,其格式为:点数各个点坐标例如:410 15050 50150 50190 1503.可以实现100阶以内Bezier*/#include <windows.h>#include <stdio.h>#include <vector>using namespace std;LRESULT CALLBACK WinSunProc(HWND hwnd, // handle to windowUINT uMsg, // message identifierWPARAM wParam, // first message parameter LPARAM lParam // second message parameter);void MidpointLine(int x0, int y0, int x1, int y1, HWND hwnd); void bezier(HWND hwnd);int cnt = 0;const int MAX = 105;const int COUNT = 1000;int n;int ptr;struct Point{double x, y;};vector<Point> p[2], vec;int WINAPI WinMain(HINSTANCE hInstance, // handle to current instance HINSTANCE hPrevInstance, // handle to previous instanceLPSTR lpCmdLine, // command lineint nCmdShow // show state){WNDCLASS wndcls;wndcls.cbClsExtra=0;wndcls.cbWndExtra=0;wndcls.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);wndcls.hCursor=LoadCursor(NULL,IDC_CROSS);wndcls.hIcon=LoadIcon(NULL,IDI_ERROR);wndcls.hInstance=hInstance;wndcls.lpfnWndProc=WinSunProc;wndcls.lpszClassName="Ted";wndcls.lpszMenuName=NULL;wndcls.style=CS_HREDRAW | CS_VREDRAW;RegisterClass(&wndcls);HWND hwnd;hwnd=CreateWindow("Ted","XukeIsDaHaoRen!",WS_OVERLAPPEDWINDOW, 0,0,600,400,NULL,NULL,hInstance,NULL);ShowWindow(hwnd,SW_SHOWNORMAL);UpdateWindow(hwnd);MSG msg;while(GetMessage(&msg,NULL,0,0)){TranslateMessage(&msg);DispatchMessage(&msg);}return 0;}LRESULT CALLBACK WinSunProc(HWND hwnd, // handle to windowUINT uMsg, // message identifierWPARAM wParam, // first message parameterLPARAM lParam // second message parameter){switch(uMsg){case WM_CHAR:char szChar[20];sprintf(szChar,"char is %d",wParam);MessageBox(hwnd,szChar,"Nothing",0);break;case WM_LBUTTONDOWN:MessageBox(hwnd,"Waiting...","Performance",0);//HDC hdc;//hdc=GetDC(hwnd);//MidpointLine(100, 100, 200, 200, hwnd);bezier(hwnd);break;case WM_PAINT:HDC hDC;PAINTSTRUCT ps;hDC=BeginPaint(hwnd,&ps);TextOut(hDC,0,0,"By Ted",strlen("By Ted"));EndPaint(hwnd,&ps);break;case WM_CLOSE:if(IDYES==MessageBox(hwnd,"Quit?(Y/N)"," ",MB_YESNO)){DestroyWindow(hwnd);}break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hwnd,uMsg,wParam,lParam);}return 0;}int curPtr(){return ptr % 2;}int prePtr(){return (ptr + 1) % 2;}Point cut(Point p1, Point p2, double t){Point temp;temp.x = p1.x + t * (p2.x - p1.x);temp.y = p1.y + t * (p2.y - p1.y);return temp;}Point deCasteljau(double t){//Point temp;for(int i = 0; i < n - 1; i++){int cur = curPtr(), pre = prePtr();p[pre].clear();for(int j = 0; j < (int)p[cur].size() - 1; j++){Point temp = cut(p[cur][j], p[cur][j + 1], t);p[pre].push_back(temp);}++ptr;}int cur = curPtr();return p[cur][0];}void bezier(HWND hwnd){HDC dc;dc = GetDC(hwnd);int i;Point temp;FILE *fp = fopen("data.in", "r");fscanf(fp, "%d\n", &n);//char str[20];//sprintf(str, "%d\n", n);//MessageBox(hwnd,"Waiting...",str,0);for(i = 0; i< n; i++){fscanf(fp, "%lf %lf\n", &temp.x, &temp.y);vec.push_back(temp);}//HDC dc;//dc = GetDC(hwnd);for(i = 0; i < (int)vec.size(); i++){SetPixel(dc, (int)vec[i].x, (int)vec[i].y, RGB(255,0,0));if(i < (int)vec.size() - 1){MoveToEx(dc, (int)vec[i].x, (int)vec[i].y, (LPPOINT) NULL);//MoveToEx(hdc, (int) 110, (int) 110, (LPPOINT) NULL);LineTo(dc, (int)vec[i + 1].x, (int)vec[i + 1].y);}}for(int t = 0; t <= COUNT; t++){ptr = 0;p[ptr] = vec;temp = deCasteljau((double)((double)t / (double)COUNT));SetPixel(dc, (int)temp.x, (int)temp.y, RGB(255,0,0));}return ;}void MidpointLine(int x0, int y0, int x1, int y1, HWND hwnd){HDC dc;dc=GetDC(hwnd);int a=0;int b=0;int d1=0;int d2=0;int d=0;int x=0;int y=0;a=y0-y1;b=x1-x0;d=2*a+b;d1=2*a;d2=2*a+2*b;x=x0;y=y0;SetPixel(dc,x,y,RGB(255,0,0));while(x<x1){if(d<0){x++;y++;d += d2;}else{x++;d =+ d1;}SetPixel(dc,x,y,RGB(255,0,0));}ReleaseDC(hwnd,dc);}。
实验四 自由曲线绘制算法1. 实验目的:1.掌握曲线的表示形式、曲线的连续性条件、拟合和逼近的基本概念2.掌握Bezier 曲线的性质3.编程实现Bezier 曲线生成算法2. 实验描述:绘制三次Bezier 曲线,可以采用公式法或德卡斯特里奥(De Casteliau )算法绘制。
3. 算法设计:在空间给定1n +个点012,,,,n PP P P ,称下列参数曲线为n 次Bezier 曲线:,0()(),01ni i n i P t P B tt ==≤≤∑其中,()i n B t 是Bernstein 基函数,其表达式为:,!()(1)!()!i n ii n n B t t ti n i -=--,接着我们讨论3次Bezier 曲线,我们也采用将表达式改写为矩阵形式的方法,我们得到:3303!()(1)!(3)!i i ii P t P t t i i -==--∑32230123(1)3(1)3(1)t P t t P t t P t P =-+-+-+01323232323331,363,33,P P t t t t t t t t t P P ⎡⎤⎢⎥⎢⎥⎡⎤=-+-+-+-+⎣⎦⎢⎥⎢⎥⎣⎦01322313313630,,,133001000P P t t t P P --⎡⎤⎡⎤⎢⎥⎢⎥-⎢⎥⎢⎥⎡⎤=⎣⎦⎢⎥⎢⎥-⎢⎥⎢⎥⎣⎦⎣⎦4. 源程序://1)TestView.hclass CTestView : public CView {…….protected:bool Flag;//标志CPoint *pt;//顶点int CtrlPoint;//控制多边形顶点……..}2) //TestView.cpp#include "math.h"//数学头文件#define N_MAX_POINT 10//控制多边形的最大顶点数#define ROUND(a) int(a+0.5) //四舍五入。
Bezier曲线的绘制实验报告一、程序实现环境1操作系统:Windows XP 、Windows72.编程语言:C++3.程序实现环境:Visual C++ 6.0二、算法思想三、使用说明程序界面如下图:用户可以在编辑框中输入4个控制点的坐标,也可以通过在绘图区内直接通过鼠标的单击指定4个控制点的位置,输入4个控制端点后,单击“画Bezier曲线”按钮即可绘制Bezier曲线。
四、实验结果五、程序代码(关键代码)void CMFC_BezierCurve2Dlg::OnLButtonDown(UINT nFlags, CPoint point) {if(pointOrd==1) //原点(490,270){m_p1_x = point.x - 490;m_p1_y = 270 - point.y;}if(pointOrd==2){CDC *pDC=GetDC();pDC->MoveTo(490+m_p1_x, 270-m_p1_y);pDC->LineTo(point.x, point.y);m_p2_x = point.x - 490;m_p2_y = 270 - point.y;}if(pointOrd==3){CDC *pDC=GetDC();pDC->MoveTo(490+m_p2_x, 270-m_p2_y);pDC->LineTo(point.x, point.y);m_p3_x = point.x - 490;m_p3_y = 270 - point.y;}if(pointOrd==4){CDC *pDC=GetDC();pDC->MoveTo(490+m_p3_x, 270-m_p3_y);pDC->LineTo(point.x, point.y);m_p4_x = point.x - 490;m_p4_y = 270 - point.y;}pointOrd++;UpdateData(FALSE);CDialog::OnLButtonDown(nFlags, point);}voidGetCnk (int n, int *c){inti,k;for(k=0; k<=n; k++){c[k]=1;for(i=n; i>=k+1; i--) c[k]=c[k]*i;for(i=n-k; i>=2; i--) c[k]=c[k]/i;}}void CMFC_BezierCurve2Dlg::GetPointPos(intControlN, double t, int *c) {int k, n=ControlN-1;double Bernstein;Pt.x=0.0; Pt.y=0.0;for(k=0; k<ControlN; k++){Bernstein=c[k]*pow(t,k)*pow(1-t,n-k);Pt.x += ControlP[0][k].x * Bernstein;Pt.y += ControlP[0][k].y * Bernstein;}}void CMFC_BezierCurve2Dlg::OnButtonDrawBeziercurve(){UpdateData();pointOrd=1;CDC *pDC=GetDC();ControlP[0][0].x=m_p1_x;ControlP[0][0].y=m_p1_y;ControlP[0][1].x=m_p2_x;ControlP[0][1].y=m_p2_y;ControlP[0][2].x=m_p3_x;ControlP[0][2].y=m_p3_y;ControlP[0][3].x=m_p4_x;ControlP[0][3].y=m_p4_y;pDC->MoveTo(490+m_p1_x, 270-m_p1_y);pDC->LineTo(490+m_p2_x, 270-m_p2_y);pDC->LineTo(490+m_p3_x, 270-m_p3_y);pDC->LineTo(490+m_p4_x, 270-m_p4_y);int *C, i;intControlN=4, m=500;C=new int[ControlN];GetCnk (ControlN-1, C);for(i=0; i<=m; i++){GetPointPos(ControlN, (double)i/(double)m, C);pDC->SetPixel(490+Pt.x, 270-Pt.y, 255);}}两段Bezier曲线的拼接实验报告一、程序实现环境1操作系统:Windows XP 、Windows72.编程语言:C++3.程序实现环境:Visual C++ 6.0二、算法思想三、使用说明程序界面如下图:用户可以在编辑框中输入4个控制点的坐标,也可以通过在绘图区内直接通过鼠标的单击指定4个控制点的位置,输入4个控制端点后,单击“画Bezier曲线”按钮即可绘制Bezier曲线。
实验四 自由曲线绘制算法1.实验目的:1.掌握曲线的表示形式、曲线的连续性条件、拟合和逼近的基本概念2.掌握Bezier 曲线的性质3.编程实现Bezier 曲线生成算法2.实验描述:绘制三次Bezier 曲线,可以采用公式法或德卡斯特里奥(De Casteliau )算法绘制。
3.算法设计:在空间给定1n +个点012,,,,n P PP P ,称下列参数曲线为n 次Bezier 曲线:,0()(),01n i i n i P t PB t t ==≤≤∑其中,()i n B t 是Bernstein 基函数,其表达式为:,!()(1)!()!i n ii n n B t t t i n i -=--,接着我们讨论3次Bezier 曲线,我们也采用将表达式改写为矩阵形式的方法,我们得到:3303!()(1)!(3)!i i ii P t P t t i i -==--∑32230123(1)3(1)3(1)t P t t P t t P t P =-+-+-+01323232323331,363,33,P P t t t t t t t t t P P ⎡⎤⎢⎥⎢⎥⎡⎤=-+-+-+-+⎣⎦⎢⎥⎢⎥⎣⎦01322313313630,,,133001000P P t t t P P --⎡⎤⎡⎤⎢⎥⎢⎥-⎢⎥⎢⎥⎡⎤=⎣⎦⎢⎥⎢⎥-⎢⎥⎢⎥⎣⎦⎣⎦4.源程序://1)TestView.hclass CTestView : public CView {…….protected:bool Flag;//标志CPoint *pt;//顶点int CtrlPoint;//控制多边形顶点……..}2) //TestView.cpp#include "math.h"//数学头文件#define N_MAX_POINT 10//控制多边形的最大顶点数#define ROUND(a) int(a+0.5) //四舍五入。
昆明理工大学理学院信息与计算科学专业操作性实验报告年级: 10级姓名:刘陈学号: 201011101128 指导教师:胡杰实验课程名称:计算机图形学程序设计开课实验室:理学院机房216实验内容:1.实验/作业题目:用计算机高级语言VC++6.0实现计算机的基本图元绘制2.实验/作业课时:2学时3.实验过程(包括实验环境、实验内容的描述、完成实验要求的知识或技能):实验环境:(1)硬件:每人一台PC机(2)软件:windows OS,VC++6.0或以上版本。
试验内容及步骤:(1)在VC++环境下创建MFC应用程序工程(单文档)(2)编辑菜单资源(3)添加菜单命令消息处理函数(4)添加成员函数(5)编写函数内容试验要求:(1)掌握Bezier曲线、Bezier曲面、及另一个曲面的算法。
(2)实现对Bezier曲线、Bezier曲面、及另一个曲面。
(3)试验中调试、完善所编程序,能正确运行出设计要求结果。
(4)书写试验报告上交。
4.程序结构(程序中的函数调用关系图)5.算法描述、流程图或操作步骤:在lab4iew.cpp文件中添加如下头文件及变量int flag_2=0;int n_change;#define M 30#define PI 3.14159 //圆周率#include "math.h" //数学头文件在lab4iew.h文件中的public内添加变量:int move;int graflag;void Tiso(float p0[3],float x0, float y0, float p[3]);void OnBezierface();在lab4iew.h文件中的protected内添加变量:int n;//控制点数const int N;//控制点数的上限CPoint* a;//控制点存放的数组double result[4][2];在lab4iew.cpp文件中的函数Clab4iew::OnDraw(CDC* pDC)下添加如下代码:int i,j;for(i=0;i<n;i++){pDC->FillSolidRect(a[i].x-2,a[i].y-2,4,4,RGB(255,55,255));}pDC->MoveTo(a[0]);for(j=0;j<n;j++){ pDC->LineT o(a[j]); }if(n<2) return;//如果控制点数少于2,则不用画CPen pen(0,2,RGB(255,0,255)),*p1;p1=pDC->SelectObject(&pen);……在Lab4iew.cpp文件中添加如下的各个消息处理函数及代码:void CLab4View::OnLButtonDown(UINT nFlags, CPoint point){ if(flag_2==0) //flag_2等于0,此时是输入控制点状态{ CClientDC dc(this); //实时输入一个控制点,在屏幕上显示此点dc.FillSolidRect(point.x-2,point.y-2,4,4,RGB(0,0,255));if(n<N){a[n++]=point;} //给控制点数组a[]赋值else {MessageBox("控制点太多!","waring",MB_OK|MB_ICONINFORMATION);}}else if(flag_2==1) //flag_2等于1,此时是修改控制点状态{ int i;for(i=0;i<n;i++) {if((abs(point.x-a[i].x)<10)&&(abs(point.y-a[i].y)<10)) //给定一个范围,如果在范围内,则选中该控制点{ n_change=i; }}CClientDC dc(this); //如果选中该点,则该点的颜色发生变化dc.FillSolidRect(a[n_change].x-2,a[n_change].y-2,4,4,RGB(255,255,0));}CView::OnLButtonDown(nFlags, point);}void CLab4View::OnLButtonUp(UINT nFlags, CPoint point){ if(flag_2==1) {a[n_change]=point; //给变换的点赋值Invalidate(true); //调用OnDraw函数,重新画控制多边形}CView::OnLButtonUp(nFlags, point);}void CLab4View::OnMouseMove(UINT nFlags, CPoint point){ if(flag_2==1) {if(nFlags==MK_LBUTTON){ a[n_change]=point;Invalidate(true); }}CView::OnMouseMove(nFlags, point);}void CLab4View::Ondrawbezier(){ move=0; graflag=1; Invalidate(true); flag_2=1;}void CLab4View::OnRButtonDown(UINT nFlags, CPoint point){ CRect rc; //点右键,刷新屏幕,使控制定点数归零,并且所有开关变量变为初试值GetClientRect(&rc);CClientDC dc(this);dc.Rectangle(0,0,rc.right,rc.bottom); //清屏n=0; //控制点数归零flag_2=0; //开关变量变为初试值CView::OnRButtonDown(nFlags, point);}void CLab4View::OnMove(){ move=1; flag_2=1;CClientDC dc(this);int i=0;while (i<n){ a[i].y=a[i].y+50; i++; }Invalidate(true); }void CLab4View::OnBezierface(){ Invalidate(true);UpdateWindow();CClientDC dc(this);dc.SetTextColor(RGB(0,0,255));dc.TextOut(160,160,"Bezier曲面");CPen pen1,pen2;pen1.CreatePen(PS_SOLID,1,RGB(255,0,0));pen2.CreatePen(PS_SOLID,3,RGB(0,0,255));int a[24][2]={{100,400},{110,300},{130,250},{150,350}, {200,300},{210,280},{250,200},{280,250},{300,320},{300,280},{330,180},{360,250},{400,400},{380,320},{410,200},{480,280}};int i,j;dc.SelectObject(&pen2);for(i=0;i<16;i=i+4){ dc.MoveTo(a[i][0],a[i][1]);for(j=0;j<4;j++){ dc.LineT o(a[i+j][0],a[i+j][1]); }}for(i=0;i<4;i++){ dc.MoveTo(a[i][0],a[i][1]);for(j=0;j<16;j=j+4){ dc.LineT o(a[i+j][0],a[i+j][1]); }dc.SelectObject(&pen2);}double x,y; x=a[0][0]; y=a[0][1]; dc.MoveTo(x,y);dc.SelectObject(&pen1);double u,w;for(u=0;u<1;u=u+0.01){ double U0=-u*u*u+3*u*u-3*u+1;double U1=3*u*u*u-6*u*u+3*u;double U2=-3*u*u*u+3*u*u;double U3=u*u*u;x=U0*a[0][0]+U1*a[4][0]+U2*a[8][0]+U3*a[12][0];y=U0*a[0][1]+U1*a[4][1]+U2*a[8][1]+U3*a[12][1];dc.MoveTo(x,y);for(w=0;w<1;w=w+0.01){ double W0=-w*w*w+3*w*w-3*w+1;double W1=3*w*w*w-6*w*w+3*w;double W2=-3*w*w*w+3*w*w;double W3=w*w*w;x=((U0*a[0][0]+U1*a[4][0]+U2*a[8][0]+U3*a[12][0])*W0+(U0*a[1][0]+U1*a[5][0]+U2*a[9][0]+U3*a[13][0])*W1+(U0*a[2][0]+U1*a[6][0]+U2*a[10][0]+U3*a[14][0])*W2+(U0*a[3][0]+U1*a[7][0]+U2*a[11][0]+U3*a[15][0])*W3);y=((U0*a[0][1]+U1*a[4][1]+U2*a[8][1]+U3*a[12][1])*W0+(U0*a[1][1]+U1*a[5][1]+U2*a[9][1]+U3*a[13][1])*W1+(U0*a[2][1]+U1*a[6][1]+U2*a[10][1]+U3*a[14][1])*W2+(U0*a[3][1]+U1*a[7][1]+U2*a[11][1]+U3*a[15][1])*W3);dc.LineT o(x,y);Sleep(1);}}for(w=0;w<1;w=w+0.01){ double W0=-w*w*w+3*w*w-3*w+1;double W1=3*w*w*w-6*w*w+3*w;double W2=-3*w*w*w+3*w*w;double W3=w*w*w;x=W0*a[0][0]+W1*a[1][0]+W2*a[2][0]+W3*a[3][0];y=W0*a[0][1]+W1*a[1][1]+W2*a[2][1]+W3*a[3][1];dc.MoveTo(x,y);for(u=0;u<1;u=u+0.01){ double U0=-u*u*u+3*u*u-3*u+1;double U1=3*u*u*u-6*u*u+3*u;double U2=-3*u*u*u+3*u*u;double U3=u*u*u;x=((U0*a[0][0]+U1*a[4][0]+U2*a[8][0]+U3*a[12][0])*W0+(U0*a[1][0]+U1*a[5][0]+U2*a[9][0]+U3*a[13][0])*W1+(U0*a[2][0]+U1*a[6][0]+U2*a[10][0]+U3*a[14][0])*W2+(U0*a[3][0]+U1*a[7][0]+U2*a[11][0]+U3*a[15][0])*W3);y=((U0*a[0][1]+U1*a[4][1]+U2*a[8][1]+U3*a[12][1])*W0+(U0*a[1][1]+U1*a[5][1]+U2*a[9][1]+U3*a[13][1])*W1+(U0*a[2][1]+U1*a[6][1]+U2*a[10][1]+U3*a[14][1])*W2。