cg作业Word文件下载.docx
- 文档编号:21821572
- 上传时间:2023-02-01
- 格式:DOCX
- 页数:14
- 大小:98.09KB
cg作业Word文件下载.docx
《cg作业Word文件下载.docx》由会员分享,可在线阅读,更多相关《cg作业Word文件下载.docx(14页珍藏版)》请在冰豆网上搜索。
floatb[N][2];
printf("
请输入图形定点个数:
);
k);
请输入顶点坐标:
\n"
for(ii=0;
ii<
k;
ii++)
%f,%f"
b[ii][0],
&
b[ii][1]);
请输入变换模式:
比例
(1),对称
(2),错切(3),平移(4),旋转(5):
scanf("
h);
if(h==1)
{intm,n;
请输入比例因子(x,y):
%d,%d"
m,&
n);
a[0][0]=m;
a[1][1]=n;
}
Else
if(h==2)
{intch;
请输入对称轴:
x
(1)或y
(2):
ch);
if(ch==1)a[1][1]=-1;
if(ch==2)a[0][0]=-1;
else
if(h==3)
{intr;
floatf;
请输入错切轴x
(1)或y
(2)和错切因子a(b):
%d,%f"
r,&
f);
if(r==1)a[1][0]=f;
if(r==2)a[0][1]=f;
if(h==4)
{floati,j;
请输入平移坐标(x,y):
i,&
j);
a[2][0]=i;
a[2][1]=j;
if(h==5)
{floatg;
请输入旋转角度(度):
%f"
g);
g=M*g/180;
a[0][0]=cos(g);
a[0][1]=sin(g);
a[1][0]=-sin(g);
a[1][1]=cos(g);
经过变换后的坐标为:
%.2f,%.2f\n"
b[ii][0]*a[0][0]+b[ii][1]*a[1][0]+a[2][0],b[ii][0]*a[0][1]+b[ii][1]*a[1][1]+a[2][1]);
voidsanwei()
{floata[4][4]={{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}};
floatc[N][3],x1,y1,z1;
inth,q,jj;
请输入三维图形的顶点个数:
q);
\n"
for(jj=0;
jj<
q;
jj++)
%f,%f,%f"
c[jj][0],&
c[jj][1],&
c[jj][2]);
if(h==1)
{intl,m,n;
请输入比例因子(x,y,z):
%d,%d,%d"
l,&
a[0][0]=l;
a[1][1]=m;
a[2][2]=n;
if(h==2)
{intch;
请输入对称面:
xy
(1),yz
(2),zx(3):
if(ch==1)
a[2][2]=-1;
if(ch==3)a[1][1]=-1;
{intstr;
floato,p;
请输入错切面:
scanf("
str);
请输入错切因子(a,b):
o,&
p);
if(str==1)
{a[1][0]=o;
a[2][0]=p;
a[0][1]=o;
a[2][1]=p;
}
If(str==2)
{a[0][1]=o;
a[0][2]=o;
a[1][2]=p;
if(str==3)
{a[1][0]=o;
}
"
Else
if(h==4)
{floatr,s,t;
请输入平移坐标(x,y,z):
s,&
t);
a[3][0]=r;
a[3][1]=s;
a[3][2]=t;
if(h==5)
{inte;
floatdu;
请输入旋转轴,x轴
(1),y轴
(2),z轴(3):
e);
请输入旋转角度(度):
du);
du=M*du/180;
if(e==1)
{a[1][1]=cos(du);
a[2][1]=-sin(du);
a[1][2]=sin(du);
a[2][2]=cos(du);
if(e==2){a[0][0]=cos(du);
a[2][0]=-sin(du);
a[0][2]=sin(du);
if(e==3){a[0][0]=cos(du);
a[1][0]=-sin(du);
a[0][1]=sin(du);
a[1][1]=cos(du);
}}
经变换后坐标为:
for(jj=0;
jj++)
{x1=c[jj][0]*a[0][0]+c[jj][1]*a[1][0]+c[jj][2]*a[2][0]+a[3][0];
y1=c[jj][0]*a[0][1]+c[jj][1]*a[1][1]+c[jj][2]*a[2][1]+a[3][1];
z1=c[jj][0]*a[0][2]+c[jj][1]*a[1][2]+c[jj][2]*a[2][2]+a[3][2];
%.2f,%.2f,%.2f\n"
x1,y1,z1);
其中程序中由黄色标记部分即体现齐次坐标思想
在齐次坐标系中,n维空间的位置矢量,用n+1维矢量表示,即二维空间的位置矢量用三维矢量表示。
一个二维位置矢量[xy]用齐次坐标表示即为
[xyh],其中的h为附加坐标,是一个不为零的参数。
一个二维点的齐次坐标表示不是唯一的,如二维点[2010]可以有[20101],[40202],[60403],…等无穷组齐次坐标。
通过对齐次坐标的规范化,即用各坐标分别除以附加坐标,得到一个规范化
坐标[xy1],也就是将h转化为1。
通过二维点的齐次坐标表示,把二维图形的点集矩阵扩充为n×
3阶矩阵。
这样,点集矩阵就可以同变换矩阵进行乘法运算了:
(2)、二维齐次变换矩阵
为了使二维变换矩阵具有更多的功能,可将3×
2阶变换矩阵进一步扩充为3×
3阶矩阵,其各元素的功能和几何意义各不相同,可以分割成四块:
2×
2阶矩阵
可以实现图形的比例、对称、错切、旋转等变换;
1×
2阶矩阵[lm]可以实现图形的平移变换其中
;
2×
1阶矩阵[pq]T可以实现图形的透视变换;
而[s]可以实现图形的全比例变换。
Bezier程序
/*程序实现根据鼠标输入的点进行Bezier曲线的绘制,程序中鼠标
*输入点的个数是可以手动改动的,此程序中输入点的最大值设置为.
*同时,程序实现了键盘的交互,用来控制程序运行过程中的退出、重画等
*/
#include<
GL/glut.h>
intW,H;
//屏幕的大小
intN=-1;
//贝赛尔曲线的幂次
GLfloatBfunc[15]={0.0};
//Bernstein多项式的值的数组
GLfloatpoint[15][2]={0.0};
//存储控制点的坐标
voidInit()
{
//设置清除颜色为白色
glClearColor(1.0f,1.0f,1.0f,1.0f);
voidChangeSize(intw,inth)
GLfloatnRange=1.0f;
if(h==0)h=1;
glViewport(0,0,w,h);
W=w;
H=h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//设置修剪空间
if(w<
=h)
glOrtho(0.0,0.0,-nRange*h/w,nRange*h/w,0.0,0.0);
else
glOrtho(-nRange*w/h,nRange*w/h,0.0,0.0,0.0,0.0);
glMatrixMode(GL_MODELVIEW);
voidBezier()
inti,j,t;
GLfloatu;
//使用的绘制点坐标
GLfloatDPoint1[2];
GLfloatDPoint2[2];
//先将第一个控制点赋给第二个点,为后面的循环做准备
for(i=0;
i<
2;
i++)
DPoint2[i]=point[0][i];
glClear(GL_COLOR_BUFFER_BIT);
//设置控制点的颜色
glColor3f(1.0f,0.0f,0.0f);
//设置控制点的大小
glPointSize(5);
//绘制控制点
glBegin(GL_POINTS);
=N;
{
glVertex2fv(point[i]);
glEnd();
//设置连接控制点线的颜色
glColor3f(0.0f,0.0f,0.0f);
//设置连线的宽度
glLineWidth(3);
//绘制连线
glBegin(GL_LINE_STRIP);
glVertex2fv(point[i]);
//设置Bezier曲线的颜色
glColor3f(1.0f,0.0f,0.0f);
//设置线宽
glLineWidth
(2);
=1000;
//获得u值
u=i/1000.0;
//初始化Bfunc数组
for(t=0;
t<
t++)
Bfunc[t]=1.0;
//第一个点的坐标等于第二个点的坐标,方便下面的绘制
DPoint1[0]=DPoint2[0];
DPoint1[1]=DPoint2[1];
//将第二个坐标的x,y设置为
DPoint2[0]=0.0;
DPoint2[1]=0.0;
//循环、递推计算Bezier基函数的值
for(j=0;
j<
j++)
{
if(j==0)
{
//V0处的Bezier基函数
Bfunc[j]=1;
for(t=N;
t>
j;
t--)
Bfunc[j]=Bfunc[j]*(1-u);
}
else
if(i!
=1000)
Bfunc[j]=(1.0*(N-j+1)/j)*(u/(1-u))*Bfunc[j-1];
else
{
//Bfunc[N]处的Bezier基函数
if(j==N)
for(t=0;
N;
Bfunc[j]=Bfunc[j]*u;
else
Bfunc[j]=0.0;
}
//获得第二个点的坐标值
DPoint2[0]=DPoint2[0]+Bfunc[j]*point[j][0];
DPoint2[1]=DPoint2[1]+Bfunc[j]*point[j][1];
}
//连接两点
if(N>
=1)
glBegin(GL_LINES);
glVertex2fv(DPoint1);
glVertex2fv(DPoint2);
glEnd();
glFlush();
//鼠标事件获得控制点的坐标
voidInitMouse(intbutton,intstate,intx,inty)
//如果不是点击鼠标左键的状态,则不获得坐标值
if(button!
=GLUT_LEFT_BUTTON||state!
=GLUT_DOWN)
return;
if(N<
14)
N++;
//获得鼠标点击的坐标
point[N][0]=(2.0*x)/(float)(W-1)-1.0;
point[N][1]=(2.0*(H-y))/(float)(H)-1.0;
//重绘
glutPostRedisplay();
//键盘响应
voidkeyboard(unsignedcharkey,intx,inty)
switch(key)
//退出运行系统
case'
q'
:
case'
Q'
exit(0);
break;
//重画曲线
c'
C'
N=0;
glutPostRedisplay();
//刷新
e'
E'
voidmain(intargc,char*argv[])
glutInit(&
argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowPosition(50,100);
glutInitWindowSize(800,600);
glutCreateWindow("
Bezier曲线绘制"
glutReshapeFunc(ChangeSize);
Init();
glutDisplayFunc(Bezier);
glutMouseFunc(InitMouse);
glutKeyboardFunc(keyboard);
glutMainLoop();
程序流程图
其中被黄色标记的部分体现了
德卡斯特里奥算法的思想。
德卡斯特里奥算法可以计算贝塞尔曲线上的点C(u),u∈[0,1]。
因此,通过给定一组u的值,便可以计算出贝塞尔曲线上的坐标序列,从而绘制出贝塞尔曲线。
德卡斯特里奥算法的基础就是在向量AB上选择一个点C,使得C分向量AB为u:
1-u(也就是∣AC∣:
∣AB∣=u)。
给定点A、B的坐标以及u(u∈[0,1])的值,点C的坐标便为:
C=A+(B-A)*u=(1-u)*A+B*u。
定义贝塞尔曲线的控制点Pi编号为0i,其中,0表示是第0次迭代。
当第一、二、三……次迭代时,0将会被1、2、3……替换。
德卡斯特里奥算法的思想如下:
为了计算n次贝塞尔曲线上的点C(u),
u∈[0,1],首先将控制点连接形成一条折线00-01-02……0(n-1)-0n。
利用上述方法,计算出折线中每条线段0j-0(j+1)上的一个点1j,使得点1j分该线段的比为u:
1-u。
然后在折线10-11-……-1(n-1)上递归调用该算法,以此类推。
最终,求得最后一个点n0。
德卡斯特里奥证明了,点n0一定是曲线上的点。
如上图,曲线控制点是00、01、02、03、04、05。
线段00-01上取点10,10分该线段的比为u:
1-u,类似地取点11、12、13、14,然后第二次迭代在线段10-11上取点20,点20分该线段的比为u:
1-u,类似地取点21、22、23。
然后进行下一次迭代,依次类推,直到最后在线段40-41上取点50,50是最终惟一的点,也是在曲线上的点。
上述直观的算法描述可以表达成一个计算方法。
首先,将所有给定的控制点排列成一列,在上图中,即为最左边的一列。
每一对相邻的控制点可以伸出两个箭头,分别指向右下方和右上方。
在相邻箭头的交叉处,生成一个新的控制点。
例如,控制点ij和i(j+1)生成新的控制点(i+1)j。
指向右下方的箭头表示乘以(1-u),指向右上方的箭头表示乘以u。
因此,通过第0列,可以求出第1列,然后求出第2列……,最终,在n次迭代后,可以到达惟一的一个点n0,这个点就是曲线上的点。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- cg 作业