From e409bec63a0f5e84df91825c47c148996cc9e7c9 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Tue, 1 Mar 2022 15:58:55 -0500 Subject: [PATCH] add discrete control of bridge, flat, and infill print speeds --- notes.md | 2 -- release.md | 2 ++ src/kiri-mode/fdm/client.js | 3 +++ src/kiri-mode/fdm/prepare.js | 4 ++++ src/kiri-mode/fdm/slice.js | 35 ++++++++++++++++++++++++++++++----- src/kiri/conf.js | 2 ++ src/kiri/init.js | 5 +++-- web/kiri/lang/en.js | 10 +++++----- 8 files changed, 49 insertions(+), 14 deletions(-) diff --git a/notes.md b/notes.md index 15f6982a..88e53206 100644 --- a/notes.md +++ b/notes.md @@ -39,10 +39,8 @@ * `F` first layer segment large flat areas for better fill reliability * `F` option to support interior bridges when 0% infill * `F` calculate filament use per extruder per print -* `F` apply finish speed to exposed top and underside flat areas * `F` expand internal supporting flats / solids before projection -* `P` expand projected flats (parameterize?) * `P` enable purge blocks when quick layers are detected * `P` refactor skirt, brim, raft as synth widget instead of in path routing * `P` extruder + filament max flow rate cap in planner diff --git a/release.md b/release.md index b9d238f0..a71e0094 100644 --- a/release.md +++ b/release.md @@ -22,6 +22,8 @@ * `C` trigger solid layer when transitions lead to 50% projected areas * `C` limit non-manifold solution search depth * `C` refactor slicers to use single improved slice core (cnc deferred) +* `C` add parameterized solid projection expansion (infill -> solid expand) +* `C` add parameterized control of bridge/flat and infill print speeds * `P` template vars: nozzles used and layers until next use (IDEX) * `-` improved vertex replacement and widget update matrix tracking diff --git a/src/kiri-mode/fdm/client.js b/src/kiri-mode/fdm/client.js index 00806f40..4fbb236d 100644 --- a/src/kiri-mode/fdm/client.js +++ b/src/kiri-mode/fdm/client.js @@ -39,6 +39,9 @@ FDM.init = function(kiri, api) { "sliceFillType": LANG.fi_type, "sliceFillWidth": LANG.fi_wdth_s, "sliceFillSparse": LANG.fi_pcnt_s, + "sliceFillRate": LANG.ou_feed_s, + "sliceFillGrow": LANG.fi_grow_s, + "sliceSolidRate": LANG.ou_fini_s, "sliceSolidMinArea": LANG.ad_msol_s, "firstLayerRate": LANG.fl_rate_s, "firstLayerPrintMult": LANG.fl_mult_s, diff --git a/src/kiri-mode/fdm/prepare.js b/src/kiri-mode/fdm/prepare.js index e7166b6a..ca9372cf 100644 --- a/src/kiri-mode/fdm/prepare.js +++ b/src/kiri-mode/fdm/prepare.js @@ -812,6 +812,10 @@ function slicePrintPath(print, slice, startPoint, offset, output, opt = {}) { z = slice.z, lastPoly; + if (slice.finishSolids) { + fillSpeed = process.sliceSolidRate || finishSpeed; + } + // apply first layer extrusion multipliers if (firstLayer) { fillMult *= firstPrintMult; diff --git a/src/kiri-mode/fdm/slice.js b/src/kiri-mode/fdm/slice.js index 6c1ec009..1c936746 100644 --- a/src/kiri-mode/fdm/slice.js +++ b/src/kiri-mode/fdm/slice.js @@ -103,7 +103,6 @@ FDM.slice = function(settings, widget, onupdate, ondone) { isDanger = controller.danger, useAssembly = controller.assembly, isConcurrent = controller.threaded && kiri.minions.concurrent, - solidMinArea = process.sliceSolidMinArea, solidLayers = process.sliceSolidLayers || 0, vaseMode = process.sliceFillType === 'vase' && !isSynth, metadata = widget.anno, @@ -564,7 +563,10 @@ FDM.slice = function(settings, widget, onupdate, ondone) { if (solidLayers && !vaseMode && !isSynth) { profileStart("delta"); forSlices(0.2, 0.34, slice => { - if (slice.index > 0) doDiff(slice, solidMinArea); + let params = slice.params || process; + let solidMinArea = params.sliceSolidMinArea; + let sliceFillGrow = params.sliceFillGrow; + doDiff(slice, { min: solidMinArea, grow: sliceFillGrow }); }, "layer deltas"); profileEnd(); profileStart("delta-project"); @@ -581,9 +583,12 @@ FDM.slice = function(settings, widget, onupdate, ondone) { let solidWidth = params.sliceFillWidth || 1; let spaceMult = first ? params.firstLayerLineMult || 1 : 1; let fillSpace = fillSpacing * spaceMult * solidWidth; + let solidMinArea = params.sliceSolidMinArea; doSolidsFill(slice, fillSpace, sliceFillAngle, solidMinArea, promises); sliceFillAngle += 90.0; }, "fill solids"); + // very last layer (top) is set to finish solid rate + slices.last().finishSolids = true if (promises) { await tracker(promises, (i, t) => { trackupdate(i / t, 0.4, 0.5); @@ -1057,8 +1062,8 @@ function doSparseLayerFill(slice, options = {}) { * Used to calculate bridges, flats and then solid projections. * 'expand' is used for top offsets in SLA mode */ -function doDiff(slice, minArea, options = {}) { - const { sla, fakedown } = options; +function doDiff(slice, options = {}) { + const { sla, fakedown, grow, min } = options; if (slice.index === 0 && !fakedown) { return; } @@ -1076,9 +1081,25 @@ function doDiff(slice, minArea, options = {}) { return; } - POLY.subtract(topInner, downInner, bridges, flats, slice.z, minArea, { + let newBridges = []; + let newFlats = []; + + POLY.subtract(topInner, downInner, newBridges, newFlats, slice.z, min, { wasm: true }); + + newBridges = newBridges.filter(p => p.areaDeep() >= min); + newFlats = newFlats.filter(p => p.areaDeep() >= min); + + if (grow > 0 && newBridges.length) { + newBridges = POLY.offset(newBridges, grow); + } + if (grow > 0 && newFlats.length) { + newFlats = POLY.offset(newFlats, grow); + } + + bridges.appendAll(newBridges); + flats.appendAll(newFlats); }; /** @@ -1099,6 +1120,8 @@ function addSolidFills(slice, polys) { */ function projectFlats(slice, count) { if (!slice.down || !slice.flats) return; + // these flats are marked for finishing print speed + if (slice.flats.length) slice.finishSolids = true; projectSolid(slice, slice.flats, count, false, true); }; @@ -1107,6 +1130,8 @@ function projectFlats(slice, count) { */ function projectBridges(slice, count) { if (!slice.up || !slice.bridges) return; + // these flats are marked for finishing print speed + if (slice.bridges.length) slice.finishSolids = true; projectSolid(slice, slice.bridges, count, true, true); }; diff --git a/src/kiri/conf.js b/src/kiri/conf.js index eeda0589..34b78c80 100644 --- a/src/kiri/conf.js +++ b/src/kiri/conf.js @@ -298,12 +298,14 @@ const conf = exports({ sliceShellOrder: "in-out", sliceLayerStart: "last", sliceLineWidth: 0, + sliceFillGrow: 0, sliceFillAngle: 45, sliceFillWidth: 1, sliceFillOverlap: 0.35, sliceFillSparse: 0.25, sliceFillRepeat: 1, sliceFillRate: 0, + sliceSolidRate: 0, sliceFillType: "hex", sliceSupportDensity: 0.25, sliceSupportOffset: 1.0, diff --git a/src/kiri/init.js b/src/kiri/init.js index 6b12f37e..d773ec75 100644 --- a/src/kiri/init.js +++ b/src/kiri/init.js @@ -1812,10 +1812,11 @@ gapp.register("kiri.init", [], (root, exports) => { sliceFillRepeat: uc.newInput(LANG.fi_rept_s, {title:LANG.fi_rept_l, convert:uc.toInt, bound:uc.bound(1,10), show:fillShow, modes:FDM}), fdmSep: uc.newBlank({class:"pop-sep", modes:FDM}), sliceFillOverlap: uc.newInput(LANG.fi_over_s, {title:LANG.fi_over_l, convert:uc.toFloat, bound:uc.bound(0.0,2.0), modes:FDM}), - sliceFillRate: uc.newInput(LANG.ou_feed_s, {title:LANG.fi_rate_l, convert:uc.toInt, bound:uc.bound(0,300), modes:FDM}), + sliceFillRate: uc.newInput(LANG.ou_feed_s, {title:LANG.ou_feed_l, convert:uc.toInt, bound:uc.bound(0,500), modes:FDM}), + sliceSolidRate: uc.newInput(LANG.ou_fini_s, {title:LANG.ou_fini_l, convert:uc.toInt, bound:uc.bound(0,500), modes:FDM}), fdmSep: uc.newBlank({class:"pop-sep", modes:FDM}), + sliceFillGrow: uc.newInput(LANG.fi_grow_s, {title:LANG.fi_grow_l, convert:uc.toFloat, modes:FDM}), sliceFillAngle: uc.newInput(LANG.fi_angl_s, {title:LANG.fi_angl_l, convert:uc.toFloat, modes:FDM}), - // sliceFillWidth: uc.newInput(LANG.fi_wdth_s, {title:LANG.fi_wdth_l, convert:uc.toFloat, modes:FDM}), fdmSupport: uc.newGroup(LANG.sp_menu, null, {modes:FDM, marker:false}), sliceSupportNozzle: uc.newSelect(LANG.sp_nozl_s, {title:LANG.sp_nozl_l, modes:FDM}, "extruders"), diff --git a/web/kiri/lang/en.js b/web/kiri/lang/en.js index a272a029..a5538695 100644 --- a/web/kiri/lang/en.js +++ b/web/kiri/lang/en.js @@ -328,10 +328,10 @@ self.kiri.lang['en-us'] = { fi_pcnt_l: ["fill density values","0.0 - 1.0"], fi_rept_s: "fill repeat", fi_rept_l: ["number of times to repeat","unchanged fill layers"], - fi_angl_s: "solid start", + fi_angl_s: "solid angle", fi_angl_l: ["starting angle in degrees","90 degrees added to ","each following layer","applies only to solid layers"], - fi_wdth_s: "solid width", - fi_wdth_l: ["line width for solid fill","as a fraction of nozzle width","values < 1 are more dense","good for surface finishes","0.0 - 1.0"], + fi_grow_s: "solid expand", + fi_grow_l: ["expand projected solids","can help with solid areas","over sparse infill areas","units in millimeters"], fi_over_s: "shell overlap", fi_over_l: ["overlap with shell and other fill","as fraction of nozzle diameter","0.0 - 2.0"], // fi_rate_s: "print speed", @@ -568,9 +568,9 @@ self.kiri.lang['en-us'] = { ou_bedd_s: "bed temp", ou_bedd_l: "degrees in celsius", ou_feed_s: "print speed", - ou_feed_l: ["max print speed","millimeters / second"], + ou_feed_l: ["max printing speed","set to 0 to use default","millimeters / second"], ou_fini_s: "finish speed", - ou_fini_l: ["outermost shell speed","millimeters / second"], + ou_fini_l: ["outermost shell speed","bridge/flat solid layers","set to 0 to use default","millimeters / second"], ou_move_s: "move speed", ou_move_l: ["non-print move speed","millimeters / second","0 = enable G0 moves"], ou_shml_s: "shell factor",