使用计算机处理图形信息时,计算机内部存储的图形往往比较大,而屏幕显示的只是图形的一部分。
如上矩形为显示屏,要显示该多边形,就要进行裁剪
因此需要确定图形哪些部分落在显示区之内,哪些落在显示区之外。这个选择的过程就称为裁剪。
最简单的裁剪方法是把各种图形扫描转换为点之后,再判断点是否在窗口内。
点的裁剪
对于任意一点P(x,y),若满足下列两队不等式:
则点P在矩形窗口内;否则,点P在矩形窗口之外
直线段的裁剪
直线段裁剪算法复杂图形裁剪的基础
直线段和裁剪窗口的可能关系:
- 完全落在窗口内(EF)
- 完全落在窗口外(IJ、CD)
- 与窗口边界相交(HG、AB)
要裁剪一条直线段,首先要判断:
它是否完全落在裁剪窗口内?
它是否完全在窗口外?
如果不满足以上两个条件,则计算它与一个或多个裁剪边界的交点
常用的裁剪算法有三种,即Cohen-Sutherland、中点分割法和Liang-Barsky裁剪算法
Cohen-Sutherland算法
本算法又称为编码裁剪算法,算法的基本思想是对每条直线段分为三种情况处理:
(1)若点p1 和p2完全在裁剪窗口内
“简取”之
(2)若点p1(x1,y1)和p2(x2,y2)均在窗口外,且满足下列四个条件之一:
- x1 < xleft 且 x2 < xleft
- x2 > xright且x2 > xright
- y1 < ybottom 且 y2 < ybottom
- y1 > ytop且y2>ytop
对这四种类型的直线,“简弃”之
“简弃”:认为这几种直线在窗口外,可以抛弃
(3)如果直线段既不满足“简取”的条件,也不满足“简弃”的条件?
需要对直线段按交点进行分段,分段后判断直线是“简取”还是“简弃”。上图中,直线与窗口上边界有交点p3,与右边界有交点p4,求出交点后再对直线进行分段处理
每条线段的端点都赋以四位二进制码D3D2D1D0,编码规则如下:
若x< xleft,则D0=1,否则D0=0
若x > xright,则D1=1,否则D1=0
若y < ybottom,则D2=1,否则D2=0
若y > ytop,则D3=1,否则D3=0
窗口及其延长线所构成了9个区域。根据该编码规则:
- D0对应窗口左边界
- D1对应窗口右边界
- D2对应窗口下边界
- D3对应窗口上边界
裁剪一条线段时,先求出端点p1和p2的编码code1和code2,然后进行二进制的“或”运算和“与”运算 - 若code1|code2=0,对直线段应简取之,说明该直线段在窗口内
- code1&code2 不等于 0,对直线可简弃之
- 若上述两条件均不成立,则需要求出直线段与窗口边界的交点,在交点处把线段一分为二
小结
- Cohen-Sutherland算法用编码的方法实现了对直线段的裁剪
- 编码的思想在图形学中甚至在计算机科学里也是非常重要的,一个很简单的思想可以带来很了不起的作用
- 比较适合两种情况:一是大部分线段完全可见;二是大部分线段完全不可见
存在的问题:最坏情况下,被裁剪线段与窗口4条边计算交点,然后所得的裁剪结果却可能是全部舍弃。
中点分割法
和Cohen-Sutherland算法一样,首先对直线段的端点进行编码
把线段和窗口的关系分成三种情况:
完全在窗口内
完全在窗口外
和窗口有交点
中点分割算法的核心思想是通过二分逼近来确定直线段与窗口的交点
直线p1p2的中点是p3,显然p3在窗口外,舍去。P1p3的中点为p4,p1p4中点p5,p3p4中点p6。
注意
- 若中点不在窗口内,则把中点和离窗口边界最远点构成的线段丢掉,以线段上的另一点和该中点再构成线段求其中点
- 如中点在窗口内,则又以中点和最远点构成线段,并求其中点,知道中点与窗口边界的坐标值在规定的误差范围内相等。
Liang-Barsky算法
在Cohen-Sutherland算法提出后,梁友栋和Brasky又针对标准矩形窗口提出来更快的Liang-Brasky直线段裁剪算法。
Liang-Barsky算法的主要思想:
(1)用参数方程表示一条直线
前面我们都是用直线的标准方程或者是斜截式方程
(2)把被裁剪的红色直线段看成是一条有方向的线段,把窗口的四条边分成两类:入边和出边
直线和入边有两个交点,和出边有两个交点,绿色点为起点和终点。一共有6个交点,分为两组,入边交点和起点为一组,出边交点和终点有一组
裁剪结果的线段起点是直线和两条入边的交点以及始端点三个点里面最前面的一个点,即参数u最大的那个点;
裁剪线段的终点是和两条出边的交点以及端点最后面的一个点,取参数u最小的那个点。
两个箭头所指的点即为裁剪线段的起点和终点。
值得注意的是,当u从负无穷到正无穷遍历直线时,首先对裁剪窗口的两条边界直线(下边和左边)从外面向里面移动,再对裁剪窗口两条边界直线(上边和右边)从里面向外面移动。
如果用u1,u2分别表示线段(u1<=2)可见部分的开始和结束
- u1=max(0,ul,ub)
- u2=min(1,ut,ur)
Liang-Barsky算法的基本实现
Liang-Barsky算法的基本出发点是直线方程
视频教程请看:http://www.icourse163.org/learn/CAU-45006?tid=1002164003#/learn/content?type=detail&id=1002868267&cid=1003270499
文档请看:http://pan.baidu.com/s/1dE0YyQl
多边形的裁剪
用直线裁剪法裁剪左边多边形,得到右边的图形
即得到一系列不连续的直线段!得到的结果是不正确的
而实际上,应该得到的是下图所示的右边界的区域:
多边形裁剪算法的输出应该是裁剪后的多边形边界的定点序列!
Sutherland-Hodgeman多边形裁剪
该算法的基本思想是将多边形边界作为一个整体,每次用窗口的一条边对要裁剪的多边形和中间结果多边形进行裁剪,体现一种份而治之的思想。
裁剪得到的结果多边形的顶点有两部分组成:
落在可见一侧的原多边形顶点
多边形的边与裁剪窗口边界的交点
根据多边形每一边与窗口边所形成的位置关系,沿着多边形依次处理顶点会遇到四种情况:
(1)第一点S在不可见侧面,而第二点P在可见侧
此时交点I和点P均被加入到输出顶点表中
(2)是S和P都在可见侧
则P被加入到输出顶点表中
(3)S在可见侧,而P在不可见侧
则交点I被加入到输出顶点表中
(4)如果S和P都在不可见侧
输出顶点表中不增加任何顶点
在窗口的一条裁剪边界处理完所有顶点后,其输出顶点表将用窗口的下一条边界继续裁剪。
如图多边形,用矩形框去裁剪
输入:123456
输出:a345b
根据上面讲的,我们将12、16舍去
Sutherland-Hodgema算法不足之处
利用Sutherland-Hodgema裁剪算法对凸多边形进行裁剪可以获得正确的裁剪结果,但是凹多边形会出错。如下图
文字裁剪
屏幕上显示的不仅仅是多边形和直线等,还显示字符。字符如何来处理?
字符并不是由直线段组成的。文字裁剪包括以下几种:
串精度裁剪
字符精度裁剪
笔划/像素精度裁剪
串精度裁剪
当字符串中的所有字符都在裁剪窗口内时,就全部保留,否则舍弃整个字符串
第一个字符串S在窗口外,所以将String1舍弃,保留String2
字符精度裁剪
在进行裁剪时,任何与窗口有重叠或落在窗口边界以外的字符都被裁剪掉
因为t与窗口重叠,所以最后的结果为右边所示
笔划/像素精度裁剪
将笔划分解成直线段对窗口做裁剪。需判断字符串中各字符的哪些像素、笔划的哪一部分在窗口内,保留窗口内部分,裁剪掉窗口外的部分
STRING2完全在窗口内,所以保留。STRING1有一半在窗口外,舍弃,有一半在窗口内,保留。