




已阅读5页,还剩15页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
一、实验目的 1、掌握中点Bresenham直线扫描转换算法的思想。 2掌握边标志算法或有效边表算法进行多边形填充的基本设计思想。 3掌握透视投影变换的数学原理和三维坐标系中几何图形到二维图形的观察流程。 4掌握三维形体在计算机中的构造及表示方法二、实验环境Windows系统, VC6.0。3、 实验步骤 1、给定两个点的坐标P0(x0,y0),P1(x1,y1),使用中点Bresenham直线扫描转换算法画出连接两点的直线。实验基本步骤 首先、使用MFC AppWizard(exe)向导生成一个单文档视图程序框架。 其次、使用中点Bresenham直线扫描转换算法实现自己的画线函数,函数原型可表示如下:void DrawLine(CDC *pDC, int p0x, int p0y, int p1x, int p1y);在函数中,可通过调用CDC成员函数SetPixel来画出扫描转换过程中的每个点。COLORREF SetPixel(int x, int y, COLORREF crColor ); 再次、找到文档视图程序框架视图类的OnDraw成员函数,调用DrawLine函数画出不同斜率情况的直线,如下图: 最后、调试程序直至正确画出直线。2、 给定多边形的顶点的坐标P0(x0,y0),P1(x1,y1),P2(x2,y2),P3(x3,y3),P4(x4,y4)使用边标志算法或有效边表算法进行多边形填充。实验基本步骤 首先、使用MFC AppWizard(exe)向导生成一个单文档视图程序框架。 其次、实现边标志算法或有效边表算法函数,如下:void FillPolygon(CDC *pDC, int px, int py, int ptnumb);px:该数组用来表示每个顶点的x坐标py :该数组用来表示每个顶点的y坐标ptnumb:表示顶点个数注意实现函数FillPolygon可以直接通过窗口的DC(设备描述符)来进行多边形填充,不需要使用帧缓冲存储。(边标志算法)首先用画线函数勾画出多边形,再针对每条扫描线,从左至右依次判断当前像素的颜色是否勾画的边界色,是就开始填充后面的像素直至再碰到边界像素。注意对顶点要做特殊处理。通过调用GDI画点函数SetPixel来画出填充过程中的每个点。需要画线可以使用CDC的画线函数MoveTo和LineTo进行绘制,也可以使用实验一实现的画直线函数。CPoint MoveTo(int x, int y );BOOL LineTo(int x, int y );实现边标志算法算法需要获取某个点的当前颜色值,可以使用CDC的成员函数COLORREF GetPixel(int x, int y ); 再次、找到文档视图程序框架视图类的OnDraw成员函数,调用FillPolygon函数画出填充的多边形,如下:void CTestView:OnDraw(CDC* pDC)CTestcoodtransDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);/ TODO: add draw code for native data here /绘制之前先把整个窗口涂上背景色(白色)以便于下面的填充 RECT Rt; GetClientRect(&Rt); pDC-FillSolidRect(&Rt, RGB(255,255,255); int ptx = 10, 100, 200, 150, 80; int pty = 10, 50, 80, 120, 70; FillPolygon(pDC, ptx, pty, 5);截图如下3. 在世界坐标系中定义一个立方体(由6个面组成),并给定观察点在世界坐标系中的位置(a,b,c)以及观察坐标系的方位角,俯仰角和姿态角,另外再给定投影面离观察点的距离D,在屏幕上画出立方体的透视投影图形。 实验基本步骤 首先、使用MFC AppWizard(exe)向导生成一个单文档视图程序框架。其次、由给定观察点在世界坐标系中的位置(a,b,c)以及观察坐标系的方位角,俯仰角和姿态角求出观察变换矩阵Tv.再次、将立方体的每一个面的顶点坐标与变换矩阵Tv相乘得到观察坐标系中的坐标,再由式(1)求得二维投影坐标。并用直线连接这些二维投影坐标点形成每一个面在投影面的图形,依次将立方体的6个面画出即可。核心代码如下:void CTestView:OnDraw(CDC* pDC)CTestDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);/ TODO: add draw code for native data here CRect Rect;GetClientRect(&Rect);int MaxX=Rect.right; int MaxY=Rect.bottom; pDC-SetMapMode(MM_ANISOTROPIC); pDC-SetWindowExt(1, 1); pDC-SetViewportExt(1, -1); pDC-SetViewportOrg(MaxX/2, MaxY/2);/设置视点原点在屏幕中心 DrawObject(pDC);void CTestView:ReadPoint()/读入8个顶点坐标/每一行代表正方体每个顶点的x,y,z坐标int a=200;/正方体边长P11=-a/2;P12=-a/2;P13=-a/2;P21=-a/2;P22=a/2;P23=-a/2;P31=-a/2;P32=a/2;P33=a/2;P41=-a/2;P42=-a/2;P43=a/2;P51=a/2;P52=-a/2;P53=-a/2;P61=a/2;P62=a/2;P63=-a/2;P71=a/2;P72=a/2;P73=a/2;P81=a/2;P82=-a/2;P83=a/2;void CTestView:ReadFace()/读入6个面坐标/第一列为每个面的边数;其余列为面的顶点编号F10=4;F11=1;F12=2;F13=3;F14=4;F20=4;F21=1;F22=4;F23=8;F24=5;F30=4;F31=5;F32=6;F33=7;F34=8;F40=4;F41=6;F42=2;F43=3;F44=7;F50=4;F51=8;F52=7;F53=3;F54=4;F60=4;F61=5;F62=6;F63=2;F64=1;void CTestView:DrawObject(CDC *pDC)/绘制立方体int TotalEdge,PointNumber;int xt,yt,zt,x,y,z;/边的点坐标CPen MyPen,* OldPen; double x2d,y2d;/屏幕坐标系的二维坐标点MyPen.CreatePen(PS_SOLID,3,RGB(0,0,0); OldPen=pDC-SelectObject(&MyPen);for(face=1;face=6;face+)TotalEdge=Fface0;/面的总边数for(int edge=1;edgeMoveTo(ROUND(x2d),ROUND(y2d);xt=x;yt=y;zt=z;elsepDC-LineTo(ROUND(x2d),ROUND(y2d);Project(x2d, y2d, xt,yt,zt);pDC-LineTo(ROUND(x2d),ROUND(y2d);/封闭边pDC-SelectObject(OldPen);MyPen.DeleteObject();void CTestView:Project(double &x2d, double &y2d, int x,int y,int z)/透视变换double x0,y0,z0; /用户坐标变换为观察坐标系三维坐标,即用户坐标系坐标乘观察坐标变换矩阵(x,y,z,1)*Tvx0 = x*Proj00+y*Proj10+z*Proj20+Proj30;y0 = x*Proj01+y*Proj11+z*Proj21+Proj31;z0 = x*Proj02+y*Proj12+z*Proj22+Proj32; /观察坐标系三维坐标透视变换为屏幕坐标系二维坐标,即(xv,yv,zv,1)*Ts,再转化为非其次坐标x2d=D*x0/z0; y2d=D*y0/z0;void CTestView:InitParameter()/初始化观察坐标变换矩阵 double cosTheta = cos(PI*Theta/180); double sinTheta = sin(PI*Theta/180); double cosPhi = cos(PI*Phi/180); double sinPhi = sin(PI*Phi/180); double cosAlpha = cos(PI*Alpha/180); double sinAlpha = sin(PI*Alpha/180);Proj00 = cosTheta*cosAlpha+sinTheta*cosPhi*sinAlpha; Proj01 = cosTheta*sinAlpha - cosPhi*sinTheta*cosAlpha; Proj02 = -sinPhi*sinTheta; Proj03 = 0; Proj10 = -sinPhi*sinAlpha; Proj11 = sinPhi*cosAlpha; Proj12 = -cosPhi; Proj13 = 0;Proj20 = -sinTheta*cosAlpha+cosTheta*cosPhi*sinAlpha; Proj21 = -sinTheta*sinAlpha-cosPhi*cosTheta*cosAlpha; Proj22 = -sinPhi*cosTheta; Proj23 = 0;Proj30 = -(a*cosTheta-c*sinTheta)*cosAlpha-(-b*sinPhi+(a*sinTheta+c*cosTheta)*cosPhi)*sinAlpha; Proj31 = -(a*cosTheta-c*sinTheta)*sinAlpha+(-b*sinPhi+(a*sinTheta+c*cosTheta)*cosPhi)*cosAlpha; Proj32 = b*cosPhi+(a*sinTheta+c*cosTheta)*sinPhi; Proj33 = 1;void CTestView:OnCustom() / TODO: Add your command handler code hereAfxGetMainWnd()-SetWindowText(透视变换任意观察坐标系透视); /任意设定观察点 a = 200; b = 0; c = 500; /观察角度 Theta=20; Phi=90; Alpha = 10; /视距D = 800;InitParameter();ReadPoint();ReadFace();RedrawWindow();void CTestView:OnMENUOne() /一点透视 / TODO: Add your command handler code hereAfxGetMainWnd()-SetWindowText(透视变换一点透视);Theta=0; Phi=90; Alpha = 0; /采用球面坐标设定观察点double R= 700.0; a = R*sin(PI*Phi/180)*sin(PI*Theta/180); b = R*cos(PI*Phi/180); c = R*sin(PI*Phi/180)*cos(PI*Theta/180);D = 1000;/视距InitParameter();ReadPoint();ReadFace();RedrawWindow();void CTestView:OnMENUTwo()/二点透视 / TODO: Add your command handler code hereAfxGetMainWnd()-SetWindowText(透视变换二点透视);Theta=30; Phi=90; Alpha =0; /采用球面坐标设定观察点double R= 700.0; a = R*sin(PI*Phi/180)*sin(PI*Theta/180); b = R*cos(PI*Phi/180); c = R*sin(PI*Phi/180)*cos(PI*Theta/180);D = 1000;/视距InitParameter();ReadPoint();ReadFace();RedrawWindow();void CTestView:OnMENUThree() /三点透视/ TODO: Add your command handler code hereAfxGetMainWnd()-SetWindowText(透视变换三点透视);Theta=45; Phi=45; Alpha=0; /采用球面坐标设定观察点double R= 700.0; a = R*sin(PI*Phi/180)*sin(PI*Theta/180); b = R*cos(PI*Phi/180); c = R*sin(PI*Phi/180)*cos(PI*Theta/180);D = 1000;/视距InitParameter();ReadPoint();ReadFace();RedrawWindow(); 实验截图4、迭代剖分法生成球面。 首先、使用MFC AppWizard(exe)向导生成一个单文档视图程序框架。其次、初始化生成正八面体的顶点表,和面表。再次、对面表里的每一个三角形进行剖分,一个三角形变成四个三角形。将产生的新的顶点加入到顶点表,同时将产生的新三角形加入到面表里,并从面表里删除原来的三角形。迭代多次后即得一个逼近于球面的多面体。最后、对面表里的每一个三角形进行透视投影,在屏幕上画出透视投影图,调试程序直至正确。实验核心代码如下:void CTestView:GenerateSphereFace()/生成球面表 /首先生成一个正八面体int a=200;P00=0; P01=a; P02=0;P10=0; P11=-a; P12=0;P20=a; P21=0; P22=0;P30=0; P31=0; P32=-a;P40=-a; P41=0; P42=0;P50=0; P51=0; P52=a; int ptNum = 6; faceNum = 8; F00=3;F01=0;F02=4;F03=5;F10=3;F11=0;F12=5;F13=2;F20=3;F21=0;F22=2;F23=3;F30=3;F31=0;F32=3;F33=4;F40=3;F41=1;F42=5;F43=4;F50=3;F51=1;F52=2;F53=5; F60=3;F61=1;F62=3;F63=2;F70=3;F71=1;F72=4;F73=3; /分割迭代 for(int times = 0; times 3; times+) int i, iNum = faceNum; for(i = 0; i * * / * * * * * /先求中点坐标,并添加到点表 int pt1 = Fi1; int pt2 = Fi2; int pt3 = Fi3; int mid12 = ptNum+; double mx = (Ppt10 + Ppt20)/2; double my = (Ppt11 + Ppt21)/2; double mz = (Ppt12 + Ppt22)/2; Pmid120 = a/sqrt(mx*mx+my*my+mz*mz)*mx;/坐标规范化 Pmid121 = a/sqrt(mx*mx+my*my+mz*mz)*my; Pmid122 = a/sqrt(mx*mx+my*my+mz*mz)*mz; int mid23 = ptNum+; mx = (Ppt30 + Ppt20)/2; my = (Ppt31 + Ppt21)/2; mz = (Ppt32 + Ppt22)/2; Pmid230 = a/sqrt(mx*mx+my*my+mz*mz)*mx; Pmid231 = a/sqrt(mx*mx+my*my+mz*mz)*my; Pmid232 = a/sqrt(mx*mx+my*my+mz*mz)*mz; int mid13 = ptNum+; mx = (Ppt10 + Ppt30)/2; my = (Ppt11 + Ppt31)/2; mz = (Ppt12 + Ppt32)/2; Pmid130 = a/sqrt(mx*mx+my*my+mz*mz)*mx; Pmid131 = a/sqrt(mx*mx+my*my+mz*mz)*my; Pmid132 = a/sqrt(mx*mx+my*my+mz*mz)*mz; /被分割的三角形改为其中一个小的三角形,新建另外三个小的三角形 Fi2 = mid12; Fi3 = mid13; FfaceNum0 = 3; FfaceNum1 = mid12; FfaceNum2 = pt2; FfaceNum3 = mid23; faceNum+; FfaceNum0 = 3; FfaceNum1 = mid13; FfaceNum2 = mid23; FfaceNum3 = pt3; faceNum+; FfaceNum0 = 3; FfaceNum1 = mid12; FfaceNum2 = mid23; FfaceNum3 = mid13; faceNum+; void CTestView:GenerateEllipsoidFace()/生成椭球面表int a = 200, b = 100, c = 100;P00=0; P01=b; P02=0;P10=0; P11=-b; P12=0;P20=a; P21=0; P22=0;P30=0; P31=0; P32=-c;P40=-a; P41=0; P42=0;P50=0; P51=0; P52=c; int ptNum = 6; faceNum = 8; F00=3;F01=0;F02=4;F03=5;F10=3;F11=0;F12=5;F13=2;F20=3;F21=0;F22=2;F23=3;F30=3;F31=0;F32=3;F33=4;F40=3;F41=1;F42=5;F43=4;F50=3;F51=1;F52=2;F53=5; F60=3;F61=1;F62=3;F63=2;F70=3;F71=1;F72=4;F73=3; /分割迭代 for(int times = 0; times 3; times+) int i, iNum = faceNum; for(i = 0; i * * / * * * * * /先求中点坐标,并添加到点表 int pt1 = Fi1; int pt2 = Fi2; int pt3 = Fi3; int mid12 = ptNum+; double mx = (Ppt10 + Ppt20)/2; double my = (Ppt11 + Ppt21)/2; double mz = (Ppt12 + Ppt22)/2; double scale = 1.0/sqrt(mx*mx/(a*a)+my*my/(b*b)+mz*mz/(c*c); Pmid120 = scale*mx;/坐标规范化 Pmid121 = scale*my; Pmid122 = scale*mz; int mid23 = ptNum+; mx = (Ppt30 + Ppt20)/2; my = (Ppt31 + Ppt21)/2; mz = (Ppt32 + Ppt22)/2; scale = 1.0/sqrt(mx*mx/(a*a)+my*my/(b*b)+mz*mz/(c*c); Pmid230 = scale*mx; Pmid231 = scale*my; Pmid232 = scale*mz; int mid13 = ptNum+; mx = (Ppt10 + Ppt30)/2; my = (Ppt11 + Ppt31)/2; mz = (Ppt12 + Ppt32)/2; scale = 1.0/sqrt(mx*mx/(a*a)+my*my/(b*b)+mz*mz/(c*c); Pmid130 = scale*mx; Pmid131 = scale*my; Pmid132 = scale*mz; /被分割的三角形改为其中一个小的三角形,新建另外三个小的三角形 Fi2 = mid12; Fi3 = mid13; FfaceNum0 = 3; FfaceNum1 = mid12; FfaceNum2 = pt2; FfaceNum3 = mid23; faceNum+; FfaceNum0 = 3; FfaceNum1 = mid13; FfaceNum2 = mid23; FfaceNum3 = pt3; faceNum+; FfaceNum0 = 3; FfaceNum1 = mid12; FfaceNum2 = mid23; FfaceNum3 = mid13; faceNum+; void CTestView:DrawObject(CDC *pDC)/绘制int TotalEdge,pt;int xt,yt,zt,x,y,z;/边的点坐标 double x2d,y2d;/屏幕坐标系的二维坐标点for(int face=0;facefaceNum;face+)TotalEdge=Fface0;/面的总边数 if(!IsFaceVisible(Fface)/判定从视线方向看过去,该面是否可见 continue;for(int edge=1;edgeMoveTo(ROUND(x2d),ROUND(y2d);xt=x;yt=y;zt=z;elsepDC-LineTo(ROUND(x2d),ROUND(y2d);Project(x2d, y2d, xt,yt,zt);pDC-LineTo(ROUND(x2d),ROUND(y2d);/封闭边void CTestView:Project(double &x2d, double &y2d, int x,int y,int z)/透视变换double x0,y0,z0; /用户坐标变换为观察坐标系三维坐标,即用户坐标系坐标乘观察坐标变换矩阵(x,y,z,1)*Tvx0 = x*Proj00+y*Proj10+z*Proj20+Proj30;y0 = x*Proj01+y*Proj11+z*Proj21+Proj31;z0 = x*Proj02+y*Proj12+z*Proj22+Proj32; /观察坐标系三维坐标透视变换为屏幕坐标系二维坐标,即(xv,yv,zv,1)*Ts,再转化为非其次坐标x2d=D*x0/z0; y2d=D*y0/z0;void CTestView:InitParameter()/初始化观察坐标变换矩阵 double cosTheta = cos(PI*Theta/180); double sinTheta = sin(PI*Theta/180); double cosPhi = cos(PI*Phi/180); double sinPhi = sin(PI*Phi/180); double cosAlpha = cos(PI*Alpha/180); double sinAlpha = sin(PI*Alpha/180);Proj00 = cosTheta*cosAlpha+sinTheta*cosPhi*sinAlpha; Proj01 = cosTheta*sinAlpha - cosPhi*sinTheta*cosAlpha; Proj02 = -sinPhi*sinTheta; Proj03 = 0; Proj10 = -sinPhi*sinAlpha; Proj11 = sinPhi*cosAlpha; Proj12 = -cosPhi; Proj13 = 0;Proj20 = -sinTheta*cosAlpha+cosTheta*cosPhi*sinAlpha; Proj21 = -sinTheta*sinAlpha-cosPhi*cosTheta*cosAlpha; Proj22 = -sinPhi*cosTheta; Proj23 = 0;Proj30 = -(a*cosTheta-c*sinTheta)*cosAlpha-(-b*sinPhi+(a*sinTheta+c*cosTheta)*cosPhi)*sinAlpha; Proj31 = -(a*cosTheta-c*sinTheta)*sinAlpha+(-b*sinPhi+(a*sinTheta+c*cosTheta)*cosPhi)*cosAlpha; Proj32 = b*cosPhi+(a*sinTheta+c*cosTheta)*sinPhi; Proj33 = 1;BOOL CTestView:IsFaceVisible(int Face5) /求视矢量 int pt0 = Fa
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论