计算机图形学8_二维图形裁剪
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
问题:如何判断线段与窗口的关系?
为使计算机能够快速判断一条直线段与窗口属 何种关系,采用如下编码方法。延长窗口的边, 将二维平面分成九个区域。每个区域赋予4位 编码Ct Cb Cr Cl.其中各位编码的定义如下:
<
Cohen-Sutherland裁剪算法步骤:
裁剪一条线段时,先求出P1P2所在的区号 code1,code2。 若code1=0,且code2=0,则线段P1P2在窗口内, 应取之。 若按位与运算code1&code2≠0,则说明两个端点 同在窗口的上方、下方、左方或右方。可判断线 段完全在窗口外,可弃之。 否则,按第三种情况处理。求出线段与窗口某边 的交点,在交点处把线段一分为二,其中必有一 段在窗口外,可弃之。在对另一段重复上述处理。 在实现本算法时,不必把线段与每条窗口边界依 次求交,只要按顺序检测到端点的编码不为0,才 把线段与对应的窗口边界求交。
Cohen-Sutherland 直线裁剪算法小结
本算法的优点在于简单,易于实现。他可以简 单的描述为将直线在窗口左边的部分删去,按 左,右,下,上的顺序依次进行,处理之后, 剩余部分就是可见的了。在这个算法中求交点 是很重要的,他决定了算法的速度。 特点:用编码方法可快速判断线段的完全可见 和显然不可见。
百度文库
Cohen-Sutherland裁剪
如何判定应该与窗口的哪条边求交呢? 编码中对应位为1的边。 计算线段P1(x1,y1)P2(x2,y2)与窗口边界的交点 if(LEFT&code !=0) { x=XL; y=y1+(y2-y1)*(XL-x1)/(x2-x1);} else if(RIGHT&code !=0) { x=XR; y=y1+(y2-y1)*(XR-x1)/(x2-x1);} else if(BOTTOM&code !=0) { y=YB; x=x1+(x2-x1)*(YB-y1)/(y2-y1);} else if(TOP & code !=0) { y=YT; x=x1+(x2-x1)*(YT-y1)/(y2-y1);}
已知直线:(X1,Y1)(X2,Y2)与水平线Y= K的交点为:
与垂直直线X=R的交点为:
在进行裁剪是除了要求直线与边界线的 交点外,还要判断端点与窗口的位置关系。 为此有: 若编码&0001<>0,端点与左边界有交点; 若编码&0010<>0,端点与右边界有交点; 若编码&0100<>0,端点与下边界有交点; 若编码&1000<>0,端点与上边界有交点;
2.直线段裁剪
直线段裁剪算法比较简单,但非常重要, 是复杂图元裁剪的基础。因为复杂的曲线 可以通过折线段来近似,从而裁剪问题也 可以化为直线段的裁剪问题。 常用的线段裁剪方法有三种:CohenSutherland,中点分割算法和参数化算法。
Cohen-Sutherland裁剪算法
该算法的思想是:对于每条线段P1P2分为三种情 况处理。 (1)若P1P2完全在窗口内,则显示该线段 P1P2简称“取”之。 (2)若P1P2明显在窗口外,则丢弃该线段,简 称“弃”之。 (3)若线段既不满足“取”的条件,也不满足 “弃”的条件,则在交点处把线段分为两段。其 中一段完全在窗口外,可弃之。然后对另一段重 复上述处理。
主要内容
1.点的裁剪 2.直线的裁剪 3.多边形的裁剪 4.字符的裁剪
1.点的裁剪
设窗口由x=xL,x=xR,y=yB,y=yT围成。 对于点(x,y)判别两对不等式:xL<=x<=xR, yB<=y<=yT; 若四个不等式均成立,则点在窗口之内;否则, 点在窗口之外。 最简单的裁剪方法是把各种图形扫描转换为点之 后,再判断各点是否在窗内。但那样太费时,一 般不可取。这是因为有些图形组成部分全部在窗 口外,可以完全排除,不必进行扫描转换。所以 一般采用先裁剪再扫描转换的方法。
else if(RIGHT&code !=0) { x=XR; y=y1+(y2-y1)*(XR-x1)/(x2-x1); } else if(BOTTOM&code !=0) { y=YB; x=x1+(x2-x1)*(YB-y1)/(y2-y1); } else if(TOP & code !=0) { y=YT; x=x1+(x2-x1)*(YT-y1)/(y2-y1); } if(code ==code1) { x1=x;y1=y; code1 =encode(x,y);} else { x2=x;y2=y; code2 =encode(x,y);} } displayline(x1,y1,x2,y2); }
算法伪代码
#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; y=y1+(y2-y1)*(XL-x1)/(x2-x1); }