From 9085b883805b37c0d8793eb8774947a5df8374bb Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Wed, 26 Jan 2022 17:28:23 -0500 Subject: [PATCH] add polygon.simplify(), xray for sla --- notes.md | 4 ++ src/geo/polygon.js | 114 +++++++++++++++++++++---------------- src/kiri-mode/sla/slice.js | 11 ++-- src/kiri/init.js | 2 +- src/kiri/main.js | 7 ++- src/kiri/slicer.js | 2 +- 6 files changed, 82 insertions(+), 58 deletions(-) diff --git a/notes.md b/notes.md index abdd93af..e442d799 100644 --- a/notes.md +++ b/notes.md @@ -108,3 +108,7 @@ # Laser * `F` add PLT / HP-GL output format (https://en.wikipedia.org/wiki/HP-GL) + +# Other + +* investigate libtess https://www.npmjs.com/package/libtess b/c earcut sometimes broken diff --git a/src/geo/polygon.js b/src/geo/polygon.js index e9185511..90f1a2db 100644 --- a/src/geo/polygon.js +++ b/src/geo/polygon.js @@ -1411,18 +1411,6 @@ return this.clean(true, undefined, Math.min(CONF.clipper / 10, CONF.clipperClean * 5)); }; - // does not work with nested polys - PRO.simplify = function(parent) { - if (this.length === 0 || this.open) return [ this ]; - let clib = self.ClipperLib, - clip = clib.Clipper, - ctyp = clib.ClipType, - p2cl = this.toClipper(), - clean = clip.SimplifyPolygon(p2cl[0], ctyp.pftPositive), - z = this.getZ(); - return clean.map(array => fromClipperPath(array, z)); - }; - /** * simplify and merge collinear. only works for single * non-nested polygons. used primarily in slicer/connectLines. @@ -1748,14 +1736,40 @@ return (a1 > a2) ? a2 / a1 : a1 / a2; }; + // does not work with nested polys + PRO.simplify = function(opt = {}) { + let z = this.getZ(); + + // use expand / deflate technique instead + if (opt.pump) { + let p2 = POLY().offset([ this ], opt.pump, { z }); + if (p2) { + p2 = POLY().offset(p2, -opt.pump, { z }); + return p2; + } + return null; + } + + let clib = self.ClipperLib, + cfil = clib.PolyFillType, + clip = this.toClipper(), + res = clib.Clipper.SimplifyPolygons(clip, cfil.pftNonZero); + + if (!(res && res.length)) { + return null; + } + + return res.map(array => { + let poly = newPolygon(); + for (let pt of array) { + poly.push(BASE.pointFromClipper(pt, z)); + } + return poly; + }); + }; + PRO.unionMatch = function(polys) { return polys.filter(poly => poly.isEquivalent(this)).length; - // for (let poly of polys) { - // if (this.isEquivalent(poly)) { - // return true; - // } - // } - // return false; }; /** @@ -1767,41 +1781,45 @@ PRO.union = function(poly, min, all) { if (!this.overlaps(poly)) return null; - let fillang = this.fillang && this.area() > poly.area() ? this.fillang : poly.fillang, - clib = self.ClipperLib, - ctyp = clib.ClipType, - ptyp = clib.PolyType, - cfil = clib.PolyFillType, - clip = new clib.Clipper(), - ctre = new clib.PolyTree(), - sp1 = this.toClipper(), - sp2 = poly.toClipper(), - minarea = min >= 0 ? min : 0.1; + PRO.union = function(poly, min, all) { + if (!this.overlaps(poly)) return null; - clip.AddPaths(sp1, ptyp.ptSubject, true); - clip.AddPaths(sp2, ptyp.ptClip, true); + let fillang = this.fillang && this.area() > poly.area() ? this.fillang : poly.fillang, + clib = self.ClipperLib, + ctyp = clib.ClipType, + ptyp = clib.PolyType, + cfil = clib.PolyFillType, + clip = new clib.Clipper(), + ctre = new clib.PolyTree(), + sp1 = this.toClipper(), + sp2 = poly.toClipper(), + minarea = min >= 0 ? min : 0.1; - if (clip.Execute(ctyp.ctUnion, ctre, cfil.pftEvenOdd, cfil.pftEvenOdd)) { - let union = POLY().fromClipperTreeUnion(ctre, poly.getZ(), minarea); - if (all) { - if (union.length === 2) { - return null; - // if (this.unionMatch(union) || poly.unionMatch(union)) { - // return null; - // } + clip.AddPaths(sp1, ptyp.ptSubject, true); + clip.AddPaths(sp2, ptyp.ptClip, true); + + if (clip.Execute(ctyp.ctUnion, ctre, cfil.pftEvenOdd, cfil.pftEvenOdd)) { + let union = POLY().fromClipperTreeUnion(ctre, poly.getZ(), minarea); + if (all) { + if (union.length === 2) { + return null; + // if (this.unionMatch(union) || poly.unionMatch(union)) { + // return null; + // } + } + return union; + } + if (union.length === 1) { + union = union[0]; + union.fillang = fillang; + return union; + } else { + console.trace({check_union_call_path: union, this: this, poly}); } - return union; } - if (union.length === 1) { - union = union[0]; - union.fillang = fillang; - return union; - } else { - console.trace({check_union_call_path: union, this: this, poly}); - } - } - return null; + return null; + }; }; /** ****************************************************************** diff --git a/src/kiri-mode/sla/slice.js b/src/kiri-mode/sla/slice.js index 12392122..f71bc7a2 100644 --- a/src/kiri-mode/sla/slice.js +++ b/src/kiri-mode/sla/slice.js @@ -82,7 +82,7 @@ let last = slices[slices.length-1]; // remove empty slices slices = widget.slices = slices.filter(slice => slice.tops.length); - if (!process.slaOpenTop) { + if (!process.slaOpenTop && !process.xray) { // re-add last empty slice for open top slices.push(last); } @@ -212,7 +212,11 @@ SLICER.sliceWidget(widget, { height: height, add: !process.slaOpenTop, - concurrent: isConcurrent + union: controller.healMesh, + concurrent: isConcurrent, + indices: process.indices || process.xray, + debug: process.xray, + xray: process.xray }, function(slices) { onSliceDone(slices).then(ondone); }, function(update) { @@ -225,7 +229,6 @@ const render = slice.output(); if (slice.unioned) { - // console.log('solid', slice.index) slice.unioned.forEach(poly => { poly = poly.clone(true);//.move(widget.track.pos); render @@ -233,7 +236,6 @@ .addAreas([poly], { outline: true }); }); } else if (slice.tops) { - // console.log('top', slice.index) slice.tops.forEach(top => { let poly = top.poly;//.clone(true).move(widget.track.pos); render @@ -243,7 +245,6 @@ } if (slice.supports) { - // console.log('support', slice.index) slice.supports.forEach(poly => { render .setLayer("support", { line: 0x010101, face: 0xfcba03, opacity: 0.2 }) diff --git a/src/kiri/init.js b/src/kiri/init.js index 9877d290..fdb474b9 100644 --- a/src/kiri/init.js +++ b/src/kiri/init.js @@ -2641,7 +2641,7 @@ $('rot_z_gt').onclick = () => { API.selection.rotate(0,0,-d) }; // rendering options $('render-hide').onclick = () => { API.view.wireframe(false, 0, 0); }; - $('render-ghost').onclick = () => { API.view.wireframe(false, 0, API.view.isArrange() ? 0.5 : 0.25); }; + $('render-ghost').onclick = () => { API.view.wireframe(false, 0, API.view.isArrange() ? 0.4 : 0.25); }; $('render-wire').onclick = () => { API.view.wireframe(true, 0, API.space.isDark() ? 0.25 : 0.5); }; $('render-solid').onclick = () => { API.view.wireframe(false, 0, 1); }; // mesh buttons diff --git a/src/kiri/main.js b/src/kiri/main.js index 3fccf97b..5daceedd 100644 --- a/src/kiri/main.js +++ b/src/kiri/main.js @@ -250,7 +250,7 @@ const devel = { xray: (layers) => { let proc = API.conf.get().process; - let size = proc.sliceHeight || 1; + let size = proc.sliceHeight || proc.slaSlice || 1; layers = Array.isArray(layers) ? layers : [ layers ]; proc.xray = layers.map(l => l * size + size / 2); API.function.slice(); @@ -1269,7 +1269,7 @@ if (scale === 1) { updateStackLabelState(); } - if (control.lineType === 'line') { + if (!isBelt && control.lineType === 'line' && !process.xray) { $('render-ghost').onclick(); } }); @@ -1404,7 +1404,8 @@ } updateStackLabelState(); - if (settings.controller.lineType === 'line') { + let { controller, process } = settings; + if (!isBelt && controller.lineType === 'line' && !process.xray) { $('render-ghost').onclick(); } diff --git a/src/kiri/slicer.js b/src/kiri/slicer.js index f042c910..3b583441 100644 --- a/src/kiri/slicer.js +++ b/src/kiri/slicer.js @@ -675,7 +675,7 @@ let closed = path[0].group.indexOf(path.peek()) >= 0; if (closed && path.length > 2) { if (debug) console.log({ closed: path.length, path }); - emit(BASE.newPolygon().addPoints(path), debug); + emit(BASE.newPolygon().addPoints(path)); } else if (path.length > 1) { let gap = path[0].distTo2D(path.peek()).round(4); if (debug) console.log({ open: path.length, gap, path });