计算机图形学课程设计报告

更新时间:2024-03-13 12:58:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

计算机图形学 课程设计报告 题 目: 三维线段的端点编码裁剪及显示 专业班级: 信计1101班 时 间: 2014年1月2日

计算机图形学课程设计报告

一、所选题目

三维线段的端点编码裁剪算法及显示

二、题目要求

对于三维线段,裁剪体为长方体,应用端点编码裁剪算法对线段进行裁剪,做XOY平面的平行投影,要求分别绘制裁剪体、带裁剪线段和裁剪后线段。

三、小组成员及具体分工

薛小娜(组长):算法设计,编译 杨 益:算法分析

张龙娟:完善程序 程军强:报告总结

四、任务分析

本题主要包括两个任务:

(1)长方体及三维线段的显示流程;(2)三维线段的端点编码裁剪算法。 任务(1)中,包括长方体的定义:三维点结构(齐次坐标,结构中应有x, y, z, w分量);面结构,其实为面的外环,即构成该面的顶点序列(逆时针顺序);三维线段的两个端点;三维几何变换;平行投影变换;窗口-视区变换;

任务(2)中,长方体的六个边界定义,三维点的端点编码,三维线段端点编码裁剪算法

五、核心算法描述

1.裁剪矩形的实现

对于裁剪矩形,可在头文件里定义三维点齐次结构HOMOCOORD,三维齐次结构中有x,y,z,w四个分量,分别对应矩形的八个顶点的三维坐标x,y,z及其次坐标w=1。定义面结构PLANE,面结构中包含该面的四个顶点(逆时针顺序)。通过这两个结构可以将实现裁剪矩形顶点的保存。

再定义PLANE结构,该结构包含x,y,分别用来存储三维坐标转换为二维坐标后的顶点信息。

2.三维直线的端点编码裁剪算法 ⑴ 编码规则:

根据直线的任一端点P(x,y,z)相对于窗口的位置,可以赋予一组6位二进制区域编码RC=C6C5C4C3C2C1,从右到左依次代表左,右,下,上,后,前。 为了保证窗口内直线线段端点编码RC的6位二进制区域码全部为零,每位二进制区域编码编码规则如下:

第一位C1:若端点位于窗口之后侧,则C1=1,否则C1=0; 第一位C2:若端点位于窗口之前侧,则C2=1,否则C2=0;

第一位C3:若端点位于窗口之左侧,则C3=1,否则C3=0; 第一位C4:若端点位于窗口之右侧,则C4=1,否则C4=0; 第一位C5:若端点位于窗口之下侧,则C5=1,否则C5=0; 第一位C6:若端点位于窗口之上侧,则C6=1,否则C6=0;

⑵裁剪算法:

① 首先需要计算三维直线的俩个端点的编码;并且假设初始化的该直线的俩个端点的区域编码不都为零;

②判断该线段若在某条边界外侧,若p0点的编码全为0,说明该点可见,则需要对p1点进行处理;

③如果p1点在左边界外侧情况下需要求线段与左边界交点,否则需要求p1点在右边界外侧的情况下线段与右边界交点;

④在不满足③的情况下需要求p1点在下边界外侧情况下线段与下边界交点,否则求p1点在上边界外侧,求线段与上边界交点;

⑤在不满足③ ④的情况下,需要求p1点在后边界外侧情况下求线段与后边界交点,否则求p1点在前边界外情况下线段与前边界交点。

⑥若处理的是端点p0,则替换端点,求新的端点编码;若处理的是端点p1,则替换端点,求新的端点编码;直到判断到俩个端点编码都为零。 3、待裁剪线段及裁剪后线段的实现

该程序用数组pt[4]来保存裁剪线段,其中pt[0],pt[1]来保存裁剪前的线段端点,pt[2],pt[3]来保存裁剪后的两点坐标,最终用蓝色实线画出pt[2]pt[3],用绿色虚线画出pt[0]pt[2]及pt[3]pt[1]

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(int angle)及RotateY(int angle),利用转换公式完成转换。

六、算法步骤

① 定义结构和变量

定义三维齐次坐标结构和面结构;定义长方体表面模型,顶点表为顶点结构数组pts[8],面表为面结构数组faces[6];定义待裁剪线段的两个端点p1,p2和裁剪后线段的两个端点p3,p4。 ② 变量初始化

在视图类构造函数中给顶点表赋值;给面表赋值(注意顶点序列顺序);给待裁剪线段端点赋值;给待裁剪线段端点赋原点值进行初始化。

③ 在视图类中添加计算端点编码的函数;添加三维线段裁决的函数。定义线段裁剪时用到的六条边界,各边界的取值为长方体相应的值。

