add adaptive layer heights

This commit is contained in:
Stewart Allen 2018-03-06 20:57:26 -05:00
commit 4d49d0a7af
5 changed files with 69 additions and 26 deletions

View file

@ -41,16 +41,15 @@ var gs_kiri_fdm = exports;
*/ */
FDM.slice = function(settings, widget, onupdate, ondone) { FDM.slice = function(settings, widget, onupdate, ondone) {
var spro = settings.process, var spro = settings.process,
spri = settings.device, sdev = settings.device,
sout = settings.process,
update_start = time(), update_start = time(),
minSolid = spro.sliceSolidMinArea, minSolid = spro.sliceSolidMinArea,
solidLayers = spro.sliceSolidLayers, solidLayers = spro.sliceSolidLayers,
doSolidLayers = solidLayers && !spro.sliceVase, doSolidLayers = solidLayers && !spro.sliceVase,
firstOffset = spri.nozzleSize / 2, firstOffset = sdev.nozzleSize / 2,
shellOffset = spri.nozzleSize * spro.sliceShellSpacing, shellOffset = sdev.nozzleSize * spro.sliceShellSpacing,
fillOffset = shellOffset * settings.synth.fillOffsetMult, fillOffset = shellOffset * settings.synth.fillOffsetMult,
fillSpacing = spri.nozzleSize * spro.sliceFillSpacing, fillSpacing = sdev.nozzleSize * spro.sliceFillSpacing,
sliceFillAngle = spro.sliceFillAngle, sliceFillAngle = spro.sliceFillAngle,
view = widget.mesh && widget.mesh.newGroup ? widget.mesh.newGroup() : null; view = widget.mesh && widget.mesh.newGroup ? widget.mesh.newGroup() : null;
@ -66,8 +65,9 @@ var gs_kiri_fdm = exports;
SLICER.sliceWidget(widget, { SLICER.sliceWidget(widget, {
height: spro.sliceHeight, height: spro.sliceHeight,
view:view, minHeight: spro.sliceMinHeight,
firstHeight: sout.firstSliceHeight firstHeight: spro.firstSliceHeight,
view: view
}, onSliceDone, onSliceUpdate); }, onSliceDone, onSliceUpdate);
function onSliceUpdate(update) { function onSliceUpdate(update) {
@ -142,7 +142,7 @@ var gs_kiri_fdm = exports;
slice.doSupport(spro.sliceSupportOffset, spro.sliceSupportSpan, spro.sliceSupportExtra, supportMinArea, spro.sliceSupportSize, spro.sliceSupportOffset, spro.sliceSupportGap); slice.doSupport(spro.sliceSupportOffset, spro.sliceSupportSpan, spro.sliceSupportExtra, supportMinArea, spro.sliceSupportSize, spro.sliceSupportOffset, spro.sliceSupportGap);
}, "support"); }, "support");
forSlices(0.7, 0.8, function(slice) { forSlices(0.7, 0.8, function(slice) {
slice.doSupportFill(spri.nozzleSize, spro.sliceSupportDensity, supportMinArea); slice.doSupportFill(sdev.nozzleSize, spro.sliceSupportDensity, supportMinArea);
}, "support"); }, "support");
} }

View file

