矢量图的多边形裁剪
点:
判断点是否在裁剪区域内(在边界上也作为在区域内),如果是则存储
直线段:
判断直线段与裁剪区域边界是否有交点(直线段与裁剪区域最多有2个交点,曲线可以分解为N段直线段)
无交点
判断直线段某一个顶点是否在裁剪区域内,如果是,则直线段完全在裁剪区域内,储存线段的所有顶点,如果否,则直线段完全在裁剪区域外,不存储。
有交点
如果2个交点,则存储两个交点。如果一个交点,判断直线段两顶点中某一个在裁剪区域内,存储交点和在裁剪区域中的顶点
多边形:
如果主多边形的顶点或者边与裁剪区域的边重叠,裁剪区域的顶点在主多边形的一个边上
方法一:(实际中运用)
则将主多边形重叠的顶点或者边的后一个顶点在X与Y坐标上各加1/1'000'000度,然后计算与裁剪区域的交点。但是会面临一个问题,为了避免重叠,移动过以后又造成了另一次重叠,然后又再次移动。不过在实际使用中,由于程序的精度误差,所以二次重叠的机率非常小,多次重叠更是可以忽略。
方法二:(个人想法,未经证明)
上一方法在实际中可以运用,但是只在算法研究上会有多次移动的情况,我设想了另一个解决办法。
因为重叠部分的顶点也是交点,所以在计算交点以后忽略和顶点一致的交点。此方法并不影响进出性的判断,因为假如是主多边形顶点在裁剪区域的边上,而这个顶点会有主多边形的两条边,那么忽略的交点是2个。如下图,假如顶点6在裁剪多边形上,则可以看作6是g,f重叠在一起,而这时只需要保留顶点6忽略g,f,因为多边形的交点进出性是交替出现,所以减少偶数个相邻交点不影响计算交点进出性。
如果裁剪多边形的顶点在主多边形的一个边上。原理与上面相同,只是要将裁剪多边形在主多边形上的那个顶点放入结果多边形链表中,此时存在一个问题,忽略了两个交点(其实此时被忽略的两个交点重叠,即后面加入的那个顶点),加入了一个顶点,也就是忽略掉了1个交点,会影响多边形交点进出性的计算。我所采取的办法是将加入结果多边形链表的这个顶点作为顶点而不是交点,在计算多边形进出性的时候忽略此点。这时也就是减少了偶数个相邻交点。
主多边形边界与裁剪区域边界无交点
- 主多边形完全在裁剪区域内,则存储主多边形顶点链表
- 裁剪区域完全在主多边形内,则裁剪后多边形外边界是裁剪区域顶点,内边界顶点为主多边形内边界顶点
- 主多边形完全在裁剪区域之外,不存储
主多边形边界与裁剪区域边界有交点
不论主多边形是否为凹多边形或者凸多边形,其外边界取顺时针方向,当为凹多边形时内边界取逆时针方向,这样保证了多边形的内部在边界方向的右侧。
将多边形边界顶点存放入链表中,然后每次取出相邻两个顶点与裁剪多边形的边分别计算交点,然后将交点插入这两个相邻顶点的链表中。
画区域时,找到第一个入点,然后在链表中按顺序往后读取顶点,直至读到第一个出点。这就是一个裁剪区域内的多边形。重复这样的工作多次,直到链表中顶点全部读完。
入点和出点是交替出现的,有多少入点就会有多少出点。
如多边形顶点链表1,2,3,4,5,6,裁剪区域顶点链表A,B,C,D。理想状态下将多边形两顶点所连成的直线与裁剪区域的交点按顺序插入多边形顶点链表中这个顶点之间。如2,3经过裁剪以后会变为2,a,b,3。但是有一个问题,假如裁剪区域顶点链表开始为B,方向为顺时针。那么1,2线段首先会与B,C线段计算出b,然后才会计算到a。如果只是简单的计算出一个交点就插入链表就会造成2,3裁剪以后变为2,b,a,3。所以有必要检验交点的先后顺序。我所采取的方法就是求a,b与2的x或者y坐标之差的绝对值,绝对值小的必为第一个交点。
|
前 |
后 |
内 |
出交点 |
入交点 |
外 |
入交点 |
出交点 |
例如b前面一个a不是多边形顶点,后面一个3是多边形顶点,2在裁剪区域外,那么b也就是出交点。
此后可以忽略,因为暂时不予考虑
对于凹多边形也是一样的原则,例如下图,内多边形7,8,9与裁剪区域有交点i,j。只需要输出时将7,8,9变为j,8,7,i。根据上文定义的填充区域在正方向的右侧,仍可以得到正确的图形