Javascript Clipper library, v6(介绍目录)
1.老祖宗C#版的Clipper2
Clipper2库可以对简单和复杂的多边形执行交集intersection、并并union、差异difference和异或XOR 布尔运算。它还执行多边形偏移
github地址:GitHub - AngusJohnson/Clipper2: Polygon Clipping and Offsetting - C++, C# and Delphi
2.目前的移植版本
基于C#版的移植版本和语言如下
语言 | 版本 | 文档地址 |
JavaScript | Javascript_Clipper_6.4.2.2_fpoint.zip(更新2017-09-08) | https://sourceforge.net/p/jsclipper/wiki/Home%206/ |
---|---|---|
WASM | Clipper2-WASM | GitHub - ErikSom/Clipper2-WASM: WASM port of Clipper 2 for Polygon Clipping and Offsetting |
Java | Clipper2-java | GitHub - micycle1/Clipper2-java: Java port of Clipper2, a Polygon Clipping and Offsetting Library |
Kotlin | clipper2-kotlin | GitHub - urbanistic/clipper2-kotlin |
golang | goclipper2 | GitHub - epit3d/goclipper2 |
3.JavaScript Clipper文档
3.1 使用前须知
操作对象
多边形 polygons和线条 lines
操作方式
裁剪clipping和偏移offsetting
区别其他库(看点)
(1)处理所有类型多边形,包括自相交多边形
(2)支持多个多边形填充规则(偶奇,非零,正,负)
(3)执行速度快
(4)直线line和多边形polygon的偏移offsetting操作
术语:
(1)Clipping裁剪
一般认为裁剪就是给定的一个多边形(当然可以多个多边形),超出多边形之外的剪切掉,换算的是交集。但在本文档中,它指的是四种布尔操作(交集intersection、并并union、差异difference和异或XOR )中的任何一种。
(2)subject/clip
被裁剪对象叫做subject, clip window等称为clip
(3)segment线段
由相连的两点(point/vertice)表示
(4)Path路径
直线或者多边形有序顶点序列,由一系列segment构成的路径
Open paths是指起点和终点不相连的Paths, 也叫做polylines
Close paths是指起点和终点相连的Paths,通常叫做polygon
subject可能是Open paths, 也可能是closed paths
clip只能是closed paths.
(5)Contour轮廓
同path术语
(6)Line直线
或者polyline折线是包含2个或更多顶点的开放路径。
(7)Polygon多边形
在本文档中,多边形指的是已知闭合的路径。
(8)simple polygons简单多边形
由一条不自交(self-intersect)的Close Paths构成的图形称为简单多边形(simple polygons)
(9)complex polygons复杂多边形
如果Closed paths自相交,或者由多条Paths组成的polygons, 称为复杂多边形(complex polygons)
(7)Polygon Hole洞
是一个多边形内的封闭区域,它不是多边形的一部分。形成孔外边界的多边形称为孔多边形。 holes通常是由位于outer polygon contour内部的inner polygon contour 组成。
(8)Polygon Filling region填充区域
简单多变形(simple polygons)的填充区域是固定的,复杂多变形(complex polygons)的填充区域(Filling region)依赖填充规则(Filling rule),填充规则决定什么是hole, 什么不是hole, hole不填充,不属于填充区域,除掉hole的部分都属于填充区域。
(9)Polygon Filling Rule多边形填充规则:
通过填充,可以表明哪些区域是位于Closed path的内部,哪些区域是位于Closed path的外部。Clipper2支持4种填充规则(Filling rule),分别是:EvenOdd, NonZero, Positive, Negative,其中EvenOdd规则是基于射线法确定,NonZero, Positive, Negative是基于图形的winding number确定。
- EvenOdd: 也称交替填充( alternate filling),从图形的外部一点引一条射线,第一次相交Paths, 相应的区域填充,第二次相交的Paths,相应区域不填充,第三次相交Paths,相应区域填充,依次类推
- NonZero: Winding number不为0的部分填充
- Positive: Winding number 大于0的部分填充
- Negative: Winding number 小于0的部分填充
EvenOdd规则和Paths中edge direction和Winding number无关,其它三个与Paths中edge direction和Winding number相关。
(10)Winding number绕圈数
Winding number可以理解为绕圈数 ,详细解释见后续章节
(11)Touching
在Closed Paths中,segments通常被叫做edge.
- Edge touching是指edge共线(collinear)或重合(overlap)
- Polygon touching是指当两个polygon有Edge touching
(12)Polygon offseting
Polygon offseting就是将polygon变大或者变小。
Clipper2的offseting支持(inflating/deflating),不支持单方向的offseting,比如horizontal or vertical offseting。对于Open paths or Closed paths,Clipper都支持offseting
1. Join type
做Polygon offseting时,edge的连接类型(Join type)可能是Square、Round、Miter,这主要是对连接处非90度的情况进行处理的。它们分别的功能是:
- Square:当edge的join处,角度小于90度时,当inflate/deflate polygon时,会将尖角切掉,并且添加一条线段,添加的线段到join vertex的距离是inflate/deflate的offset。
- Round: 当edge的join处,角度小于90度时,当inflate/deflate polygon时,会将尖角切掉,并且添加一条凸型曲线,添加的曲线到join vertex的距离是inflate/deflate的offset。
- Miter: 当edge的join处,角度小于90度时,当inflate/deflate polygon时,会将尖角切掉,并且添加一条线段,添加的线段到join vertex的距离是inflate/deflate的offset * miter, miter的默认值是2,当miter为无穷大时,这种情况下inflate/deflate将保留原来图形的尖角(spike)。
2. End type
当进行做Polygon offseting时,由于input可能是Open paths or Closed paths,End type将指明如何对待input的ending vertices.
- Polygon: output result path将会被当做polygon(首尾相连,填充内部)
- Join: output result path 将会被当作polyline(首尾相连,内部不填充)–not clear
- Square: ends 延长offset长度,采用Square的方法截短
- Round:ends 延长offset长度,采用Square的方法截短
- Butt: ends不延长,采用Square方法截断
当对Polygons进行inflate/deflate时,EndType必须选择 EndType.Polygon,如果选择别的类型,将会支队polygon的outline进行inflate/deflate
3.2 Clipper2 中注意事项
3.2.1. polygon touching problem
由于subject可能是Open paths,也可能是closed paths,clip只能是closed paths.那么我们有时可能是clip closed paths,有时是clip open paths.
用的最多的是clip closed paths,这种情况下得到的外层contour一般是逆时针的(anti-clockwise/counter-clockwise),内层holes是顺时针的(clockwise),这意味着用EvenOdd填充方法或NonZero填充方法得到的contour是一样的。
clip closed paths最大的一个问题是得到的结果可能还有polygon touching的情况,如果遇到这样的情况,作者的建议是再调用一次union,那么得到的应该是最简(simplest/clean)形式的polygon。
3.2.2 Self-intersection polygon
boolean操作支持self-intersection polygon
offseting操作不支持self-intersection polygon
3.2.3 Rounding
在计算几何中,由于坐标是由离散的实数表示的(不管时整型还是浮点数),那么,从理论上来说,如果我们需要得到确切的坐标(比如两条线的交点),几何计算就不可能是numerically robust的。
Clipper2预期到了坐标的不精确,管理这种不精确性,做到了numerically robust,主要是通过以下几点:
- 用整型表示所有的内部坐标(by using integer variables rather than floats, maximum imprecision is constant. This simplifies differentiating significant from insignificant imprecision)。
- 使用算法来解决由于不精确性带来的坐标不是严格不等的问题
- 内部计算对所有的结果进行round
3.2.4 Self-intersection artefacts
在做union操作时,可能会有自相交的局部图形存在:
3.2.5 IntPoit整数坐标点
在本文档中,多边形所有点的集合在clipper2库内部处理的时候都要求是整数。
而实际工程中,多边形点坐标,通常都是double类型。
通常需要对double类型的点,进行放大,转换为int类型,
然后进行实际的求交计算,
再将求交结果进行等比例的缩小,转回实际的double类型
这个放大/缩小的比例,这里采用1e7
源码:有7625行源代码
3.3 将Clipper与SVG和Canvas一起使用示例:
Clipper 6 Info and Examples演示例子和源码
3.4 文档使用目录
(1)JS-Clipper2之ClipperBase
(2)JS-Clipper2之Clipper
(3)JS-Clipper2之Types
(4)JS-Clipper2之PolyTree
(5)JS-Clipper2之PolyNode
(6)JS-Clipper2之ClipperOffset