diff --git a/src/geo/polygon.js b/src/geo/polygon.js index 362bc3d3..4c1b7481 100644 --- a/src/geo/polygon.js +++ b/src/geo/polygon.js @@ -17,11 +17,24 @@ const { config, util, polygons, newBounds, newPoint } = base; const POLY = polygons, XAXIS = new THREE.Vector3(1,0,0), DEG2RAD = Math.PI / 180, - clib = self.ClipperLib, - clip = clib.Clipper, - ctyp = clib.ClipType, - ptyp = clib.PolyType, - cfil = clib.PolyFillType; + ClipperLib = self.ClipperLib, + Clipper = ClipperLib.Clipper, + ClipType = ClipperLib.ClipType, + PolyType = ClipperLib.PolyType, + PolyFillType = ClipperLib.PolyFillType, + CleanPolygon = Clipper.CleanPolygon, + FillNonZero = PolyFillType.pftNonZero, + FillEvenOdd = PolyFillType.pftEvenOdd, + PathSubject = PolyType.ptSubject, + PathClip = PolyType.ptClip, + EndType = ClipperLib.EndType, + JoinType = ClipperLib.JoinType, + PolyTree = ClipperLib.PolyTree, + ClipDiff = ClipType.ctDifference, + ClipUnion = ClipType.ctUnion, + ClipIntersect = ClipType.ctIntersection, + ClipperOffset = ClipperLib.ClipperOffset + ; let seqid = Math.round(Math.random() * 0xffffffff); @@ -1519,7 +1532,7 @@ class Polygon { * non-nested polygons. used primarily in slicer/connectLines. */ clean(deep, parent, merge = config.clipperClean) { - let clean = clip.CleanPolygon(this.toClipper()[0], merge), + let clean = CleanPolygon(this.toClipper()[0], merge), poly = fromClipperPath(clean, this.getZ()); if (poly.length === 0) return this; if (deep && this.inner) { @@ -1590,23 +1603,21 @@ class Polygon { */ offset_open(distance, type = 'miter') { if (this.isOpen()) { - let cjnt = clib.JoinType, - cety = clib.EndType, - coff = new clib.ClipperOffset(), - ctre = new clib.PolyTree(), + let coff = new ClipperOffset(), + tree = new PolyTree(), entt = { - 'square' : cety.etOpenSquare, - 'round' : cety.etOpenRound, - 'miter' : cety.etOpenSquare - }[type] || cety.etOpenSquare, + 'square' : EndType.etOpenSquare, + 'round' : EndType.etOpenRound, + 'miter' : EndType.etOpenSquare + }[type] || EndType.etOpenSquare, jntt = { - 'square': cjnt.jtSquare, - 'round': cjnt.jtRound, - 'miter': cjnt.jtMiter - }[type] || cjnt.jtMiter; + 'square': JoinType.jtSquare, + 'round': JoinType.jtRound, + 'miter': JoinType.jtMiter + }[type] || JoinType.jtMiter; coff.AddPaths(this.toClipper(), jntt, entt); - coff.Execute(ctre, distance * config.clipper); - return POLY.fromClipperTree(ctre, this.getZ(), null, null, 0); + coff.Execute(tree, distance * config.clipper); + return POLY.fromClipperTree(tree, this.getZ(), null, null, 0); } else { return this.offset(distance); } @@ -1748,16 +1759,16 @@ class Polygon { */ diff(poly) { let fillang = this.fillang && this.area() > poly.area() ? this.fillang : poly.fillang, - clip = new clib.Clipper(), - ctre = new clib.PolyTree(), + clip = new Clipper(), + tree = new PolyTree(), sp1 = this.toClipper(), sp2 = poly.toClipper(); - clip.AddPaths(sp1, ptyp.ptSubject, true); - clip.AddPaths(sp2, ptyp.ptClip, true); + clip.AddPaths(sp1, PathSubject, true); + clip.AddPaths(sp2, PathClip, true); - if (clip.Execute(ctyp.ctDifference, ctre, cfil.pftEvenOdd, cfil.pftEvenOdd)) { - poly = POLY.fromClipperTree(ctre, poly.getZ()); + if (clip.Execute(ClipDiff, tree, FillEvenOdd, FillEvenOdd)) { + poly = POLY.fromClipperTree(tree, poly.getZ()); poly.forEach(p => { p.fillang = fillang; }) @@ -1773,15 +1784,15 @@ class Polygon { */ mask(poly, nullOnEquiv, minarea) { let fillang = this.fillang && this.area() > poly.area() ? this.fillang : poly.fillang, - clip = new clib.Clipper(), - ctre = new clib.PolyTree(), + clip = new Clipper(), + tree = new PolyTree(), sp1 = this.toClipper(), sp2 = poly.toClipper(); - clip.AddPaths(sp1, ptyp.ptSubject, true); - clip.AddPaths(sp2, ptyp.ptClip, true); + clip.AddPaths(sp1, PathSubject, true); + clip.AddPaths(sp2, PathClip, true); - if (clip.Execute(ctyp.ctIntersection, ctre, cfil.pftEvenOdd, cfil.pftEvenOdd)) { - poly = POLY.fromClipperTree(ctre, this.getZ(), undefined, undefined, minarea); + if (clip.Execute(ClipIntersect, tree, FillEvenOdd, FillEvenOdd)) { + poly = POLY.fromClipperTree(tree, this.getZ(), undefined, undefined, minarea); poly.forEach(p => { p.fillang = fillang; }) @@ -1810,17 +1821,17 @@ class Polygon { } } - let clip = new clib.Clipper(), - ctre = new clib.PolyTree(), - type = inter ? ctyp.ctIntersection : ctyp.ctDifference, + let clip = new Clipper(), + tree = new PolyTree(), + type = inter ? ClipIntersect : ClipDiff, sp1 = target.toClipper(), sp2 = POLY.toClipper(polys); - clip.AddPaths(sp1, ptyp.ptSubject, false); - clip.AddPaths(sp2, ptyp.ptClip, true); + clip.AddPaths(sp1, PathSubject, false); + clip.AddPaths(sp2, PathClip, true); - if (clip.Execute(type, ctre, cfil.pftEvenOdd, cfil.pftEvenOdd)) { - let cuts = POLY.fromClipperTree(ctre, target.getZ(), null, null, 0); + if (clip.Execute(type, tree, FillEvenOdd, FillEvenOdd)) { + let cuts = POLY.fromClipperTree(tree, target.getZ(), null, null, 0); cuts.forEach(no => { // heal open but really closed polygons because cutting // has to open the poly to perform the cut. but the result @@ -1841,22 +1852,22 @@ class Polygon { intersect(poly, min) { if (!this.overlaps(poly)) return null; - let clip = new clib.Clipper(), - ctre = new clib.PolyTree(), - sp1 = this.toClipper(), - sp2 = poly.toClipper(), - minarea = min >= 0 ? min : 0.1; - if (this.isInside(poly)) { return [this]; } - clip.AddPaths(sp1, ptyp.ptSubject, true); - clip.AddPaths(sp2, ptyp.ptClip, true); + let clip = new Clipper(), + tree = new PolyTree(), + sp1 = this.toClipper(), + sp2 = poly.toClipper(), + minarea = min >= 0 ? min : 0.1; - if (clip.Execute(ctyp.ctIntersection, ctre, cfil.pftNonZero, cfil.pftNonZero)) { + clip.AddPaths(sp1, PathSubject, true); + clip.AddPaths(sp2, PathClip, true); + + if (clip.Execute(ClipIntersect, tree, FillNonZero, FillNonZero)) { let inter = POLY - .fromClipperTreeUnion(ctre, poly.getZ(), minarea) + .fromClipperTreeUnion(tree, poly.getZ(), minarea) // .filter(p => p.isEquivalent(this) || p.isInside(this)) .filter(p => p.isInside(this)); return inter; @@ -1890,7 +1901,7 @@ class Polygon { } let clip = this.toClipper(), - res = clib.Clipper.SimplifyPolygons(clip, cfil.pftNonZero); + res = CLIB.Clipper.SimplifyPolygons(clip, FillNonZero); if (!(res && res.length)) { return null; @@ -1919,17 +1930,17 @@ class Polygon { if (!this.overlaps(poly)) return null; let fillang = this.fillang && this.area() > poly.area() ? this.fillang : poly.fillang, - clip = new clib.Clipper(), - ctre = new clib.PolyTree(), + clip = new Clipper(), + tree = new PolyTree(), sp1 = this.toClipper(), sp2 = poly.toClipper(), minarea = min >= 0 ? min : 0.1; - clip.AddPaths(sp1, ptyp.ptSubject, true); - clip.AddPaths(sp2, ptyp.ptClip, true); + clip.AddPaths(sp1, PathSubject, true); + clip.AddPaths(sp2, PathClip, true); - if (clip.Execute(ctyp.ctUnion, ctre, cfil.pftEvenOdd, cfil.pftEvenOdd)) { - let union = POLY.fromClipperTreeUnion(ctre, poly.getZ(), minarea); + if (clip.Execute(ClipUnion, tree, FillEvenOdd, FillEvenOdd)) { + let union = POLY.fromClipperTreeUnion(tree, poly.getZ(), minarea); if (all) { if (union.length === 2) { return null; diff --git a/src/geo/polygons.js b/src/geo/polygons.js index dfd9fe11..4201b44c 100644 --- a/src/geo/polygons.js +++ b/src/geo/polygons.js @@ -18,11 +18,26 @@ const DEG2RAD = Math.PI / 180, SQR = util.sqr, ABS = Math.abs; -const clib = self.ClipperLib, - clip = clib.Clipper, - ctyp = clib.ClipType, - ptyp = clib.PolyType, - cfil = clib.PolyFillType; +const ClipperLib = self.ClipperLib, + Clipper = ClipperLib.Clipper, + ClipType = ClipperLib.ClipType, + PolyType = ClipperLib.PolyType, + PolyFillType = ClipperLib.PolyFillType, + CleanPolygon = Clipper.CleanPolygon, + CleanPolygons = Clipper.CleanPolygons, + SimplifyPolygons = Clipper.SimplifyPolygons, + FillNonZero = PolyFillType.pftNonZero, + FillEvenOdd = PolyFillType.pftEvenOdd, + PathSubject = PolyType.ptSubject, + PathClip = PolyType.ptClip, + EndType = ClipperLib.EndType, + JoinType = ClipperLib.JoinType, + PolyTree = ClipperLib.PolyTree, + ClipDiff = ClipType.ctDifference, + ClipUnion = ClipType.ctUnion, + ClipIntersect = ClipType.ctIntersection, + ClipperOffset = ClipperLib.ClipperOffset + ; const POLYS = base.polygons = { rayIntersect, @@ -152,7 +167,7 @@ function fromClipperTreeUnion(tnode, z, minarea, tops, parent) { function cleanClipperTree(tree) { if (tree.m_Childs) for (let child of tree.m_Childs) { - child.m_polygon = clip.CleanPolygon(child.m_polygon, config.clipperClean); + child.m_polygon = CleanPolygon(child.m_polygon, config.clipperClean); cleanClipperTree(child.m_Childs); } @@ -354,31 +369,31 @@ function subtract(setA, setB, outA, outB, z, minArea, opt = {}) { outB.appendAll(filter(oB)); } } else { - let clip = new clib.Clipper(), - ctre = new clib.PolyTree(), + let clip = new Clipper(), + tree = new PolyTree(), sp1 = toClipper(setA), sp2 = toClipper(setB); // more expensive? worth it? clip.StrictlySimple = true; if (outA) { - clip.AddPaths(sp1, ptyp.ptSubject, true); - clip.AddPaths(sp2, ptyp.ptClip, true); - if (clip.Execute(ctyp.ctDifference, ctre, cfil.pftEvenOdd, cfil.pftEvenOdd)) { - cleanClipperTree(ctre); - filter(fromClipperTree(ctre, z, null, null, min), outA); + clip.AddPaths(sp1, PathSubject, true); + clip.AddPaths(sp2, PathClip, true); + if (clip.Execute(ClipDiff, tree, FillEvenOdd, FillEvenOdd)) { + cleanClipperTree(tree); + filter(fromClipperTree(tree, z, null, null, min), outA); } } if (outB) { if (outA) { - ctre.Clear(); + tree.Clear(); clip.Clear(); } - clip.AddPaths(sp2, ptyp.ptSubject, true); - clip.AddPaths(sp1, ptyp.ptClip, true); - if (clip.Execute(ctyp.ctDifference, ctre, cfil.pftEvenOdd, cfil.pftEvenOdd)) { - cleanClipperTree(ctre); - filter(fromClipperTree(ctre, z, null, null, min), outB); + clip.AddPaths(sp2, PathSubject, true); + clip.AddPaths(sp1, PathClip, true); + if (clip.Execute(ClipDiff, tree, FillEvenOdd, FillEvenOdd)) { + cleanClipperTree(tree); + filter(fromClipperTree(tree, z, null, null, min), outB); } } } @@ -459,16 +474,16 @@ function subtract(setA, setB, outA, outB, z, minArea, opt = {}) { * @returns {?Polygon[]} */ function diff(setA, setB, z) { - let clip = new clib.Clipper(), - ctre = new clib.PolyTree(), + let clip = new Clipper(), + tree = new PolyTree(), sp1 = toClipper(setA), sp2 = toClipper(setB); - clip.AddPaths(sp1, ptyp.ptSubject, true); - clip.AddPaths(sp2, ptyp.ptClip, true); + clip.AddPaths(sp1, PathSubject, true); + clip.AddPaths(sp2, PathClip, true); - if (clip.Execute(ctyp.ctDifference, ctre, cfil.pftEvenOdd, cfil.pftEvenOdd)) { - return fromClipperTree(ctre, z); + if (clip.Execute(ClipDiff, tree, FillEvenOdd, FillEvenOdd)) { + return fromClipperTree(tree, z); } else { return null; } @@ -503,24 +518,6 @@ function sumCirc(polys) { return sum; } -/** - * @param {Polygon[]} polys - * @param {number} distance offset - * @param {number} [z] defaults to 0 - */ -// function expand_lines(poly, distance, z) { -// let fact = config.clipper, -// cjnt = clib.JoinType, -// cety = clib.EndType, -// coff = new clib.ClipperOffset(), -// ctre = new clib.PolyTree(); - -// coff.AddPaths(poly.toClipper(), cjnt.jtMiter, cety.etOpenSquare); -// coff.Execute(ctre, distance * fact); - -// return fromClipperTree(ctre, z, null, null, 0); -// } - /** * @param {Polygon[]} polys * @param {number} distance offset @@ -565,9 +562,9 @@ function offset(polys, dist, opts = {}) { depth = numOrDefault(opts.depth, 0), clean = opts.clean !== false, simple = opts.simple !== false, - fill = numOrDefault(opts.fill, clib.PolyFillType.pftNonZero), - join = numOrDefault(opts.join, clib.JoinType.jtMiter), - type = numOrDefault(opts.type, clib.EndType.etClosedPolygon), + fill = numOrDefault(opts.fill, FillNonZero), + join = numOrDefault(opts.join, JoinType.jtMiter), + type = numOrDefault(opts.type, EndType.etClosedPolygon), // if dist is array with values, shift out next offset offs = Array.isArray(dist) ? (dist.length > 1 ? dist.shift() : dist[0]) : dist, mina = numOrDefault(opts.minArea, 0.1), @@ -583,21 +580,21 @@ function offset(polys, dist, opts = {}) { return offset(polys, dist, opts); } } else { - let coff = new clib.ClipperOffset(opts.miter, opts.arc), - ctre = new clib.PolyTree(); + let coff = new ClipperOffset(opts.miter, opts.arc), + tree = new PolyTree(); // setup offset for (let poly of polys) { // convert to clipper format poly = poly.toClipper(); - if (clean) poly = clib.Clipper.CleanPolygons(poly, config.clipperClean); - if (simple) poly = clib.Clipper.SimplifyPolygons(poly, fill); + if (clean) poly = CleanPolygons(poly, config.clipperClean); + if (simple) poly = SimplifyPolygons(poly, fill); coff.AddPaths(poly, join, type); } // perform offset - coff.Execute(ctre, offs * config.clipper); + coff.Execute(tree, offs * config.clipper); // convert back from clipper output format - polys = fromClipperTree(ctre, zed, null, null, mina); + polys = fromClipperTree(tree, zed, null, null, mina); } @@ -748,8 +745,8 @@ function fillArea(polys, angle, spacing, output, minLen, maxLen) { step = SQRT(SQR(stepX) + SQR(stepY)), steps = dist / step, start = angle < 0 ? { x:bounds.minx, y:bounds.miny, z:zpos } : { x:bounds.maxx, y:bounds.miny, z:zpos }, - clip = new clib.Clipper(), - ctre = new clib.PolyTree(), + clip = new Clipper(), + tree = new PolyTree(), minlen = base.config.clipper * (minLen || 0), maxlen = base.config.clipper * (maxLen || 0), lines = []; @@ -771,13 +768,13 @@ function fillArea(polys, angle, spacing, output, minLen, maxLen) { start.y += stepY; } - clip.AddPaths(lines, ptyp.ptSubject, false); - clip.AddPaths(toClipper(polys), ptyp.ptClip, true); + clip.AddPaths(lines, PathSubject, false); + clip.AddPaths(toClipper(polys), PathClip, true); lines = []; - if (clip.Execute(ctyp.ctIntersection, ctre, cfil.pftNonZero, cfil.pftEvenOdd)) { - for (let poly of ctre.m_AllPolys) { + if (clip.Execute(ClipIntersect, tree, FillNonZero, FillEvenOdd)) { + for (let poly of tree.m_AllPolys) { if (minlen || maxlen) { let plen = clib.JS.PerimeterOfPath(poly.m_polygon, false, 1); if (minlen && plen < minlen) continue;