diff --git a/js/kiri-driver-fdm.js b/js/kiri-driver-fdm.js index de40955d..fc7cb13c 100644 --- a/js/kiri-driver-fdm.js +++ b/js/kiri-driver-fdm.js @@ -41,16 +41,15 @@ var gs_kiri_fdm = exports; */ FDM.slice = function(settings, widget, onupdate, ondone) { var spro = settings.process, - spri = settings.device, - sout = settings.process, + sdev = settings.device, update_start = time(), minSolid = spro.sliceSolidMinArea, solidLayers = spro.sliceSolidLayers, doSolidLayers = solidLayers && !spro.sliceVase, - firstOffset = spri.nozzleSize / 2, - shellOffset = spri.nozzleSize * spro.sliceShellSpacing, + firstOffset = sdev.nozzleSize / 2, + shellOffset = sdev.nozzleSize * spro.sliceShellSpacing, fillOffset = shellOffset * settings.synth.fillOffsetMult, - fillSpacing = spri.nozzleSize * spro.sliceFillSpacing, + fillSpacing = sdev.nozzleSize * spro.sliceFillSpacing, sliceFillAngle = spro.sliceFillAngle, view = widget.mesh && widget.mesh.newGroup ? widget.mesh.newGroup() : null; @@ -66,8 +65,9 @@ var gs_kiri_fdm = exports; SLICER.sliceWidget(widget, { height: spro.sliceHeight, - view:view, - firstHeight: sout.firstSliceHeight + minHeight: spro.sliceMinHeight, + firstHeight: spro.firstSliceHeight, + view: view }, onSliceDone, onSliceUpdate); 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); }, "support"); forSlices(0.7, 0.8, function(slice) { - slice.doSupportFill(spri.nozzleSize, spro.sliceSupportDensity, supportMinArea); + slice.doSupportFill(sdev.nozzleSize, spro.sliceSupportDensity, supportMinArea); }, "support"); } diff --git a/js/kiri-slicer.js b/js/kiri-slicer.js index 30100c1a..a9a7d9a8 100644 --- a/js/kiri-slicer.js +++ b/js/kiri-slicer.js @@ -102,12 +102,15 @@ var gs_kiri_slicer = exports; var zMin = options.zmin || Math.floor(bounds.min.z), zMax = options.zmax || Math.ceil(bounds.max.z), zInc = options.height, + zIncMin = options.minHeight, + zIncFirst = options.firstHeight || zInc, zOff = true ? zInc / 2 : 0, + zHeights = [], // heights for zIndexes in adaptive mode zIndexes = [], // auto-detected z slicing offsets (laser/cam) + zOrdered = [], // ordered list of Z vertices zList = {}, // list of z indices for auto slicing (laser) zFlat = {}, // area of z offset flat areas (cam) zScale, // bucket span in z units - zPos, timeStart = time(), slices = [], zSum = 0.0, @@ -129,7 +132,7 @@ var gs_kiri_slicer = exports; p3 = points[i++]; 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 - if (zInc === 0) { + if (zInc === 0 || zIncMin) { countZ(p1.z); countZ(p2.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) { // find unique z-index offsets for slicing - var key, zl = []; - 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++) { + var zl = zOrdered + for (i = 0; i < zl.length - 1; i++) { zIndexes.push((zl[i] + zl[i+1]) / 2); } - zIndexes.sort(function(a,b) { return a - b}); } else if (options.cam) { // re-divide slice height so that top and // bottom slices fall exactly on those faces @@ -202,6 +208,40 @@ var gs_kiri_slicer = exports; zIndexes.sort(function(a,b) { 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 { // FDM is the simplest case. Just offset and slice at // predicable offsets. @@ -216,8 +256,8 @@ var gs_kiri_slicer = exports; // create a Slice for each z offset in the zIndexes array for (var i = 0; i < zIndexes.length; i++) { - zPos = zIndexes[i]; - sliceZ(zPos); + // mark the slice height + sliceZ(zIndexes[i], zHeights[i]); // kill slicing if onupdate() returns 42 if (onupdate(i / zIndexes.length) === 42) { return ondone(null); @@ -319,8 +359,9 @@ var gs_kiri_slicer = exports; * add to slices array * * @param {number} z + * @param {number} [height] optional real height (fdm) */ - function sliceZ(z) { + function sliceZ(z, height) { z = UTIL.round(z,5); // 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) if (lines.length == 0 && !(options.swapX || options.swapY)) return; + slice.height = height || z; slice.index = slices.length; slice.lines = removeDuplicateLines(lines); diff --git a/js/kiri.js b/js/kiri.js index f332c493..1244e5a4 100644 --- a/js/kiri.js +++ b/js/kiri.js @@ -97,6 +97,7 @@ self.kiri.license = exports.LICENSE; outputShortDistance: 1, outputShortFactor: 1, outputFinishFactor: 1, + sliceMinHeight: 1, outputCooling: 1, // detectThinWalls: 1, antiBacklash: 1, @@ -308,6 +309,7 @@ self.kiri.license = exports.LICENSE; outputShortDistance: 0.0, outputShortFactor: 0.2, outputFinishFactor: 0, + sliceMinHeight: 0, detectThinWalls: false, antiBacklash: 2, 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}), 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}), - 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}), + 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}) gcodeVars: UC.newGroup("gcode", null, {modes:FDM}), diff --git a/js/license.js b/js/license.js index 8493363f..23867065 100644 --- a/js/license.js +++ b/js/license.js @@ -1,7 +1,7 @@ var exports = { COPYRIGHT:"Copyright (C) 2014-2017 Stewart Allen - All Rights Reserved", 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 = {}; module.exports = exports; diff --git a/notes.md b/notes.md index 37643382..6ae9c1aa 100644 --- a/notes.md +++ b/notes.md @@ -59,8 +59,6 @@ # FDM todo -* adaptive layer heights -* preview doesn't show proper z offsets * trim support offset from layer below * feather sharp tips by reducing extrusion in area of overlap * add option to reduce poly speed to match shortest/slowest segment