第三节 二维裁剪 一、线段裁剪 二、多边形裁剪
第三节 二维裁剪 在二维图形的绘制或显示处理中,有时需要给出或显示某一部分原始图形。这可在适当位置按一定边界范围定义一个矩形区域(即窗口),使窗口内图形为所需部分,将其保留下来作为绘制或显示之用,而窗口边界以外的图形则予以舍弃。这种对二维原始图形的处理称为二维裁剪。 二维裁剪处理主要是判定图形元素是否在所开的窗口内,若在内则进一步求出窗口内的那一部分。也就是说裁剪处理工作有两点:第一是窗口内外的判定;第二是计算图形元素与窗口边界的交点。 在定义一个窗口时,一般规定窗口为矩形框。它在用户坐标系中的位置和大小用窗口对角点坐标或右下角点坐标(x1,y1)和右上角点坐标(x2,y2)来表示,有时也可用窗口原点(左下角点或右上角点)和窗口边长来表示。在某些情况下,用户也可以用圆心和半径来定图形窗口,或定义其它窗口。 在实际应用中,往往需要观察某一图形的各个细部,或切产生不同比例的显示图形,这些都需要对原图形作二维处理。裁剪处理是把每个图形元素分成窗口内的与窗口外两部分,舍弃窗口外部分。虽然对不同的图形元素(如点、线段、多边形等)有不同的裁剪算法,但它们的原理都是一致的。都是一对简单的不等式,由这对不等式来确定图形上的点(x,y)是否位于窗口内。在选定窗口的情况下,如窗口的四条边线是x=x1,x=x2,y=y1,y=y2时,不等式为 x1≤x≤x2 y1≤y≤y2 根据此式对图形进行逐点裁剪,不满足其中任何一个不等式的点就不在窗口内,应舍弃。显然这种算法效率很低。因此要另外设计对较大图形是行裁剪的算法,如对线段、多边形进行裁剪的算法,下面分别介绍。
一、线段裁剪 裁剪处理的要害是如何去掉窗口外的图形,这要设计出相应的算法。在线段裁剪算法中,需要检查线段相对于窗口的位置关系。对整个位于窗口内的线段须全部保留,对整个位于窗口外的线段要全部予以舍弃。对于部分位于窗口内而其余部分位于窗口外的线段 则须计算出该线段与窗口边的交点作为线段的分段点,保留位于窗口内的那部分线段,舍弃其余部分线段。一般线段两端点相对于窗口的位置有下面几种情况: 1、两端点均在窗口外同一侧位置。如图2-6中线段CD,这时线段全部位于窗口之外,故整个线段舍弃。 2、两端点均在窗口内,如图2-6中线段MN,显然整个线段位于窗口内,应全部保留。 3、两端点线段中,一点在窗口内,另一点在窗口外,如图2-6中线段PQ,在这种情况应计算出线段PQ与窗口边的交点T,保留窗口内部分线段TQ,舍弃其余部分线段PT。 4、两端点均不在窗口内,但又不处于 边界外同一侧位置,如图2-6中线段AB和线段EF,这时线段可能穿过窗口(如线段AB)也可能全部位于窗口之外(如线段EF),因此需要根据线段与窗口边界的交点来判定。若线段与窗口边线的交点中有两个交点处于窗口上,则此两交点间线段位于窗口内,予以保留,线段的其余部分位于窗口外,应舍弃;若线段与窗口边界的所有交点均在之外,则整个线段位于窗口外,应予全部舍弃。
下面介绍线段裁剪算法(编码裁剪法)。 由上面线段相对于窗口的位置的几种情况讨论可以得知,有些线段被窗口边界切割后会产生一条以上的窗口外的线段,而窗口内的线段却只有一条。这一点很重要,它意味着要确定窗口内的线段,只要计算出它位于窗口内的两个端点。丹科恩和伊凡.瑟萨兰德就根据这一思路设计出了线段裁剪的算法。这种算法分为两步:第一步先确定该线段是否整个位于窗口内或全部位于窗口外,若属于这两种情况,则全部保留或全部舍弃;第二步对不属于第一步那两种情况的线段,则被窗口某一边界线分成两部分,再对每一部分进行第一步。具本这两步留舍测试如下进行:延长窗口各边界,将窗口及其四周共划分为九个区域,中心就是所要裁剪的区域。每个区域各用一个四位二进制数组成的代码(即代码中每一位分别为0或1)来表示,如图2-7所示。
当线的一端点位于某一区域时,便将该区域的代码赋予端点。然后根据线从而段两端点代码就能很方便地判定出线段相对于窗口的位置关系,并决定对该线段如何进行裁剪。四位代码中每位(位的顺序由右向左排序)代码的意义如下: 第一位,点在窗口左边界线之左为1,否则为0; 第二位,点在窗口右边界线之右为1,否则为0; 第三位,点在窗口底边界线之下为1,否则为0; 第四位,点在窗口顶边界线之上为1,否则为0。 对线段进行测试时,首先对全部保留和全部舍弃线段这两种情况进行判定,即 1、当线段两端点的四位代码全由零组成时,则表示两端点均在窗口内,要全部保留该线段。 2、当线段的四位代码逻辑乘不等于零时,则表示两个端点的代码中有一相同位,同时为1;若线段两个端点在侣边界线外的同侧位置,则整个线段在窗口之外,应予全部舍弃。如图2-6中各线段端点代码(或称编码)逻辑乘如表2-1所示。
表 2-1 线段端点代码及其逻辑 ---------------------------------------------------------------------- 线段 端点代码 逻辑乘 注释 (见图2-6) (见图2-7中代码规则) (窗口内为可见) ---------------------------------------------------------------------- AB 0 0 0 1 0 0 1 0 0 0 0 0 部分可见 CD 0 1 0 0 0 1 0 0 0 1 0 0 不可见 EF 0 0 0 1 1 0 0 0 0 0 0 0 不可见 MN 0 0 0 0 0 0 0 0 0 0 0 0 可 见 PQ 0 0 1 0 0 0 0 0 0 0 0 0 部分可见 ----------------------------------------------------------------------
由表2-1可得知,当线段两端点逻辑乘非零时,则线段不可见。但当线段两端点逻辑乘为零时,则有三种情形:可见,部分可见与不可见,因此这时不需要对端两端点代码分别进行检查。 假如线段不能通过上述两种测试判定为保留或舍弃,则必须求出线段与窗口边界线的交点,即分割 线段 ,舍弃在窗口外同侧的部分线段,对留下的线段重复进行上述两种情况的判定,直到留下的线段符合上述两种情况之一为止。
二、多边形裁剪 多边形裁剪比线段裁剪要复杂许多。多边形裁剪需要解决两个问题:一是一个完整封闭的多边形经剪裁后不再是封闭的,需要用窗口边界的适当部分来封闭它;二是边界线段的边接,不适当的连接会产生错误。另外假如对多边形相对于窗口的四条边同时进行裁剪,那么很难算出应该使用窗口的哪些边界线段来封闭图形。但相对于
窗口的一条边界线来裁剪多边形就比较轻易,并由此可提出多边形裁剪算法。 下面介绍多边形裁剪算法(逐边裁剪法)。 伊凡.瑟萨兰德和格雷霍奇曼1974年对多边形裁剪提 出了逐边裁剪算法。他们的思路是,把多边形裁剪这样一个整体问题分割成一系列简单问题,这些简单问题解决了,对整体也解决了。具体算法是:把整个多边形先相对于窗口的第一条边界线进行裁剪,形成一个新的多边形;然后再把这个新的多边形相对于窗口的第二条边界线进行裁剪、再次形成一个新的多边形;接着用窗口的第三条边、第四条边依次进行如此剪裁,最后形成一个整个多边形经过窗口的四条边界线裁剪后的多边形。这个多边形裁剪过程如图2-8所示。
这个算法看起来似乎要很大的内存保留中间数据,其实不然,它可以采用递归方式调用同一算法,整个裁剪过程由四级同样的算法组成。每一级相对于窗口的四条边界线之一来剪裁,第一级输出的顶点传送给第二级(即把多边形每个顶点相对于第一条边界线裁剪,所形成的多边形顶点作为下一步裁剪过程输入),第二级的顶点输出传送给第三级,依此类推,最后一级产生的顶点就构成经过裁剪的多边形。具体实现采用一个数组存放原始多边形的顶点坐标,再设置一个待裁剪多边形顶点坐标数组,用来存放经某条窗口边界线裁剪后所生成的顶点坐标,不妨把这个数组称为新多边形数组,最后新多边形数组存放的是经所有窗口边界裁剪完毕而得到的结果多边形的顶点坐标。 设与多边形的顶点为P1、P2、P3、......Pn,多边形的各条边线分别为顶点P1与P2、P2与P3、......、Pn与P1的连线,其中Pn与P1的连线为多边形的封闭边。多边形在裁剪后应得到一个或几个新的多边形,其顶点为Q1、Q2、Q3......、Qn, 主要任务就是求得这些新的顶点。其过程是,首先依次按照窗口的一条边界线L对多边形的顶点Pi(i=1,2,3...,n)进行检查。若顶点在边界L以内,则保留该顶点作为裁剪后新的顶点,反之则予以舍弃。同时对于顶点Pi是否与前一顶点Pi-1处于窗口边解甲归田线L的同侧位置,还须进行检查。若它们分别位于窗口边蜀线的两侧,则应计算边线Pi-1Pi与窗口边线L的交点,并将交点保留下来作为裁剪后新的顶点输出。显然对于多边形的第一个顶点P1来说,上述后一顶检查无意义可以省略。当检查最末一个顶点Pn时,除了进行上述检查外,还须对多边形的封闭边PnP1进行检查。若封闭边PnP1与窗口边界线L相交,则应计算这一点并予以保留。这样通过以上检查便保留并输出各顶点Q1、Q2、Q3、......Qn,在这些顶点之间依次联成边线,即可得到裁剪后新的多边形。
视频教程列表
文章教程搜索
C语言程序设计推荐教程
C语言程序设计热门教程
|