CGA裁剪算法之Sutherland-Hodgman多边形裁剪算法
Sutherland-Hodgman算法也叫逐边裁剪法,该算法是萨瑟兰德(I.E.Sutherland)和霍德曼(Hodgman)在1974年提出的。
这种算法采用了分割处理、逐边裁剪的方法。这一算法,适合任何凸多边形窗口对任何“凸或者凹,或者平面或者非平面”多边形的裁剪处理。
逐边逐次裁剪特点:逐边是分别用裁剪平面的边界来处理,且裁剪各个边界的处理顺序无关紧要。逐次是每次的裁剪边界对多边形的每条边处理是依次进行的,有顺序要求。
1. 基本思想
“逐边裁剪”,即依次用裁剪窗口的一条边裁剪多边形所有的边。
裁剪边与多边形每条边裁剪,只需要处理“单个裁剪边”与“单个多边形边”的位置关系。多边形顶点列表中,相邻两个端点组成多边形的边,SP作为前后相邻的端点(P第一点除外),则SP与裁剪边的位置关系如下图所示,只有4中可能。
每条裁剪边对多边形的所有边处理后,想输出顶点列表输出1个,或者2个,或者0个(不输出)顶点。
【1】如果边完全可见,则输出P点,注意,因为是“逐次”处理多边形的顶点,所以S点作为前一个点的终点已经摆输出;
【2】如果完全不可见,则不输出,0个;
【3】如果部分可见,分两种情况,如果是离开的情况,则需要输出将交点I作为输出点输出,此时输出1个,其次如果是进入的情况,则需要将交点I以及终点P依次输出,此时输出 2个。
2. 算法的关键问题处理
(1) 处理多边形的特殊点:
【1】多边形的第一个点P1,需要根据它的可见性判定是否输出到输出顶点表,如果可见则输出,并作为起点S。如果不可见,则不输出,但是任然作为S保存,处理后续的第二个点;
【2】处理多边形左后一条边:PnP1,需要分开处理,为了不消除P1的特殊性,可以把P1保存为F(first),这样当处理最后一条边是,即为PnF,可以与其他边一样进行同样处理。
(2)判定顶点与当前裁剪边的可见性
向量叉积法判定。
为简单计,测试点表示为P点。假设窗口边界方向为顺时针,如图中所示,对于其中任一边界向量,从向量起点A向终点B看过去:
【1】如果被测试点P在该边界线右边(即内侧),AB×AP的方向与X-Y平面垂直并指向屏幕里面,即右手坐标系中Z轴的负方向,叉乘结果<0。
【2】反过来,如果P在该边界线的左边(即外侧)内或者边界上,这时AB×AP的方向与X-Y平面垂直并指向屏幕外面,即右手坐标系中Z轴的正方向,叉乘结果>=0。
AB×AP叉乘,右手坐标,中四指头由AB到AP的方向,顺着AB方向,此时大拇指Z正向(朝向你)为结果正, 大拇指Z负半轴(背向你)为负。
如下图,边界AB是顺时针的,所以右手定则时,说些别扭咯。
设:点P(x,y)、点A(xA,yA)、点B(xB,yB),
向量AB={(xB-xA),(yB-yA)},
向量AP={(x-xA),(y-yA)},
那么AB×AP的方向可由下式的符号来确定:
V=(xB-xA)·(y-yA)-(x-xA)·(yB-yA)
因此,当V>=0时,P在边界线内侧, 可见。 而V<0时,P在边界线外侧。
(3)相交线段的求交处理
方法有三种【1】区域编码,处理,【2】中点分割, 【3】参数方程。
因为在已确定两线段为相交情况,则采用参数方程法最合适。
如: 线段P1P2, P3P4, 他们的参数方程如下,
P(s) = P1 + s*(P2 - P1) 0<= s <=1
P(t) = P3 + t*(P4 - P3) 0<= t <=1
则交点P(s) = P(t) ,因为P(s),P(t)都是矢量函数,即,P(s)= [X(s), Y(s)] P(t) = [X(t), Y(t)] 则两个未知量两个方程,可以求解出结果。
【1】如果方程无解,则两线段平行;【2】如果s或者t超出了范围,则两线段不想交且不平行;【3】没有超出范围,则有效交点。
用助阵形式求解方程组最合适。
如:
=,令M=,其行列式=3×1-3×(-2)=9≠0,
∴M-1=.
∴=M-1==,
即方程组的解为
(3)Sutherland_dodman算法,产生一个退化的边界。即裁剪结果,多边形的一部分与窗口边界成和,蜕变边界往返连词,将裁剪结果中多边形中两个彼此相连的部分连在一起。在许多应用中,如“实区域填充”扫描转换,则退化的边界没有影响;但是,对于另一些应用,如“隐藏面消除算法”则需要事先删除这些退化的边界。
可以采用SutherLand-hodMan提出的“顶点排序的办法”处理问题。
3. 程序如下
一个问题