diff --git a/js/geo-polygon.js b/js/geo-polygon.js index f26d3e1e..c26c08ec 100644 --- a/js/geo-polygon.js +++ b/js/geo-polygon.js @@ -162,7 +162,7 @@ var gs_base_polygon = exports; length = points.length; poly.bounds = new Bounds(); for (var i=0; i { + px = widget.polish.x = polish_done + .filter(s => s.groups.length) + .map(s => s.groups); + }), (polish_update) => { + // console.log({polish_update}); + }); + // compute y polishing slices + SLICER.sliceWidget(widget, { + height: sdev.nozzleSize, + swapX: false, + swapY: true, + simple: true + }, (polish_done => { + py = widget.polish.y = polish_done + .filter(s => s.groups.length) + .map(s => s.groups); + }), (polish_update) => { + // console.log({polish_update}); + }); + // apply polishing finishes to layers + let pa = []; + px.forEach(p => pa.appendAll(p)); + py.forEach(p => pa.appendAll(p)); + forSlices(1.0, 1.0, slice => { + if (slice.index >= 2) { + let zb = slice.down.down.z; + let zt = slice.z; + let lines = []; + pa.forEach(p => { + p.forEachSegment((p1, p2) => { + // if (Math.abs(p1.z - p2.z) < 0.01) { + // return; + // } + // return when both below + if (p1.z < zb && p2.z < zb) { + return; + } + // return when both above + if (p1.z > zt && p2.z > zt) { + return; + } + // return when vertical + if (p1.x === p2.x && p1.y === p2.y) { + return; + } + // order points lowest to highest + if (p1.z > p2.z) { + let t = p2; + p2 = p1; + p1 = t; + } + let trimlo = false; + let trimhi = false; + if (p1.z < zb) { + trimlo = true; + } + if (p2.z > zt) { + trimhi = true; + } + let xaxis = p1.x === p2.x; + if (xaxis) { + p1 = BASE.newPoint(p1.y,p1.z,p1.x); + p2 = BASE.newPoint(p2.y,p2.z,p2.x); + } else { + p1 = BASE.newPoint(p1.x,p1.z,p1.y); + p2 = BASE.newPoint(p2.x,p2.z,p2.y); + } + let slope = BASE.newSlope(p1, p2); + let angle = Math.abs(slope.angle); + if (angle < 160 && angle > 20) { + return; + } + let len = p1.distTo2D(p2); + let np1 = p1; + if (trimlo) { + let zunder = zb - p1.y; + let zover = p2.y - zb; + let zdelt = p2.y - p1.y; + let pct = zunder / zdelt; + np1 = p1.follow(slope, len * pct); + } + if (trimhi) { + let zunder = zt - p1.y; + let zover = p2.y - zt; + let zdelt = p2.y - p1.y; + let pct = zover / zdelt; + p2 = p2.follow(slope.invert(), len * pct); + } + p1 = np1; + if (xaxis) { + p1 = BASE.newPoint(p1.z,p1.x,p1.y); + p2 = BASE.newPoint(p2.z,p2.x,p2.y); + } else { + p1 = BASE.newPoint(p1.x,p1.z,p1.y); + p2 = BASE.newPoint(p2.x,p2.z,p2.y); + } + lines.push(p1); + lines.push(p2); + }); + }); + if (lines.length && slice.tops.length) { + slice.tops[0].polish = lines; + } + } + }); + } + // report slicing complete ondone(); } diff --git a/js/kiri-slice.js b/js/kiri-slice.js index 45b8135a..9de9402d 100644 --- a/js/kiri-slice.js +++ b/js/kiri-slice.js @@ -619,6 +619,7 @@ var gs_kiri_slice = exports; this.tops.forEach(function(top) { if (top.fill_lines) layer.lines(top.fill_lines, fill_color); + if (top.polish) layer.lines(top.polish, 0x880000); }); layer.render(); diff --git a/js/kiri-slicer.js b/js/kiri-slicer.js index 971ec0f6..5f97a3f0 100644 --- a/js/kiri-slicer.js +++ b/js/kiri-slicer.js @@ -49,6 +49,7 @@ var gs_kiri_slicer = exports; */ function slice(points, bounds, options, ondone, onupdate) { var topoMode = options.topo, + simpleMode = options.simple, ox = 0, oy = 0; @@ -465,7 +466,7 @@ var gs_kiri_slicer = exports; slice.lines = removeDuplicateLines(lines); // for topo slices, we just need the raw lines - if (!topoMode) { + if (!topoMode && !simpleMode) { slice.groups = connectLines(slice.lines, slices.length); POLY.nest(slice.groups).forEach(function(top) { slice.addTop(top) }); } @@ -492,13 +493,20 @@ var gs_kiri_slicer = exports; line.p1.move(move); line.p2.move(move); } - } else { - slice.tops.forEach(function(top) { - top.poly.swap(options.swapX, options.swapY); - top.poly.move(move); - top.poly.inner = null; + } else if (simpleMode) { + // fdm polishing mode + slice.groups = connectLines(slice.lines, slices.length); + slice.groups.forEach(poly => { + poly.swap(options.swapX, options.swapY); + poly.move(move); + poly.inner = null; }); - drape(slice, options.swapX, options.swapY); + // slice.tops.forEach(function(top) { + // top.poly.swap(options.swapX, options.swapY); + // top.poly.move(move); + // top.poly.inner = null; + // }); + // drape(slice, options.swapX, options.swapY); } } diff --git a/js/kiri-widget.js b/js/kiri-widget.js index 835a71b3..981c2570 100644 --- a/js/kiri-widget.js +++ b/js/kiri-widget.js @@ -245,17 +245,17 @@ var gs_kiri_widget = exports; }); }; - PRO.encodeSlices = function() { - var encoded = []; - if (this.slices) this.slices.forEach(function(slice) { - encoded.push(slice.encode()); - }); - return encoded; - }; + // PRO.encodeSlices = function() { + // var encoded = []; + // if (this.slices) this.slices.forEach(function(slice) { + // encoded.push(slice.encode()); + // }); + // return encoded; + // }; - PRO.decodeSlices = function(encoded) { - this.slices = KIRI.codec.decode(encoded, { mesh:this.mesh }); - }; + // PRO.decodeSlices = function(encoded) { + // this.slices = KIRI.codec.decode(encoded, { mesh:this.mesh }); + // }; /** * @@ -538,12 +538,28 @@ var gs_kiri_widget = exports; if (reply.update) { onupdate(reply.update, reply.updateStatus); } - if (reply.send_start) widget.xfer = {start: reply.send_start}; - if (reply.topo) widget.topo = reply.topo; - if (reply.stats) widget.stats = reply.stats; - if (reply.send_end) widget.stats.load_time = widget.xfer.start - reply.send_end; - if (reply.slices) { widget.clearSlices(); widget.slices = [] }; - if (reply.slice) widget.slices.push(KIRI.codec.decode(reply.slice, {mesh:widget.mesh})); + if (reply.send_start) { + widget.xfer = {start: reply.send_start}; + } + if (reply.topo) { + widget.topo = reply.topo; + } + if (reply.stats) { + widget.stats = reply.stats; + } + if (reply.send_end) { + widget.stats.load_time = widget.xfer.start - reply.send_end; + } + if (reply.slices) { + widget.clearSlices(); + widget.slices = [] + }; + if (reply.slice) { + widget.slices.push(KIRI.codec.decode(reply.slice, {mesh:widget.mesh})); + } + if (reply.polish) { + widget.polish = KIRI.codec.decode(reply.polish); + } if (reply.error) { ondone(false, reply.error); } @@ -620,6 +636,17 @@ var gs_kiri_widget = exports; if (!cam) slices.forEach(function(s) { s.renderSparseFill() }); // render supports if (!cam) slices.forEach(function(s) { s.renderSupport() }); + // render polish (sent in debug mode only) + if (this.polish && false) { + let layer = KIRI.newLayer(this.mesh.newGroup()); + this.polish.x.forEach(poly => { + layer.poly(poly, 0xff0000, false, false); + }); + this.polish.y.forEach(poly => { + layer.poly(poly, 0x0000ff, false, false); + }); + layer.render(); + } }; PRO.hideSlices = function() { diff --git a/js/kiri-worker.js b/js/kiri-worker.js index 091c632e..4be511a9 100644 --- a/js/kiri-worker.js +++ b/js/kiri-worker.js @@ -108,6 +108,9 @@ let dispatch = { slices.forEach(function(slice,index) { send.data({index: index, slice: slice.encode()}); }) + if (debug && widget.polish) { + send.data({polish: kiri.codec.encode(widget.polish)}); + } send.data({send_end: time()}); } send.done({done: true}); diff --git a/js/kiri.js b/js/kiri.js index b2503479..9a2a2190 100644 --- a/js/kiri.js +++ b/js/kiri.js @@ -103,6 +103,7 @@ self.kiri.license = exports.LICENSE; // detectThinWalls: 1, antiBacklash: 1, zHopDistance: 1, + layerPolishing: 1, outputLayerRetract: 1, gcodeNozzle: 1, gcodePauseLayers: 1, @@ -336,6 +337,7 @@ self.kiri.license = exports.LICENSE; detectThinWalls: false, antiBacklash: 1, zHopDistance: 0.2, + layerPolishing: 0, outputLayerRetract: false, gcodeNozzle: 0, gcodePauseLayers: "", @@ -1870,8 +1872,7 @@ self.kiri.license = exports.LICENSE; if (!scope.hasOwnProperty(key)) continue; if (UI.hasOwnProperty(key)) { var nval = null, - uie = UI[key], - src = uie.parentNode.getAttribute('source'); + uie = UI[key]; // skip empty UI values if (!uie || uie === '') continue; if (uie.type === 'text') { @@ -1881,6 +1882,7 @@ self.kiri.license = exports.LICENSE; } else if (uie.type === 'select-one') { if (uie.selectedIndex > 0) { nval = uie.options[uie.selectedIndex].value; + let src = uie.parentNode.getAttribute('source'); if (src === 'tools') { nval = parseInt(nval); } @@ -2888,7 +2890,8 @@ self.kiri.license = exports.LICENSE; outputShortPoly: UC.newInput("slow poly", {title:"polygons shorter than this\nwill have their print speed\nscaled down to min speed\nin millimeters", bound:UC.bound(0,200), convert:UC.toFloat, modes:FDM, expert: true}), zHopDistance: UC.newInput("z hop dist", {title: "amount to raise z\non retraction moves\nin millimeters\n0 to disable", bound:UC.bound(0,3.0), convert:UC.toFloat, modes:FDM, expert: true}), antiBacklash: UC.newInput("anti-backlash", {title: "use micro-movements to cancel\nbacklash during fills\nin millimeters", bound:UC.bound(0,3), convert:UC.toInt, modes:FDM, expert: true}), - //detectThinWalls: UC.newBoolean("thin wall fill", onBooleanClick, {title: "detect and fill thin openings\nbetween shells walls", modes:FDM, expert: true}) + // detectThinWalls: UC.newBoolean("thin wall fill", onBooleanClick, {title: "detect and fill thin openings\nbetween shells walls", modes:FDM, expert: true}) + layerPolishing: LOCAL ? UC.newInput("layer polish", {title:"polish up to specified\n# of layers at a time", bound:UC.bound(0,10), convert:UC.toFloat, modes:FDM, expert: true}) : null, outputLayerRetract: UC.newBoolean("layer retract", onBooleanClick, {title:"force filament retraction\nbetween layers", modes:FDM, expert: true}), gcodeVars: UC.newGroup("gcode", null, {modes:FDM, expert: true}),