直线段裁剪算法比较简单,但非常重要,是复杂图元裁剪的基础。因为复杂的曲线可以通过折线段来近 似,从而裁剪问题也可以化为直线段的裁剪问题。常用的线段裁剪方法有三种: Cohen- Sutherland,中点分 割算法和梁友栋一 barkey算法 2.5.1.1 CohenSutherland裁剪 该算法的思想是:对于每条线段PP2分为三种情况处理。(1)若PP2完全在窗口内,则显示该线段PP2 简称“取"之。(2)若PP2明显在窗口外,则丢弃该线段,简称“弃”之。(3)若线段既不满足“取”的条件,也 不满足“弃”的条件,则在交点处把线段分为两段。其中一段完全在窗口外,可弃之。然后对另一段重复上述 处理。 为使计算机能够快速判断一条直线段与窗口属何种关系,采用如下编码方法。延长窗口的边,将二维平 面分成九个区域。每个区域赋予4位编码 CtcbCro1.其中各位编码的定义如下 1 y>y 1 y<ymim x> other other 1001 1000 1010 010 P3 0101 0110 图2.5.2多边形裁剪区域编码图2.5.3线段裁剪 裁剪一条线段时,先求出PP2所在的区号 codel,code。若 codel=0,且code2=0,则线段PP2在窗口内 应取之。若按位与运算code&code2判,则说明两个端点同在窗口的上方、下方、左方或右方。可判断线段 完全在窗口外,可弃之。否则,按第三种情况处理。求出线段与窗口某边的交点,在交点处把线段一分为 ,其中必有一段在窗口外,可弃之。在对另一段重复上述处理。在实现本算法时,不必把线段与每条窗 口边界依次求交,只要按顺序检测到端点的编码不为0,才把线段与对应的窗口边界求交。 Cohen- Sutherland裁减算法 #define left l #define right 2 #define bottom 4 #define top 8 int encode(float x, float y) i int c=0: if(x<XL)c|=LEFT; if(x)XR)c=RIGHT f(x<YB)c=BOTTOM if(x<YT)c=TOP; retrun c void CS LineClip(xl, y1, x2, y2, XL, XR, YB, YT) float xl, y1, x 2, y2, XL, XR, YB, YT /(x1,y1)(x2,y2)为线段的端点坐标,其他四个参数定义窗口的边界 i int codel, code2, code codel=encode(xl, y1) code2=encode(x2, y2) i if(codel&code2!=0)return if(codel=0) code code2 f(LEFT&code !=0) [x=XI 计算机图形学第二章第28页共27页计算机图形学 第二章 第 28 页 共 27 页 直线段裁剪算法比较简单,但非常重要,是复杂图元裁剪的基础。因为复杂的曲线可以通过折线段来近 似,从而裁剪问题也可以化为直线段的裁剪问题。常用的线段裁剪方法有三种:Cohen-Sutherland,中点分 割算法和梁友栋-barskey 算法。 2.5.1.1 Cohen-Sutherland 裁剪 该算法的思想是:对于每条线段 P1P2分为三种情况处理。(1)若 P1P2完全在窗口内,则显示该线段 P1P2 简称“取”之。(2)若 P1P2明显在窗口外,则丢弃该线段,简称“弃”之。(3)若线段既不满足“取”的条件,也 不满足“弃”的条件,则在交点处把线段分为两段。其中一段完全在窗口外,可弃之。然后对另一段重复上述 处理。 为使计算机能够快速判断一条直线段与窗口属何种关系,采用如下编码方法。延长窗口的边,将二维平 面分成九个区域。每个区域赋予 4 位编码 CtCbCrCl.其中各位编码的定义如下: 图 2.5.2 多边形裁剪区域编码 图 2.5.3 线段裁剪 裁剪一条线段时,先求出 P1P2 所在的区号 code1,code2。若 code1=0,且 code2=0,则线段 P1P2 在窗口内, 应取之。若按位与运算 code1&code2≠0,则说明两个端点同在窗口的上方、下方、左方或右方。可判断线段 完全在窗口外,可弃之。否则,按第三种情况处理。求出线段与窗口某边的交点,在交点处把线段一分为 二,其中必有一段在窗口外,可弃之。在对另一段重复上述处理。在实现本算法时,不必把线段与每条窗 口边界依次求交,只要按顺序检测到端点的编码不为 0,才把线段与对应的窗口边界求交。 Cohen-Sutherland 裁减算法 #define LEFT 1 #define RIGHT 2 #define BOTTOM 4 #define TOP 8 int encode(float x,float y) { int c=0; if(x<XL) c|=LEFT; if(x>XR) c|=RIGHT; if(x<YB) c|=BOTTOM; if(x<YT) c|=TOP; retrun c; } void CS_LineClip(x1,y1,x2,y2,XL,XR,YB,YT) float x1,y1,x2,y2,XL,XR,YB,YT; //(x1,y1)(x2,y2)为线段的端点坐标,其他四个参数定义窗口的边界 { int code1,code2,code; code1=encode(x1,y1); code2=encode(x2,y2); while(code1!=0 ||code2!=0) { if(code1&code2 !=0) return; code = code1; if(code1==0) code = code2; if(LEFT&code !=0) { x=XL;