@ -102,12 +102,15 @@ var gs_kiri_slicer = exports;
var zMin = options.zmin || Math.floor(bounds.min.z), var zMin = options.zmin || Math.floor(bounds.min.z),
zMax = options.zmax || Math.ceil(bounds.max.z), zMax = options.zmax || Math.ceil(bounds.max.z),
zInc = options.height, zInc = options.height,
zIncMin = options.minHeight,
zIncFirst = options.firstHeight || zInc,
zOff = true ? zInc / 2 : 0, zOff = true ? zInc / 2 : 0,
zHeights = [], // heights for zIndexes in adaptive mode
zIndexes = [], // auto-detected z slicing offsets (laser/cam) zIndexes = [], // auto-detected z slicing offsets (laser/cam)
zOrdered = [], // ordered list of Z vertices
zList = {}, // list of z indices for auto slicing (laser) zList = {}, // list of z indices for auto slicing (laser)
zFlat = {}, // area of z offset flat areas (cam) zFlat = {}, // area of z offset flat areas (cam)
zScale, // bucket span in z units zScale, // bucket span in z units
zPos,
timeStart = time(), timeStart = time(),
slices = [], slices = [],
zSum = 0.0, zSum = 0.0,
@ -129,7 +132,7 @@ var gs_kiri_slicer = exports;
p3 = points[i++]; p3 = points[i++];
zSum += (Math.abs(p1.z - p2.z) + Math.abs(p2.z - p3.z) + Math.abs(p3.z - p1.z)); zSum += (Math.abs(p1.z - p2.z) + Math.abs(p2.z - p3.z) + Math.abs(p3.z - p1.z));
// laser auto-detect z slice points // laser auto-detect z slice points
if (zInc === 0) { if (zInc === 0 || zIncMin) {
countZ(p1.z); countZ(p1.z);
countZ(p2.z); countZ(p2.z);
countZ(p3.z); countZ(p3.z);
@ -172,19 +175,22 @@ var gs_kiri_slicer = exports;
} }
} }
// create zIndexes array (0 = auto-detect) // we need Z ordered list for laser auto or adaptive fdm slicing
if (zInc === 0 || zIncMin) {
for (var key in zList) {
if (!zList.hasOwnProperty(key)) continue;
zOrdered.push(parseFloat(key));
}
zOrdered.sort(function(a,b) { return a - b});
}
// use Z indices in auto slice mode for laser
if (zInc === 0) { if (zInc === 0) {
// find unique z-index offsets for slicing // find unique z-index offsets for slicing
var key, zl = []; var zl = zOrdered
for (key in zList) {
if (!zList.hasOwnProperty(key)) continue;
zl.push(parseFloat(key));
}
zl.sort(function(a,b) { return a - b});
for (i = 0; i < zl.length - 1; i++) { for (i = 0; i < zl.length - 1; i++) {
zIndexes.push((zl[i] + zl[i+1]) / 2); zIndexes.push((zl[i] + zl[i+1]) / 2);
} }
zIndexes.sort(function(a,b) { return a - b});
} else if (options.cam) { } else if (options.cam) {
// re-divide slice height so that top and // re-divide slice height so that top and
// bottom slices fall exactly on those faces // bottom slices fall exactly on those faces
@ -202,6 +208,40 @@ var gs_kiri_slicer = exports;
zIndexes.sort(function(a,b) { zIndexes.sort(function(a,b) {
return b-a; return b-a;
}); });
} else if (zIncMin) {
var zPos = zMin + zIncFirst,
zOI = 0,
zDelta,
zDivMin,
zDivMax,
zStep,
nextZ;
// first slice is fixed
zHeights.push(zPos);
zIndexes.push(zIncFirst / 2);
while (zPos < zMax && zOI < zOrdered.length) {
nextZ = zOrdered[zOI++];
if (zPos >= nextZ) continue;
zDelta = nextZ - zPos;
if (zDelta < zIncMin) continue;
zDivMin = Math.floor(zDelta / zIncMin);
zDivMax = Math.floor(zDelta / zInc);
if (zDivMax) {
zStep = zDelta / (zDivMax + 1);
} else {
zStep = zDelta;
}
while (zPos < nextZ) {
zHeights.push(zPos + zStep);
zIndexes.push(zPos + zStep / 2);
zPos += zStep;
}
}
} else { } else {
// FDM is the simplest case. Just offset and slice at // FDM is the simplest case. Just offset and slice at
// predicable offsets. // predicable offsets.
@ -216,8 +256,8 @@ var gs_kiri_slicer = exports;
// create a Slice for each z offset in the zIndexes array // create a Slice for each z offset in the zIndexes array
for (var i = 0; i < zIndexes.length; i++) { for (var i = 0; i < zIndexes.length; i++) {
zPos = zIndexes[i]; // mark the slice height
sliceZ(zPos); sliceZ(zIndexes[i], zHeights[i]);
// kill slicing if onupdate() returns 42 // kill slicing if onupdate() returns 42
if (onupdate(i / zIndexes.length) === 42) { if (onupdate(i / zIndexes.length) === 42) {
return ondone(null); return ondone(null);
@ -319,8 +359,9 @@ var gs_kiri_slicer = exports;
* add to slices array * add to slices array
* *
* @param {number} z * @param {number} z
* @param {number} [height] optional real height (fdm)
*/ */
function sliceZ(z) { function sliceZ(z, height) {
z = UTIL.round(z,5); z = UTIL.round(z,5);
// avoid slicing directly on flat faces as it greatly increases // avoid slicing directly on flat faces as it greatly increases
@ -378,6 +419,7 @@ var gs_kiri_slicer = exports;
// allow empty slices in CAM swap mode (for topos w/ gaps) // allow empty slices in CAM swap mode (for topos w/ gaps)
if (lines.length == 0 && !(options.swapX || options.swapY)) return; if (lines.length == 0 && !(options.swapX || options.swapY)) return;
slice.height = height || z;
slice.index = slices.length; slice.index = slices.length;
slice.lines = removeDuplicateLines(lines); slice.lines = removeDuplicateLines(lines);

View file

@ -97,6 +97,7 @@ self.kiri.license = exports.LICENSE;
outputShortDistance: 1, outputShortDistance: 1,
outputShortFactor: 1, outputShortFactor: 1,
outputFinishFactor: 1, outputFinishFactor: 1,
sliceMinHeight: 1,
outputCooling: 1, outputCooling: 1,
// detectThinWalls: 1, // detectThinWalls: 1,
antiBacklash: 1, antiBacklash: 1,
@ -308,6 +309,7 @@ self.kiri.license = exports.LICENSE;
outputShortDistance: 0.0, outputShortDistance: 0.0,
outputShortFactor: 0.2, outputShortFactor: 0.2,
outputFinishFactor: 0, outputFinishFactor: 0,
sliceMinHeight: 0,
detectThinWalls: false, detectThinWalls: false,
antiBacklash: 2, antiBacklash: 2,
zHopDistance: 0, zHopDistance: 0,
@ -2511,8 +2513,9 @@ self.kiri.license = exports.LICENSE;
outputShortDistance: UC.newInput("short segment", {title:"segment length cutoff\nfor short segments\nin millimeters", bound:UC.bound(0,200), convert:UC.toFloat, modes:FDM}), outputShortDistance: UC.newInput("short segment", {title:"segment length cutoff\nfor short segments\nin millimeters", bound:UC.bound(0,200), convert:UC.toFloat, modes:FDM}),
outputShortFactor: UC.newInput("short factor", {title:"max speed reduction factor\nfor short segments\nas % of print speed", bound:UC.bound(0.05,1), convert:UC.toFloat, modes:FDM}), outputShortFactor: UC.newInput("short factor", {title:"max speed reduction factor\nfor short segments\nas % of print speed", bound:UC.bound(0.05,1), convert:UC.toFloat, modes:FDM}),
outputFinishFactor: UC.newInput("finish factor", {title:"% of nozzle diameter to\nshorten finish path by\nvalues of 0-1", bound:UC.bound(0.0,1), convert:UC.toFloat, modes:FDM}), outputFinishFactor: UC.newInput("finish factor", {title:"% of nozzle diameter to\nshorten finish path by\nvalues of 0-1", bound:UC.bound(0.0,1), convert:UC.toFloat, modes:FDM}),
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}), sliceMinHeight: UC.newInput("min layer", {title: "enables adaptive slicing with\nthis as the min layer height\nin millimeters\n0 to disable", bound:UC.bound(0,3.0), convert:UC.toFloat, modes:FDM}),
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}), 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}),
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}),
//detectThinWalls: UC.newBoolean("thin wall fill", onBooleanClick, {title: "detect and fill thin openings\nbetween shells walls", modes:FDM}) //detectThinWalls: UC.newBoolean("thin wall fill", onBooleanClick, {title: "detect and fill thin openings\nbetween shells walls", modes:FDM})
gcodeVars: UC.newGroup("gcode", null, {modes:FDM}), gcodeVars: UC.newGroup("gcode", null, {modes:FDM}),

View file

@ -1,7 +1,7 @@
var exports = { var exports = {
COPYRIGHT:"Copyright (C) 2014-2017 Stewart Allen <stewart@neuron.com> - All Rights Reserved", COPYRIGHT:"Copyright (C) 2014-2017 Stewart Allen <stewart@neuron.com> - All Rights Reserved",
LICENSE:"Unauthorized copying, modification and re-distribution are strictly prohibited without prior written consent.", LICENSE:"Unauthorized copying, modification and re-distribution are strictly prohibited without prior written consent.",
VERSION:"1.1.7" VERSION:"1.1.8"
}; };
if (!module) var module = {}; if (!module) var module = {};
module.exports = exports; module.exports = exports;

View file

@ -59,8 +59,6 @@
# FDM todo # FDM todo
* adaptive layer heights
* preview doesn't show proper z offsets
* trim support offset from layer below * trim support offset from layer below
* feather sharp tips by reducing extrusion in area of overlap * feather sharp tips by reducing extrusion in area of overlap
* add option to reduce poly speed to match shortest/slowest segment * add option to reduce poly speed to match shortest/slowest segment