与Sutherland-Hodgeman算法的比较:
Sutherland-Hodgeman算法解决了裁剪窗口为凸多边形窗口的问题,但一些应用需要涉及任意多边形窗口(含凹多边形窗口)的裁剪,就可能会出错。而Weiler-Atherton多边形裁剪算法正是满足这种要求的算法。
如下图,对凹多边形 P1P2P3P4 进行裁剪,Sutherland-Hodgeman算法会得到如下中间图形,但正确的裁剪结果应该为最右边的图。
算法描述:
在算法中,裁剪窗口、被裁剪多边形可以是任意多边形:凸的、凹的(内角大于180o)、甚至是带有内环的(子区),见下图。
裁剪窗口和被裁剪多边形处于完全对等的地位,这里我们称:
1、被裁剪多边形为主多边形,记为A;
2、裁剪窗口为裁剪多边形,记为B。
主多边形A和裁剪多边形B的边界将整个二维平面分成了四个区域:
1、A∩B(交:属于A且属于B);
2、A-B(差:属于A不属于B);
3、B-A(差:属于B不属于A);
4、A∪B(并:属于A或属于B,取反;即:不属于A且不属于B)。
内裁剪:即通常意义上的裁剪,取图元位于窗口之内的部分,结果为A∩B。
外裁剪:取图元位于窗口之外的部分,结果为A-B。
观察下图,不难发现裁剪结果区域的边界由被裁剪多边形 A 的部分边界和裁剪窗口 B 的部分边界两部分构成,并且在交点处边界发生交替,即由被裁剪多边形 A 的边界转至裁剪窗口 B 的边界,或者反之。
由于多边形构成一个封闭的区域,所以,如果被裁剪多边形和裁剪窗口有交点,则交点成对出现。这些交点分成两类:
一类称 “进” 点,即被裁剪多边形由此点进入裁剪窗口,如图中 J1,J3,J5,J7,J9 ,J11这几个点;
一类称 “出” 点,即被裁剪多边形由此点离开裁剪窗口,如图中 J0,J2,J4,J6,J8 ,J10这几个点 。
算法步骤:
(以下,主多边形即被裁剪多边形,裁剪多边形即裁剪窗口。)
(1) 建立主多边形和裁剪多边形的顶点表,如下图所示。
(2) 求主多边形和裁剪多边形的交点,并将这些交点按顺序插入两个多边形的顶点表中。在两多边形顶点表中的相同交点间建立双向指针。
(3) 裁剪,如果存在没有被跟踪过的交点,执行以下步骤:
- 建立裁剪结果多边形的顶点表。
- 选取任意 没有被跟踪过的交点 为始点,将其输出到结果多边形顶点表中。
- 如果该交点为 进点 ,跟踪主多边形边界;否则跟踪裁剪多边形边界。
- 跟踪多边形边界,每遇到多边形顶点,将其输出到结果多边形顶点表中,直到遇到新的交点。
- 将该交点输出到结果多边形顶点表中,并通过连接该交点的双向指针改变跟踪方向(如果上一步跟踪的是主多边形边界,现在改为跟踪裁剪多边形边界;反之,如果上一步跟踪的是裁剪多边形边界,现在改为跟踪主多边形边界)。
- 重复第 4 、5 步直到回到起点。
如图,我这里选择没有被跟踪过的交点 J7 为始点,将 J7 输出到多边形顶点表中。-------> 交点 J7 为 进点,则跟踪主多边形(即顺着左边顶点表往下走) -------> 这时遇到新的交点 J0 -------> 将交点 J0 输出到多边形顶点表中,改变跟踪方向(即顺着箭头来到了右边的顶点表) -------> 现在开始重复第 4、5步,直到回到起点 J7 。
如上图,此番操作完成后,这时多边形顶点表中的内容为: J7 , J0 , q0 , J3 , J4 , J5 , J6 , J7 .
此时,任然有没被跟踪过的交点,再次选取任意没被跟踪过的交点,进行如上操作,直到所有的交点都被跟踪完毕,则裁剪结束。
交点的奇异情况:
算法特点:
1、裁剪窗口可以是矩形、任意凸多边形、任意凹多边形。
2、可实现被裁剪多边形相对裁剪窗口的内裁或外裁,即保留窗口内的图形或保留窗口外的图形,因此在三维消隐中可以用来处理物体表面间的相互遮挡关系。
3、裁剪思想新颖,方法简洁,裁剪一次完成,与裁剪窗口的边数无关。
核心代码:
PS: 这里是完整代码,欢迎移步: 进行下载