④ 分别对长方体、待裁剪线段、裁剪后线段进行绕X轴旋转,再绕Y轴旋转。

⑤ 分别对长方体、待裁剪线段、裁剪后线段进行以XOY平面为投影平面的平行投影变换。

⑥ 分别对长方体、待裁剪线段、裁剪后线段进行窗口视区变换,注意窗口的选区。

⑦ 显示变换后长方体,用实线绘制待裁剪线段,定义画笔,用虚线绘制裁剪后线段。

七、程序核心代码

1、头文件

#define PI 3.1415926 //定义三维齐次坐标结构

typedef struct tagHOMOCOORD {

float x; float y; float z; float w;

}HOMOCOORD;

//定义面的结构

typedef struct tagPLANE {

int v0, v1, v2, v3; bool bvisible; }PLANE;

//定义点的结构,需要浮点数的x,y typedef struct tagMYPOINT {

float x,y; }MYPOINT;

public:

void RotateY(int angle); //绕y轴逆时针旋转 void RotateX(int angle); //绕x轴逆时针旋转 void DrawMy3DGraphics(); //绘制长方体

void Encode(float x, float y,float z, int *code,float XL, float XR, float YB, float YT,float ZA,float ZB);

virtual ~CDraw3DView(); protected:

HOMOCOORD *pts,*pt; //三维顶点指针

MYPOINT *pts2D,*pt2D; //自定义的二维浮点数结构,表示变换后的二维点 PLANE *faces; //长方体的面指针 int ptn,fn; //顶点个数与面的个数 int sn;//裁剪顶点个数 2、三维端点裁剪算法的实现

float maxx,maxy,maxz,minx,miny,minz; //定义裁剪矩形框的六个边界 maxx=minx=pts[0].x; maxy=miny=pts[0].y; maxz=minz=pts[0].z; for(i=0;imaxx) 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; }

for(i=0;i

int code1,code2,code;

float x,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); }

else if(code&RIGHT)//端点在右边界外侧,求线段与右边界交点 { x=maxx; 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); }

else if(code&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); }

else if(code&TOP)//端点在上边界外侧,求线段与上边界交点 { y=maxy; 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); }

else if(code&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); }

else if(code&FRONT)//端点在前边界外侧,求线段与前边界交点 { z=maxz; 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); }

if(code==code1) //若处理的是端点p0,则替换端点,求新的端点编码 { pt[2].x=x; pt[2].y=y;pt[2].z=z; Encode(x,y,z,&code1,minx,maxx,miny,maxy,minz,maxz); } else//若处理的是端点p1,则替换端点,求新的端点编码 { pt[3].x=x; pt[3].y=y;pt[3].z=z; Encode(x,y,z,&code2,minx,maxx,miny,maxy,minz,maxz); } }

void CDraw3DView::Encode(float x, float y,float z, int *code,float XL, float XR, float YB, float YT,float ZA,float ZB) {

int c=0; if(xXR) c=c|RIGHT; if(yYT) c=c|TOP; if(zZB) c=c|FRONT; *code=c; }

3、待裁剪线段及裁剪后线段的实现 CClientDC dc(this);

CPen *pOld,newpen(PS_SOLID,2,RGB(225,155,0)); //定义棕色粗笔 CPen bulepen(PS_SOLID,2,RGB(0,0,255)); //定义蓝色粗笔 CPen greenpen(PS_DASH,1,RGB(255,0,0)); //定义红笔

pOld=dc.SelectObject(&newpen); //粗棕色线绘制矩形 for( i=0;i

}

//存在可见线段 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.MoveTo(pt2D[0].x,pt2D[0].y); dc.LineTo(pt2D[1].x,pt2D[1].y); }

dc.SelectObject(pOld); //把画笔设置为原来的 }

4、窗—视变换

//窗口-视区变换实现过程

int vxl=0,vxr=500,vyb=0,vyt=400; float wxl=-3,wxr=3,wyb=-3,wyt=3; float a,b,c,d;

a=(vxr-vxl)/(wxr-wxl); b=vxl-a*wxl;

c=(vyt-vyb)/(wyt-wyb); d=vyb-c*wyb;

for(i=0;i

for(i=0;i

5、旋转

void CDraw3DView::RotateX(int angle) //绕x轴逆时针旋转 {

float a=angle*PI/180;

for(int i=0;i

void CDraw3DView::RotateY(int angle) //绕y轴逆时针旋转 {

float b=angle*PI/180;

for(int i=0;i

八、程序运行结果截图

1、绕X轴旋转45度,绕Y轴旋转45度。

2、绕X轴旋转60度,绕Y轴旋转30度。

3、在XOY平面的平行投影

本文来源:https://www.bwwdw.com/article/0sl8.html

Top