checkpoint experimental layer polishing

This commit is contained in:
Stewart Allen 2020-03-04 15:07:06 -05:00
commit 09990a14ce
8 changed files with 193 additions and 30 deletions

View file

@ -162,7 +162,7 @@ var gs_base_polygon = exports;
length = points.length; length = points.length;
poly.bounds = new Bounds(); poly.bounds = new Bounds();
for (var i=0; i<length; i++) { for (var i=0; i<length; i++) {
p = points[i]; let p = points[i];
if (x) p.swapXZ(); if (x) p.swapXZ();
else if (y) p.swapYZ(); else if (y) p.swapYZ();
poly.bounds.update(p); poly.bounds.update(p);

View file

@ -123,7 +123,8 @@ var gs_kiri_codec = exports;
// thinner: encode(this.thinner, state), // thinner: encode(this.thinner, state),
solids: encode(this.solids, state), solids: encode(this.solids, state),
fill_lines: encodePointArray(this.fill_lines), fill_lines: encodePointArray(this.fill_lines),
fill_sparse: encode(this.fill_sparse, state) fill_sparse: encode(this.fill_sparse, state),
polish: encode(this.polish, state)
}; };
}; };
@ -134,8 +135,9 @@ var gs_kiri_codec = exports;
top.inner = decode(v.inner, state); top.inner = decode(v.inner, state);
// top.thinner = decode(v.thinner, state); // top.thinner = decode(v.thinner, state);
top.solids = decode(v.solids, state); top.solids = decode(v.solids, state);
top.fill_lines = decodePointArray(v.fill_lines,state); top.fill_lines = decodePointArray(v.fill_lines, state);
top.fill_sparse = decode(v.fill_sparse, state); top.fill_sparse = decode(v.fill_sparse, state);
top.polish = decode(v.polish, state);
return top; return top;
}); });

View file

