计算机图形学课程设计报告文档格式.docx
- 文档编号:22353609
- 上传时间:2023-02-03
- 格式:DOCX
- 页数:17
- 大小:87.69KB
计算机图形学课程设计报告文档格式.docx
《计算机图形学课程设计报告文档格式.docx》由会员分享,可在线阅读,更多相关《计算机图形学课程设计报告文档格式.docx(17页珍藏版)》请在冰豆网上搜索。
三维几何变换;
平行投影变换;
窗口-视区变换;
任务
(2)中,长方体的六个边界定义,三维点的端点编码,三维线段端点编码裁剪算法
五、核心算法描述
1.裁剪矩形的实现
对于裁剪矩形,可在头文件里定义三维点齐次结构HOMOCOORD,三维齐次结构中有x,y,z,w四个分量,分别对应矩形的八个顶点的三维坐标x,y,z及其次坐标w=1。
定义面结构PLANE,面结构中包含该面的四个顶点(逆时针顺序)。
通过这两个结构可以将实现裁剪矩形顶点的保存。
再定义PLANE结构,该结构包含x,y,分别用来存储三维坐标转换为二维坐标后的顶点信息。
2.三维直线的端点编码裁剪算法
编码规则:
根据直线的任一端点P(x,y,z)相对于窗口的位置,可以赋予一组6位二进制区域编码RC=
从右到左依次代表左,右,下,上,后,前。
为了保证窗口内直线线段端点编码RC的6位二进制区域码全部为零,每位二进制区域编码编码规则如下:
第一位
:
若端点位于窗口之后侧,则
=1,否则
=0;
若端点位于窗口之前侧,则
若端点位于窗口之左侧,则
若端点位于窗口之右侧,则
若端点位于窗口之下侧,则
若端点位于窗口之上侧,则
裁剪算法:
首先需要计算三维直线的俩个端点的编码;
并且假设初始化的该直线的俩个端点的区域编码不都为零;
判断该线段若在某条边界外侧,若p0点的编码全为0,说明该点可见,则需要对p1点进行处理;
如果p1点在左边界外侧情况下需要求线段与左边界交点,否则需要求p1点在右边界外侧的情况下线段与右边界交点;
在不满足
的情况下需要求p1点在下边界外侧情况下线段与下边界交点,否则求p1点在上边界外侧,求线段与上边界交点;
的情况下,需要求p1点在后边界外侧情况下求线段与后边界交点,否则求p1点在前边界外情况下线段与前边界交点。
若处理的是端点p0,则替换端点,求新的端点编码;
若处理的是端点p1,则替换端点,求新的端点编码;
直到判断到俩个端点编码都为零。
3、待裁剪线段及裁剪后线段的实现
该程序用数组
来保存裁剪线段,其中
,
来保存裁剪前的线段端点,
来保存裁剪后的两点坐标,最终用蓝色实线画出
,用绿色虚线画出
及
4、窗—视变换
先分别定义窗口和视区的大小,
视区:
vxl,vxr,vyb,vyt
窗口:
wxl,wxr,wyb,wyt
利用转换公式
a=(vxr-vxl)/(wxr-wxl);
b=vxl-a*wxl;
c=(vyt-vyb)/(wyt-wyb);
d=vyb-c*wyb;
则转换后的坐标为:
pt2D[i].x=pts[i].x*a+b;
pt2D[i].y=pts[i].y*c+d;
5、旋转
定义函数RotateX(intangle)及RotateY(intangle),利用转换公式完成转换。
六、算法步骤
定义结构和变量
定义三维齐次坐标结构和面结构;
定义长方体表面模型,顶点表为顶点结构数组pts[8],面表为面结构数组faces[6];
定义待裁剪线段的两个端点p1,p2和裁剪后线段的两个端点p3,p4。
变量初始化
在视图类构造函数中给顶点表赋值;
给面表赋值(注意顶点序列顺序);
给待裁剪线段端点赋值;
给待裁剪线段端点赋原点值进行初始化。
在视图类中添加计算端点编码的函数;
添加三维线段裁决的函数。
定义线段裁剪时用到的六条边界,各边界的取值为长方体相应的值。
分别对长方体、待裁剪线段、裁剪后线段进行绕X轴旋转,再绕Y轴旋转。
分别对长方体、待裁剪线段、裁剪后线段进行以XOY平面为投影平面的平行投影变换。
分别对长方体、待裁剪线段、裁剪后线段进行窗口视区变换,注意窗口的选区。
显示变换后长方体,用实线绘制待裁剪线段,定义画笔,用虚线绘制裁剪后线段。
七、程序核心代码
1、头文件
#definePI3.1415926
//定义三维齐次坐标结构
typedefstructtagHOMOCOORD
{
floatx;
floaty;
floatz;
floatw;
}HOMOCOORD;
//定义面的结构
typedefstructtagPLANE
intv0,v1,v2,v3;
boolbvisible;
}PLANE;
//定义点的结构,需要浮点数的x,y
typedefstructtagMYPOINT
floatx,y;
}MYPOINT;
public:
voidRotateY(intangle);
//绕y轴逆时针旋转
voidRotateX(intangle);
//绕x轴逆时针旋转
voidDrawMy3DGraphics();
//绘制长方体
voidEncode(floatx,floaty,floatz,int*code,floatXL,floatXR,floatYB,floatYT,floatZA,floatZB);
virtual~CDraw3DView();
protected:
HOMOCOORD*pts,*pt;
//三维顶点指针
MYPOINT*pts2D,*pt2D;
//自定义的二维浮点数结构,表示变换后的二维点
PLANE*faces;
//长方体的面指针
intptn,fn;
//顶点个数与面的个数
intsn;
//裁剪顶点个数
2、三维端点裁剪算法的实现
floatmaxx,maxy,maxz,minx,miny,minz;
//定义裁剪矩形框的六个边界
maxx=minx=pts[0].x;
maxy=miny=pts[0].y;
maxz=minz=pts[0].z;
for(i=0;
i<
ptn-1;
i++)//求出六个边界的值
{
if(pts[i+1].x>
maxx)
maxx=pts[i+1].x;
if(pts[i+1].y>
maxy)
maxy=pts[i+1].y;
if(pts[i+1].z>
maxz)
maxz=pts[i+1].z;
}
i++)
if(pts[i+1].x<
minx)
minx=pts[i+1].x;
if(pts[i+1].y<
miny)
miny=pts[i+1].y;
if(pts[i+1].z<
minz)
minz=pts[i+1].z;
intcode1,code2,code;
floatx,y,z;
Encode(pt[2].x,pt[2].y,pt[2].z,&
code1,minx,maxx,miny,maxy,minz,maxz);
//计算端点p0的编码
Encode(pt[3].x,pt[3].y,pt[3].z,&
code2,minx,maxx,miny,maxy,minz,maxz);
//计算端点p1的编码
while((code1!
=0)||(code2!
=0))//若线段不是完全可见
{
if((code1&
code2)!
=0)//线段在某条边界外侧
{
s=1;
break;
code=code1;
if(code==0)//若端点p0可见,则处理p1
code=code2;
if(code&
LEFT)//端点在左边界外侧,求线段与左边界交点
x=minx;
y=pt[2].y+(x-pt[2].x)*(pt[3].y-pt[2].y)/(pt[3].x-pt[2].x);
z=pt[2].z+(x-pt[2].x)*(pt[3].z-pt[2].z)/(pt[3].x-pt[2].x);
elseif(code&
RIGHT)//端点在右边界外侧,求线段与右边界交点
x=maxx;
BOTTOM)//端点在下边界外侧,求线段与下边界交点
y=miny;
x=pt[2].x+(y-pt[2].y)*(pt[3].x-pt[2].x)/(pt[3].y-pt[2].y);
z=pt[2].z+(y-pt[2].y)*(pt[3].z-pt[2].z)/(pt[3].y-pt[2].y);
TOP)//端点在上边界外侧,求线段与上边界交点
y=maxy;
BACK)//端点在后边界外侧,求线段与后边界交点
z=minz;
x=pt[2].x+(z-pt[2].z)*(pt[3].x-pt[2].x)/(pt[3].z-pt[2].z);
y=pt[2].y+(z-pt[2].z)*(pt[3].y-pt[2].y)/(pt[3].z-pt[2].z);
FRONT)//端点在前边界外侧,求线段与前边界交点
z=maxz;
if(code==code1)//若处理的是端点p0,则替换端点,求新的端点编码
pt[2].x=x;
pt[2].y=y;
pt[2].z=z;
Encode(x,y,z,&
else//若处理的是端点p1,则替换端点,求新的端点编码
pt[3].x=x;
pt[3].y=y;
pt[3].z=z;
}
voidCDraw3DView:
Encode(floatx,floaty,floatz,int*code,floatXL,floatXR,floatYB,floatYT,floatZA,floatZB)
intc=0;
if(x<
XL)
c=c|LEFT;
elseif(x>
XR)
c=c|RIGHT;
if(y<
YB)
c=c|BOTTOM;
elseif(y>
YT)
c=c|TOP;
if(z<
ZA)
c=c|BACK;
elseif(z>
ZB)
c=c|FRONT;
*code=c;
}
3、待裁剪线段及裁剪后线段的实现
CClientDCdc(this);
CPen*pOld,newpen(PS_SOLID,2,RGB(225,155,0));
//定义棕色粗笔
CPenbulepen(PS_SOLID,2,RGB(0,0,255));
//定义蓝色粗笔
CPengreenpen(PS_DASH,1,RGB(255,0,0));
//定义红笔
pOld=dc.SelectObject(&
newpen);
//粗棕色线绘制矩形
for(i=0;
fn;
i++)
{
PLANEf=faces[i];
dc.MoveTo(pts2D[f.v0].x,pts2D[f.v0].y);
dc.LineTo(pts2D[f.v1].x,pts2D[f.v1].y);
dc.LineTo(pts2D[f.v2].x,pts2D[f.v2].y);
dc.LineTo(pts2D[f.v3].x,pts2D[f.v3].y);
dc.LineTo(pts2D[f.v0].x,pts2D[f.v0].y);
//存在可见线段
if(s==0)
{dc.SelectObject(bulepen);
dc.MoveTo(pt2D[2].x,pt2D[2].y);
dc.LineTo(pt2D[3].x,pt2D[3].y);
dc.SelectObject(greenpen);
dc.MoveTo(pt2D[0].x,pt2D[0].y);
dc.LineTo(pt2D[2].x,pt2D[2].y);
dc.MoveTo(pt2D[3].x,pt2D[3].y);
dc.LineTo(pt2D[1].x,pt2D[1].y);
//不存在可见线段
else
dc.SelectObject(greenpen);
dc.LineTo(pt2D[1].x,pt2D[1].y);
dc.SelectObject(pOld);
//把画笔设置为原来的
//窗口-视区变换实现过程
intvxl=0,vxr=500,vyb=0,vyt=400;
floatwxl=-3,wxr=3,wyb=-3,wyt=3;
floata,b,c,d;
for(i=0;
ptn;
pts2D[i].x=pts[i].x*a+b;
pts2D[i].y=pts[i].y*c+d;
sn;
pt2D[i].x=pt[i].x*a+b;
pt2D[i].y=pt[i].y*c+d;
RotateX(intangle)//绕x轴逆时针旋转
floata=angle*PI/180;
for(inti=0;
i++)//矩形旋转
floaty,z;
y=pts[i].y;
z=pts[i].z;
pts[i].y=y*cos(a)-z*sin(a);
pts[i].z=y*sin(a)+z*cos(a);
for(intj=0;
j<
j++)//线段旋转
y=pt[j].y;
z=pt[j].z;
pt[j].y=y*cos(a)-z*sin(a);
pt[j].z=y*sin(a)+z*cos(a);
RotateY(intangle)//绕y轴逆时针旋转
floatb=angle*PI/180;
floatx,z;
x=pts[i].x;
pts[i].x=x*cos(b)+z*sin(b);
pts[i].z=-x*sin(b)+z*cos(b);
x=pt[j].x;
pt[j].x=x*cos(b)+z*sin(b);
pt[j].z=-x*sin(b)+z*cos(b);
八、程序运行结果截图
1、绕X轴旋转45度,绕Y轴旋转45度。
2、绕X轴旋转60度,绕Y轴旋转30度。
3、在XOY平面的平行投影
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 计算机 图形学 课程设计 报告