自由曲线和曲面的绘制.docx
《自由曲线和曲面的绘制.docx》由会员分享,可在线阅读,更多相关《自由曲线和曲面的绘制.docx(35页珍藏版)》请在冰豆网上搜索。
自由曲线和曲面的绘制
信息与计算科学专业基础课
ComputerGraphics
ReportOfcourseexperiment
计算机图形学课程实验报告
实验题目自由曲线和曲面的绘制
班级计算091
姓名张阳
学号3090811019
指导教师胡钢
日期2012-6-17
西安理工大学理学院应用数学系
二0一二年春季学期
实验4
自由曲线和曲面的绘制
实验说明
实验目的:
掌握自由曲线和曲面(包括Bezier曲线、曲面和B样条曲线、曲面)的生成算法思想,并能上机编程绘制相应的曲线、曲面和利用曲线、曲面进行简单的几何造型设计。
实验地点:
教九楼401数学系机房
实验要求(Direction):
1.每个学生单独完成;
2.开发语言为TurboC或C++,也可使用其它语言;
3.请在自己的实验报告上写明姓名、学号、班级;
4.每次交的实验报告内容包括:
题目、试验目的和意义、程序制作步骤、主程序、运行结果图以及参考文件;
5.自己保留一份可执行程序,考试前统一检查和上交。
实验内容
实验题一
1.1实验题目
上机编写一个能绘制Bezier曲线和B样条曲线的通用程序,并调试成功。
具体要求为:
(1)用户在运行程序时,可以根据提示信息来决定选择绘制Bezier曲线,还是B样条曲线;
(2)两种曲线控制顶点的个数和坐标值要求可以随机输入(即Bezier曲线和B样条曲线的次数和位置可以随机输入);(3)当用户输入控制点的坐标位置后,屏幕上生成曲线的同时显示其特征多边形;且在特征多边形的顶点处输出该顶点坐标;(4)要求在可执行程序后附上运行结果(两种曲线都至少附上一个结果图)。
1.2实验目的和意义
掌握Bezier曲线和B样条曲线的绘制方法。
1.3程序制作步骤(包括算法的基本思想、流程图、设计步骤等)
一、基本思想
(1)Bezier曲线:
是由一组折线来定义的,且第一个点和最后一个点在曲线上,第一条和最后一条折线分别表示出曲线在起点和终点处的切线方向。
Bezier曲线通常由(n+1)个顶点定义一个n次多项式。
(2)B样条曲线:
B样条曲线段是由若干条曲线段光滑连接而成的。
首先定义B样条曲线段。
设给定n+1个型值点,用表示(i=0,1,2,…,n)。
把n次参数曲线段:
叫做B样条曲线段。
与Bezier曲线类似,依次用线段连接中相邻两个型值点所得的折现多边形称为B特征多边形。
二、设计步骤
Step1:
选择Bezier或B样条曲线绘图;
Step2:
若选择用Bezier曲线绘图,输入控制顶点个数,依次输入控制顶点坐标;
若选择用B样条曲线绘图,输入B样条曲线段次数,输入控制顶点个数,依次输入控制顶点坐标;
Step3:
则将t[0,1]区间剖分成m等分,对于每一个ti,i=0,1,…,m,根据式
(1)或
(2)都可以计算出一个P(ti),计算所有的P(ti)。
Step4:
依次连接每个P(ti),就得到Bezier或B样条曲线
1.4主程序
#include
#include
#include
#include
#include"graphics.h"
//usingnamespacestd;
#definepi3.1415926
/**************二维点类**********************/
classPoint
{
public:
doublex;
doubley;
Point(intx=0,inty=0)//构造函数
{
this->x=x;
this->y=y;
}
voidoperator=(Point&a)//重载=运算符
{
x=a.x;
y=a.y;
}
Pointoperator*(doublea)//重载*运算符
{
returnPoint(a*x,a*y);
}
Pointoperator+(Pointa)//重载+运算符
{
returnPoint(x+a.x,y+a.y);
}
voidoperator+=(Pointa)//重载+=运算符
{
x+=a.x;
y+=a.y;
}
}
/*
********************基本的函数*************************
*/
//求阶乘
longintFactorial(intn)
{
inti,sum=1;
if(n==0)
return1;
for(i=2;i<=n;i++)
sum*=i;
returnsum;
}
//求Bernstein基函数
doubleBernstein(inti,intn,doublet)
{
return(double)Factorial(n)/Factorial(i)/Factorial(n-i)*pow(t,i)*pow(1-t,n-i);
}
//求B_SplineBase基函数
doubleB_SplineBase(inti,intn,doublet)
{
doublesum=0;intj;
for(j=0;j<=n-i;j++)
{
sum+=pow(-1,j)*Factorial(n+1)/Factorial(j)/Factorial(n+1-j)*pow(t+n-i-j,n);
}
returnsum/Factorial(n);
}
/*
********************曲线*************************
*/
//求Bezier曲线
voidBezier(Pointp[],intpn,intm)
{
//将t【0,1】分成多少等分m
doubleh=1.0/m;
doublet=0;
inti,j;
int*pB=(int*)malloc(sizeof(int)*(2*m+2));
Pointptemp(0,0);
for(j=0;j<=2*m+1;j+=2,t+=h)
{
ptemp.x=0;
ptemp.y=0;
for(i=0;i{
ptemp+=p[i]*Bernstein(i,pn-1,t);
}
pB[j]=ptemp.x;
pB[j+1]=ptemp.y;
}
drawpoly(m+1,pB);
}
//求B样条曲线
voidB_Spline(Pointp[],intpn,intn,intm)//pn为p中点个数,n为次数,m为t的等分数
{
doubleh=1.0/m;
doublet=0;
inti,j,k;
int*pB=(int*)malloc(sizeof(int)*(2*m+2));
Pointptemp(0,0);
for(k=0;k<=pn-n-1;k++)//是由pn-n个n次拼接而成
{
t=0;
for(j=0;j<=2*m+1;j+=2,t+=h)
{
ptemp.x=0;
ptemp.y=0;
for(i=0;i<=n;i++)
{
ptemp+=p[k+i]*B_SplineBase(i,n,t);
}
pB[j]=ptemp.x;
pB[j+1]=ptemp.y;
}
drawpoly(m+1,pB);
}
}
//画控制多边形
voiddrawControlPoly(Point*p,intpn)
{
setlinestyle(DASHED_LINE,0,0);
inti;charstr[60];
for(i=0;i{
line(p[i].x,p[i].y,p[i+1].x,p[i+1].y);
sprintf(str,"%c%d%c%d%c",'(',(int)p[i].x,',',(int)p[i].y,')');
outtextxy(p[i].x,p[i].y,str);
}
sprintf(str,"%c%d%c%d%c",'(',(int)p[i].x,',',(int)p[i].y,')');
outtextxy(p[i].x,p[i].y,str);
setlinestyle(SOLID_LINE,0,0);
}
voidmain()
{
intgd,gm,i,choose,n,pn;charstr[60];
detectgraph(&gd,&gm);
/**********************测试曲线************************/
setcolor(RED);
//Pointp[]={Point(0,0),Point(100,100),Point(200,100),Point(300,0)};
cout<<"***********************************"<cout<<"***输入0:
Bezier曲线"<cout<<"***输入1:
B样条曲线"<while
(1)
{
cin>>choose;
if(choose==1)
{
break;
}
elseif(choose==0)
{
break;
}
cout<<"输入错误,请重新输入:
";
}
if(choose==1)
{
cout<<"输入B样条曲线段次数:
";
cin>>n;
}
cout<<"输入控制顶点个数:
";
cin>>pn;
Point*p=newPoint[pn];
cout<<"输入控制顶点:
"<for(i=0;i{
cout<<"输入p"<
";
cin>>p[i].x>>p[i].y;
}
initgraph(&gd,&gm,"");//图形模式初始化
setcolor(GREEN);
if(choose==0)
Bezier(p,pn,100);//画Bezier曲线
else
B_Spline(p,pn,n,100);//画B样条曲线
setcolor(WHITE);
drawControlPoly(p,pn);//画出控制多边形
settextstyle(0,0,2);
if(choose==0)
{
sprintf(str,"%s%d%s","您所画的是:
",pn-1,"次Bezier曲线");
outtextxy(p[pn-1].x+200,p[0].y,str);
}
else
{
sprintf(str,"%s%d%s","您所画的是:
",n,"次B样条曲线");
outtextxy(p[pn-1].x+200,p[0].y,str);
}
sprintf(str,"%s%d","您所用控制顶点个数为:
",pn);
outtextxy(p[pn-1].x+200,p[0].y+textheight("2"),str);
outtextxy(p[pn-1].x+200,p[0].y+2*textheight("2"),"控制顶点坐标分别为");
for(i=0;i{
sprintf(str,"%d%s%d",(int)p[i].x,"",(int)p[i].y);
outtextxy(p[pn-1].x+230,p[0].y+(i+3)*textheight("2"),str);
}
getch();
closegraph();
}
1.5运行结果图
实验题二
2.1实验题目
1).利用Bezier曲线及其拼接技术设计花瓶几何图案或汽车图案(注意:
使用Bezier曲线时曲线的次数不要超过10次)。
要求:
(1)此题中Bezier曲线的生成利用deCasteljau算法,不能用Bezier曲线的定义;
(2)屏幕上生成花瓶几何图案曲线的同时显示其特征控制多边形;且在特征多边形的顶点处输出该顶点坐标;(3)花瓶几何图案的具体形状可以自行设计,但运行结果图至少包括2个花瓶图案。
运行结果参考图如下所示。
2).利用二次或三次Bezier曲线(或B样条曲线)技术绘制每个同学自己的中文名字图案。
要求:
(1)中文汉字的笔画要求具有一定的宽度,笔画区域可以填充也可以不填充;
(2)中文汉字的字体(如宋体、楷体等)可以自己设定。
参考样例的运行结果如下图所示。
2.2实验目的和意义
掌握并通过程序实现Bezier曲线和B样条曲线的C0级拼接。
2.3程序制作步骤(包括算法的基本思想、流程图、设计步骤等)
一、算法思想
利用Bezier曲线和B样条曲线的C0级拼接实现复杂图形的绘制。
二、设计步骤
Step1:
输入构成花瓶或车曲线的控制顶点。
Step2:
画花瓶:
利用deCasteljau算法生成的Bezier曲线逐段绘制花瓶图案。
画汽车:
利用B样条曲线逐段绘制汽车图案。
Step3:
画出控制多边形。
Step4:
标出控制多边形顶点坐标。
2.4主程序
(1)汽车图案
#include
#include
#include
#include
#include"graphics.h"
#definepi3.1415926
classPoint
{
public:
doublex;
doubley;
Point(intx=0,inty=0)//构造函数
{
this->x=x;
this->y=y;
}voidoperator=(Point&a)//重载=运算符
{
x=a.x;
y=a.y;
}Pointoperator*(doublea)//重载*运算符
{
returnPoint(a*x,a*y);
}
Pointoperator+(Pointa)//重载+运算符
{
returnPoint(x+a.x,y+a.y);
}
voidoperator+=(Pointa)//重载+=运算符
{
x+=a.x;
y+=a.y;
}
}
/*
********************基本的函数*************************
*/
//求阶乘
longintFactorial(intn)
{
inti,sum=1;
if(n==0)
return1;
for(i=2;i<=n;i++)
sum*=i;
returnsum;
}
//求Bernstein基函数
doubleBernstein(inti,intn,doublet)
{
return(double)Factorial(n)/Factorial(i)/Factorial(n-i)*pow(t,i)*pow(1-t,n-i);
}
//求B_SplineBase基函数
doubleB_SplineBase(inti,intn,doublet)
{
doublesum=0;intj;
for(j=0;j<=n-i;j++)
{
sum+=pow(-1,j)*Factorial(n+1)/Factorial(j)/Factorial(n+1-j)*pow(t+n-i-j,n);
}
returnsum/Factorial(n);
}
/*
********************曲线*************************
*/
//求Bezier曲线
voidBezier(Pointp[],intn,intm)
{
//将t【0,1】分成多少等分m
doubleh=1.0/m;
doublet=0;
inti,j;
int*pB=(int*)malloc(sizeof(int)*(2*m+2));
Pointptemp(0,0);
for(j=0;j<=2*m+1;j+=2,t+=h)
{
ptemp.x=0;
ptemp.y=0;
for(i=0;i<=n;i++)
{
ptemp+=p[i]*Bernstein(i,n,t);
}
pB[j]=ptemp.x;
pB[j+1]=ptemp.y;
}
drawpoly(m+1,pB);
}
//利用迪卡斯递推算法实现Bezier曲线
voidBezierD(Pointp[],intn,intm)
{
Point*pp=(Point*)malloc(sizeof(Point)*(n+1));//用于循环
//将t【0,1】分成多少等分m
doubleh=1.0/m;
doublet=0;
inti,j,k;
int*pB=(int*)malloc(sizeof(int)*(2*m+2));
for(j=0;j<=2*m+1;j+=2,t+=h)
{
for(i=0;i<=n;i++)
pp[i]=p[i];
for(i=n;i>0;i--)
{
for(k=0;k
pp[k]=(pp[k]*(1-t))+(pp[k+1]*t);
}
pB[j]=pp[0].x;
pB[j+1]=pp[0].y;
}
drawpoly(m+1,pB);
}
//求B样条曲线
voidB_Spline(Pointp[],intpn,intn,intm)//pn为p中点个数,n为次数,m为t的等分数
{
doubleh=1.0/m;
doublet=0;
inti,j,k;
int*pB=(int*)malloc(sizeof(int)*(2*m+2));
Pointptemp(0,0);
for(k=0;k<=pn-n-1;k++)//是由pn-n个n次拼接而成
{
t=0;
for(j=0;j<=2*m+1;j+=2,t+=h)
{
ptemp.x=0;
ptemp.y=0;
for(i=0;i<=n;i++)
{
ptemp+=p[k+i]*B_SplineBase(i,n,t);
}
pB[j]=ptemp.x;
pB[j+1]=ptemp.y;
}
drawpoly(m+1,pB);
}
}
voidCar()
{
inti;charstr[60];
Pointp[]=
{
Point(210,290),Point(210,350),Point(210,410),Point(310,410),Point(375,337),Point(417,337),Point(480,410),Point(670,410),Point(730,337),Point(770,337),Point(830,410),Point(935,410),Point(935,350),Point(935,290),Point(830,290),
Point(730,175),Point(625,175),Point(520,175),Point(470,232),Point(420,290),
Point(315,290),Point(210,290),Point(210,350)
};
//画车身(蓝色)
setcolor(BLUE);
B_Spline(p,23,2,100);
//画轮子
setcolor(GREEN);
circle(395,410,60);
circle(750,410,60);
//画控制点(红色)
setcolor(RED);
moveto(p[0].x,p[0].y);
for(i=1;i<23;i++)
{
lineto(p[i].x,p[i].y);
circle(p[i].x,p[i].y,4);
sprintf(str,"%c%d%c%d%c",'(',(int)p[i].x,',',(int)p[i].y,')');
outtextxy(p[i].x,p[i].y,str);
}
lineto(p[0].x,p[0].y);
circle(p[0].x,p[0].y,4);
sprintf(str,"%c%d%c%d%c",'(',(int)p[0].x,',',(int)p[0].y,')');
outtextxy(p[0].x,p[0].y,str);
}
voidmain()
{
intgd,gm,choose;
detectgraph(&gd,&gm);
initgraph(&gd,&gm,"");//图形模式初始化
Car();
getch();
closegraph();
}
(2)画姓名
#include"graphics.h"
#include"math.h"
#include
voidmain()
{
floatx0=145,y0=125,x1=160,y1=110,x2=175,y2=90,x3=180,y3=60;
floatx4=145,y4=145,x5=165,y5=185,x6=190,y6=205,x7=200,y7=210;
floatz1=345,w1=50,z2=335,w2=75,z3=320,w3=100;//阳
floatz4=330,w4=115,z5=360,w5=120,z6=330,w6=155;
floatz7=323,w7=154,z8=310,w8=145;
floatn0=100,m0=155,n1=100,m1=165,n2=100,m2=200,n3=90,m3=225;
floatn4=85,m4=223,n5=80,m5=222,n6=60,m6=210;
intgdriver=DETECT,gmode;
intx,y;