首先先来介绍一下直线裁剪的基本原理:
下图所示的为直线与窗口边界之间可能出现的几种关系。
可以通过检查直线的两个端点是否在窗口之内确定如何对此直线裁剪。
裁剪前:
裁减后:
在上图中,如果一直线的两个端点均在窗口边界之内(如图1中P5到P6的直线),则此直线应保留。
如果一条直线的一个端点在窗口外(如P9)另一个点在窗口内(如P10),则应从直线与边界的交点(P9)处裁剪掉边界之外的线段。
如果直线的两个端点均在边界外,则可分为两种情况:一种情况是该直线全部在窗口之外;
另一种情况是直线穿过两个窗口边界。图中从P3到P4的直线属于前一种情况,应全部裁剪掉;
从P7到P8的直线属于后一种情况,应保留P7到P8的线段,其余部分均裁剪掉。
直线裁剪算法应首先确定哪些直线全部保留或全部裁剪,剩下的即为部分裁剪的直线。
对于部分裁剪的直线则首先要求出这些直线与窗口边界的交点,把从交点开始在边界外的部分裁剪掉。
一个复杂的画面中可能包含有几千条直线,为了提高算法效率,加快裁剪速度,应当采用计算量较小的算法求直线与窗口边界的交点。
下面来介绍一下Cohen-Sutherland直线裁剪算法。
Cohen-Sutherland算法的大意是:对于每条线段P1P2,分为3种情况处理。
①若直线的两个端点P1P2完全在窗口内,则显示该线段P1P2,简称“取”之。
②若直线的两个端点P1P2明显在窗口外,则丢弃该线段,简称“弃”之。
③若线段既不满足“取”的条件,也不满足“弃”的条件,则把线段分为两段。其中一段完全在窗口外,可弃之。然后对另一段重复上述处理。
1.区域码及其建立
Cohen-Sutherland直线裁剪算法的核心是把所有直线的端点均分配一个表示其相对位置的4位二进制代码。此代码称为区域码。
区域码按照端点与窗口边界的相对位置编码,即区域码的4位分别代表端点位于窗口的上、下、左、右。
区域码从右到左的各位所代表的坐标区如下所示:
位 4 3 2 1
坐标区 上 下 右 左
上述各位中某位为1,则表示点位于此坐标区。
窗口周围各坐标区的区域码如下图所示。
由上图可见,位于窗中内的点,其区域码应为0000,
位于窗口左下方的点,其区域码应为0101,其余类推。
区域码各位的值可以通过对端点坐标(x,y)与窗口边界的比较求得。
如果x<xwmin,则区域码的第一位为1,其余各位的确定与此相似。
现在的计算机语言都可以进行位操作,因此,可以通过以下步骤建立区域码:
①计算出端点坐标与窗口边界的差。
②按计算出的各个差的符号把区域码的相应位置为0或1,即
区域码的第一位置为(x-xwmin)的符号位;
区域码的第二位置为(xwmin-x)的符号位;
区域码的第三位置为(y-ywmin)的符号位;
区域码的第四位置为(ywmin-y)的符号位。
2.区域码裁剪算法
对所有直线的端点都建立了区域码之后,就可按区域码判断直线在窗口之内或窗口之外。这可分为如下几种情况:
①若一直线的两个端点的区域码均为0000则此直线在窗口边界之内,应子保留。
②若一直线的两个端点的区域码的同一位同时为1,则此直线全部在窗口边界之外,应子裁剪。
例如,若一直线的一个端点的区域码为1001,另一个端点的区域码为0101,则此两端点的区域码的第一位均为1,说明此两端点均在窗口边界之左,
因此,直线在窗口边界之外,应予裁剪。可用将直线两个端点的区域码进行“与”(&)操作的方法,判断直线是否在窗口之外,
若“与”操作的结果为0000则两端点的区域码任何位均不同时为1,此直线不一定被裁剪。
③以上两种情况之外的直线,有可能穿过窗口,也有可能不穿过窗口。
对这类直线可以进行如下处理:取窗口外的一个端点与窗口边界比较以确定可排除直线的哪一部分,
然后,把直线剩下的部分与其他边界比较,这样一直到直线全部被排除或确定直线的哪一部分在窗口之内为止。
可按“左、右、下、上”的次序建立检查直线端点与窗口边界关系的算法。
例:根据区域编码裁剪算法对P1P2(P1[80,75],P2[-40,0])进行裁剪,以图解形式说明裁剪的过程(已知:XL=0,XR=100,YB=0,YT=50)。