图形学算法

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

5)多边形在z=0平面上的投影本身不相交迭。实现这个检查可以检查 一个多边形的每条边与另一个多边形的每条边是否相交。若这步检查为 真,则两个多边形也是互补遮挡的。 如果上述5步检查都为假,就假定P遮挡了Q,交换P和Q在排序表中的位 置。事实上,P不一定遮挡Q,所以交换后应该重新上述5步的检查。 3.按最大z坐标值逐次减小的次序,对每个多边形进行扫描转换。|| 7.5*深度缓存算法(Z-Buffer)的基本工作流程。 帧缓冲区置成背景色;Z-缓冲区置成最大z值; For(各个多边形) { 扫描转换该多边形 { for(计算多边形所覆盖的每个像素(x,y)) { 计算多边形在该象素的深度值Z(x,y); If(Z(x,y)小于Z缓冲区中的(x,y)处的值) {把Z(x,y)存入Z缓冲区中(x,y)处; 把多边形在(x,y)处的亮度值存入更新缓存区(x,y)处}}} *对Z缓冲算法进行改进,只用一个缓冲存储器实现消隐。 Z-Buffer() { 帧缓存全置为背景色 For(屏幕上的每个像素(I,j)) { 深度缓存变量zb置最大值MaxValue For(多面体上的每个多边形pk) { if(像素点(I,j)在pk的投影多边形之内) { 计算pk在(I,j)处的深度值depth; If(depth小于zb) {zb = depth; indexp = k; }}} If(zb != MaxValue)计算多边形Pindexp在交点(I,j)处的光照颜色并 显示。 7.7*区域分割算法(图像空间算法) 区域分割算法要将投影平面分割成区域,考察区域内的图像。如果容易 决定在这个区域内某些多边形是可见的,那么就可以显示那些可见的多 边形,完成对这一区域的显示任务;否则,就将区域再分割成小的区 域,对小的区域递归地进行判断。由于区域逐渐变小,每个区域内的多 边形逐渐变小,最终总可以判定哪些多边形是可见的。在下面四种情况 下,可以很容易做出判定,而不必再做进一步分割: 1. 所有的多边形与区域分离,所以在区域内只显示背景值。 2. 只有一个相交的多边形,或者只有一个被包含的多边形。这时可
根据以上分析,修改Cohen-Sutherland直线裁剪算法为直线“开窗”算法如 下: double xl, xr, yt, yb; (这里事先给出窗口的位置,四个数值是已知的),修 改的部分用蓝色表示 void Cohen_Sutherland(double x0, y0, x2, y2) { int c, c1, c2; double x, y; //需要将原线段的端点保存起来,以备后面需要确定原线段去除 窗口内部分时使用 double x00=x0,y00=y0,x22=x2,y22=y2; makecode(x0, y0,c1); makecode(x2, y2, c2); while (c1!=0 || c2!=0) { if (c1&c2!=0) { showline(x00, y00, x22, y22);//显示原线段,能走到这说明原线 段都在窗口外 return; } c=c1; if (c==0) c=c2; if (c&1==1) {y=y0+(y2-y0)*(x1-x0)/(x2-x0); x=x1;} else if (c&2==2) {y=y0+(y2-y0)*(xr-x0)/(x2-x0); x=xr;} else if (c&4==4) {x=x0+(x2-x0)*(yb-y0)/(y2-y0); y=yb;} else if (c&8==8) {x=x0+(x2-x0)*(yt-y0)/(y2-y0); y=yt;} if (c==c1) {x0=x; y0=y; makecode(x, y, c1);} else {x2=x; y2=y; makecode(x, y, c2);} } //因为原算法的线段分割保证了端点的顺序性,所以采用如下的 方法可确定原线段在窗口外的部分 if (x00!=x0 || y00!=y0) showline(x00,y00,x0,y0); if (x2!=x22 || y2!=y22) showline(x2,y2,x22,y22); } 此算法已经编码实现并测试通过。 另一种方法是在分割线段的同时绘制窗口外的线段,该方法无需记录初 始点坐标。
double xl, xr, yt, yb; (这里事先给出窗口的位置,四个数值是已知的),修 改的部分用蓝色表示 void Cohen_Sutherland(double x0, y0, x2, y2) { int c, c1, c2; double x, y; makecode(x0, y0,c1); makecode(x2, y2, c2); while (c1!=0 || c2!=0) { if (c1&c2!=0) { //显示线段,此时绘制的是分割完后,完全在窗口外同侧的线 段 showline(x0, y0, x2, y2); return; } c=c1; if (c==0) c=c2; if (c&1==1) {y=y0+(y2-y0)*(x1-x0)/(x2-x0); x=x1;} else if (c&2==2) {y=y0+(y2-y0)*(xr-x0)/(x2-x0); x=xr;} else if (c&4==4) {x=x0+(x2-x0)*(yb-y0)/(y2-y0); y=yb;} else if (c&8==8) {x=x0+(x2-x0)*(yt-y0)/(y2-y0); y=yt;} if (c==c1) {showline(x0,y0,x,y);//绘制被分割抛弃的线段 x0=x; y0=y; makecode(x, y, c1);} else {showline(x,y,x2,y2);//绘制被分割抛弃的线段 x2=x; y2=y; makecode(x, y, c2);} } } DDA直线扫描转换算法 void DDALine(int x1,int y1,int x2,int y2) { double dx,dy,e,x,y; dx=x2-x1; dy=y2-y1; e=(fabs(dx)>fabs(dy))?fabs(dx):fabs(dy); dx/=e; dy/=e;
以对区域首先填充背景值,然后对多边形进行扫描转换。在某些 显示设备上,将整个帧存储器都初始化为背景值,可能更为方 便。对于相交的多边形,只是被包含的部分被扫描转换 3. 只有一个包围的多边形,没有其他的多边形。这时整个区域可填 充这个包围多边形的像素值。 4. 有多于一个包围的、相交的或被包围的多边形,且至少有一个包 围的多边形。这时可以检查是否能有一个包围的多边形位于所有 其他多边形的前面 *八叉树算法: 1. 遍历形体原来的八叉树T1,对遇到的每个黑节点,做下述步2. 2. 对遇到黑节点对应的正立方体做相应变换,得到一般来说斜置的 新位置。若这位置已超出定义八叉树的充分大正立方体C之外, 报告出错;否则执行下述的步3. 3. 从要计算求出的目标树T2的根开始,检查2.中确定的处于新位置 立方体与T2中节点对应的直立的正立方体是否相交,分以下三种 情况进行处理: (1) 不相交,说明正考查直立正方体未被占据,可保持为白节点, 不做处理。 (2) 直立的正立方体整个被占据,即它在变换后“斜置”立方体内, 置对应节点为黑节点。 (3) 在上述两条都不成立时,生成当前节点的八个子节点,对八个 子节点对应的八个直立子立方体,依wk.baidu.com再递归执行步3. 如果最 终这八个节点被标上同样特性,比方为黑节点,则应再删掉这 八个子节点而把它们的共同父节点置为黑。 *修改Cohen-Sutherland直线裁剪算法,使其成为一个直线“开窗”算 法,即指定一个窗口后,窗口内舍弃,窗口外保留。 解答:根据题意,可知只需要对原Cohen-Sutherland算法中的两处进行 修改即可满足要求。 第一处是判断C1和C2的逻辑乘结果不为0时,此时如果该条件满足,表 示线段完全在窗外,原算法此处需要将原线段完全舍弃,这里就需要将 原线段完全绘制出来即可。 第二处是最后要将原线段中窗口中可见部分绘制出来,此时原算法已经 完成对原线段的裁剪,得出来原线段在窗口内的部分,这里只需要改成 将原线段去掉窗口以内部分后的线段绘制出来即可。
&5.简单多边形包含性检验的算法: 1.【准备】XnX0,yny0,m -1,i0 2.【排除必不相交情形】若下列条件有一个成立,则到4 1)xp<x,&&xp<xi+1 2)xp>=xi&&xp>=xi+1 3)xp<y&&yp<yi+1 3.【计算交点】y=yi+(xp-xi)(yi+1 - yi)/(xi+1 - xi)分两种情形: 1)若y=yp,则P在多边形边界上,算法结束 2)若y<yp,则 m(-1)m; 4.【结束判断】ii+1,若i<n,则返回到2,否则算法结束,此时若m = -1 则 点P在多边形外部,m=1,则在内部。 *简述扫描线种子填充算法的工作步骤。 1, 对种子所在的像素段进行填充 2, 从右到左检查种子所在行的上一横行,将查到的像素段依次编号 存入堆栈。实际存入堆栈内的可以是每个像素段最右边像素的地 址。接着对种子所在行的下一横行同样处理。 3, 若堆栈为空则算法结束,否则从堆栈顶部取出一个像素段。因为 按先进后出的顺序,所以将取出编号最大的像素段。实际取出的 是这个像素段最右边像素的地址。就以这个像素为新的种子,返 回到1. 写出Graham凸壳求解算法 1.(倾角排序)选出输入电集S中X坐标最小的点,若这样的点不唯一则再 由其中选出y坐标最小的点,设为O.设想有一条从O向右的射线OX,对点 集中其余每一点P,计算倾角POX,再按倾角排序,得到点序列Q1=O,Q2,Q3, …,Qn; 2.(准备扫描)vQ1; 3.(扫描)若NEXT(v) != Q1,则循环执行下面的操作至NEXT(v)=Q1时止,此时 点序列中剩下排成凸多边形的壳上顶点,算法结束。若三个相继的点v, Next(v), Next(NEXT(v))形成一个左转,则vNEXT(v);否则先删除NEXT(v),再 做vPRED(v); *写出Jarvis凸壳求解算法 1(准备)v0点集S中按x,y字典次序最小的点;d竖直向下的一个方向向量; 点v0送入收集凸壳顶点的队列Q中;S1S – {u,v0};uv0 2(一步行进)v1Wrapping(u,d,S1);S1中各点相对于自u出发方向为d的射 线,计算倾角,取倾角最小的点,若倾角相同,取与u距离最远的点, Wrapping(u,d,S1);返回下一个壳顶点。
3(准备下次) if v1 != v0,v1送入Q中;S1 = S – {u,v1}; d从u到v1的一个方向 向量; uv1;返回步骤2 4(结束)Q中存入所有的壳顶点,算法结束 *试写出判定一空间多边形与一凸多面体之间关系的算法 1. 求出空间多边形和凸多面体的包围盒 分别做x,y,z三向测试,若包围盒检查(最大最小检验)有一个为真,则 空间多边形和凸多面体分离。算法输出分离并结束。 2. 一次用凸多面体的每一表面多边形来求解与空间多边形各边的交 点 若有交点,测试空间多边形的顶点是否均在凸多面体内,若均在体 内,则为包含;若有交点,测试空间多边形的顶点有内有外,则相 交;若无交点,测试空间多边形的顶点是否在凸多面体内,若均在体 内,则为包含;若无交点,测试空间多边形的顶点均在凸多面体外, 则为分离。 7.1线面比较法消除隐藏线 1)、消除隐藏线的线面比较法的最先一步就是利用外法线判断出所 有可能的可见面。 2)、做xv方向和yv方向的范围检查。 3)、接着做zv方向的范围检查,即粗略的深度比较。 4)、进行精确的深度比较。比较时,应计算线段两端点在可能遮挡 它的平面上的投影点,比较相应的z坐标。如果z1≤z1’并且z2≤z2’,则线 段不会被遮挡;如果z1≥z1’并且z2≥z2’,则线段有可能被遮挡,还需要做 进一步检查。如果不是上述两种情况,必发生线段与表面相交。这时, 需要用交点,这些交点把线段的投影分成两部分。判断得知线段确实被 平面遮挡了哪些部分。 5)、做精确计算。计算是求出线段的投影与遮挡平面上多边形表面 边框投影的所有交点,这些交点把线段的投影分成可见和不可见的一些 子线段。对子线段的可见性,先取其上一点做点的包含性检验来进行判 断。 7.3*深度排序(优先级)算法 1.把所有的多边形按顶点最大z坐标值进行排序。 2.解决当多边形在z坐标范围内发生交迭时出现的不明确问题 1)多边形的x坐标范围不相交迭,所以多边形不相交迭 2)多边形的y坐标范围不相交迭,所以多边形不相交迭 3)P完全在Q远离观察点的一侧 4)Q完全在P靠近观察点的一侧
相关文档
最新文档