@ -161,6 +161,125 @@ var gs_kiri_fdm = exports;
}, "infill"); }, "infill");
} }
// experimental polishing
if (spro.layerPolishing) {
console.log({polish:spro.layerPolishing})
let px, py;
widget.polish = {};
// compute x polishing slices
SLICER.sliceWidget(widget, {
height: sdev.nozzleSize,
swapX: true,
swapY: false,
simple: true
}, (polish_done => {
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 // report slicing complete
ondone(); ondone();
} }

View file

@ -619,6 +619,7 @@ var gs_kiri_slice = exports;
this.tops.forEach(function(top) { this.tops.forEach(function(top) {
if (top.fill_lines) layer.lines(top.fill_lines, fill_color); if (top.fill_lines) layer.lines(top.fill_lines, fill_color);
if (top.polish) layer.lines(top.polish, 0x880000);
}); });
layer.render(); layer.render();

View file

@ -49,6 +49,7 @@ var gs_kiri_slicer = exports;
*/ */
function slice(points, bounds, options, ondone, onupdate) { function slice(points, bounds, options, ondone, onupdate) {
var topoMode = options.topo, var topoMode = options.topo,
simpleMode = options.simple,
ox = 0, ox = 0,
oy = 0; oy = 0;
@ -465,7 +466,7 @@ var gs_kiri_slicer = exports;
slice.lines = removeDuplicateLines(lines); slice.lines = removeDuplicateLines(lines);
// for topo slices, we just need the raw lines // for topo slices, we just need the raw lines
if (!topoMode) { if (!topoMode && !simpleMode) {
slice.groups = connectLines(slice.lines, slices.length); slice.groups = connectLines(slice.lines, slices.length);
POLY.nest(slice.groups).forEach(function(top) { slice.addTop(top) }); POLY.nest(slice.groups).forEach(function(top) { slice.addTop(top) });
} }
@ -492,13 +493,20 @@ var gs_kiri_slicer = exports;
line.p1.move(move); line.p1.move(move);
line.p2.move(move); line.p2.move(move);
} }
} else { } else if (simpleMode) {
slice.tops.forEach(function(top) { // fdm polishing mode
top.poly.swap(options.swapX, options.swapY); slice.groups = connectLines(slice.lines, slices.length);
top.poly.move(move); slice.groups.forEach(poly => {
top.poly.inner = null; 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);
} }
} }

View file

@ -245,17 +245,17 @@ var gs_kiri_widget = exports;
}); });
}; };
PRO.encodeSlices = function() { // PRO.encodeSlices = function() {
var encoded = []; // var encoded = [];
if (this.slices) this.slices.forEach(function(slice) { // if (this.slices) this.slices.forEach(function(slice) {
encoded.push(slice.encode()); // encoded.push(slice.encode());
}); // });
return encoded; // return encoded;
}; // };
PRO.decodeSlices = function(encoded) { // PRO.decodeSlices = function(encoded) {
this.slices = KIRI.codec.decode(encoded, { mesh:this.mesh }); // this.slices = KIRI.codec.decode(encoded, { mesh:this.mesh });
}; // };
/** /**
* *
@ -538,12 +538,28 @@ var gs_kiri_widget = exports;
if (reply.update) { if (reply.update) {
onupdate(reply.update, reply.updateStatus); onupdate(reply.update, reply.updateStatus);
} }
if (reply.send_start) widget.xfer = {start: reply.send_start}; if (reply.send_start) {
if (reply.topo) widget.topo = reply.topo; widget.xfer = {start: reply.send_start};
if (reply.stats) widget.stats = reply.stats; }
if (reply.send_end) widget.stats.load_time = widget.xfer.start - reply.send_end; if (reply.topo) {
if (reply.slices) { widget.clearSlices(); widget.slices = [] }; widget.topo = reply.topo;
if (reply.slice) widget.slices.push(KIRI.codec.decode(reply.slice, {mesh:widget.mesh})); }
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) { if (reply.error) {
ondone(false, reply.error); ondone(false, reply.error);
} }
@ -620,6 +636,17 @@ var gs_kiri_widget = exports;
if (!cam) slices.forEach(function(s) { s.renderSparseFill() }); if (!cam) slices.forEach(function(s) { s.renderSparseFill() });
// render supports // render supports
if (!cam) slices.forEach(function(s) { s.renderSupport() }); 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() { PRO.hideSlices = function() {

View file

@ -108,6 +108,9 @@ let dispatch = {
slices.forEach(function(slice,index) { slices.forEach(function(slice,index) {
send.data({index: index, slice: slice.encode()}); 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.data({send_end: time()});
} }
send.done({done: true}); send.done({done: true});

View file

@ -103,6 +103,7 @@ self.kiri.license = exports.LICENSE;
// detectThinWalls: 1, // detectThinWalls: 1,
antiBacklash: 1, antiBacklash: 1,
zHopDistance: 1, zHopDistance: 1,
layerPolishing: 1,
outputLayerRetract: 1, outputLayerRetract: 1,
gcodeNozzle: 1, gcodeNozzle: 1,
gcodePauseLayers: 1, gcodePauseLayers: 1,
@ -336,6 +337,7 @@ self.kiri.license = exports.LICENSE;
detectThinWalls: false, detectThinWalls: false,
antiBacklash: 1, antiBacklash: 1,
zHopDistance: 0.2, zHopDistance: 0.2,
layerPolishing: 0,
outputLayerRetract: false, outputLayerRetract: false,
gcodeNozzle: 0, gcodeNozzle: 0,
gcodePauseLayers: "", gcodePauseLayers: "",
@ -1870,8 +1872,7 @@ self.kiri.license = exports.LICENSE;
if (!scope.hasOwnProperty(key)) continue; if (!scope.hasOwnProperty(key)) continue;
if (UI.hasOwnProperty(key)) { if (UI.hasOwnProperty(key)) {
var nval = null, var nval = null,
uie = UI[key], uie = UI[key];
src = uie.parentNode.getAttribute('source');
// skip empty UI values // skip empty UI values
if (!uie || uie === '') continue; if (!uie || uie === '') continue;
if (uie.type === 'text') { if (uie.type === 'text') {
@ -1881,6 +1882,7 @@ self.kiri.license = exports.LICENSE;
} else if (uie.type === 'select-one') { } else if (uie.type === 'select-one') {
if (uie.selectedIndex > 0) { if (uie.selectedIndex > 0) {
nval = uie.options[uie.selectedIndex].value; nval = uie.options[uie.selectedIndex].value;
let src = uie.parentNode.getAttribute('source');
if (src === 'tools') { if (src === 'tools') {
nval = parseInt(nval); 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}), 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}), 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}), 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}), 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}), gcodeVars: UC.newGroup("gcode", null, {modes:FDM, expert: true}),