From 9a463881d1c20c519e992513060a0393bed93ad5 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Tue, 6 Jan 2026 19:16:11 -0500 Subject: [PATCH] reflow / rename / document fdm slicing --- src/kiri/mode/fdm/post.js | 11 +- src/kiri/mode/fdm/slice.js | 315 +++++++++++++++++++------------------ src/kiri/mode/sla/slice.js | 8 +- src/kiri/run/minion.js | 4 +- 4 files changed, 178 insertions(+), 160 deletions(-) diff --git a/src/kiri/mode/fdm/post.js b/src/kiri/mode/fdm/post.js index 68ac94d2..10cdbe40 100644 --- a/src/kiri/mode/fdm/post.js +++ b/src/kiri/mode/fdm/post.js @@ -9,14 +9,17 @@ import { slicer } from '../../../geo/slicer.js'; import { Point } from '../../../geo/point.js'; import { Slope } from '../../../geo/slope.js'; -slicer.slicePost.FDM = slicePost; +// tell the slicer what to do in FDM mode +// with slices (post processing). the post +// processor may depend on worker / minion context +slicer.slicePost.FDM = slicerPostProcessor; /** * may run in minion or worker context. do not create objects * that will not quickly encode in threaded mode. add to existing * data object. return is ignored. */ -export function slicePost(data, options) { +function slicerPostProcessor(data, options) { const { groups, z } = data; const { post_args, useAssembly, zIndexes } = options; const { process, vaseMode } = post_args; @@ -81,7 +84,7 @@ export function slicePost(data, options) { const nutops = []; // co-locate shell processing with top generation in slicer for (let top of data.tops) { - nutops.push(doTopShells(z, top, count, offset/2, offset, fillOff, { + nutops.push(layerProcessTop(z, top, count, offset/2, offset, fillOff, { thinType, vaseMode, useAssembly @@ -687,7 +690,7 @@ function trace_noodle(noodle, noodleWidth, minR, midR, maxR, opt = {}) { * may run in minion or worker context. performs shell offsetting * including thin wall detection when enabled */ -export function doTopShells(z, top, count, offset1, offsetN, fillOffset, opt = {}) { +export function layerProcessTop(z, top, count, offset1, offsetN, fillOffset, opt = {}) { // pretend we're a top object in minions if (!top.poly) { top = { poly: top }; diff --git a/src/kiri/mode/fdm/slice.js b/src/kiri/mode/fdm/slice.js index 0493515e..d79f3066 100644 --- a/src/kiri/mode/fdm/slice.js +++ b/src/kiri/mode/fdm/slice.js @@ -1,7 +1,6 @@ /** Copyright Stewart Allen -- All Rights Reserved */ -import { base, util } from '../../../geo/base.js'; -import { doTopShells } from './post.js'; +import { layerProcessTop } from './post.js'; import { fill, fill_fixed } from './fill.js'; import { generateBeltAnchor, embossBeltPooch, finalizeBeltBounds } from './belt.js'; import { getRangeParameters } from './driver.js'; @@ -10,8 +9,7 @@ import { newPolygon } from '../../../geo/polygon.js'; import { newSlice } from '../../core/slice.js'; import { polygons as POLY } from '../../../geo/polygons.js'; import { slice, sliceZ } from '../../../geo/slicer.js'; - -const { config } = base; +import { util } from '../../../geo/base.js'; const CONSTANTS = { // Support fill @@ -174,55 +172,6 @@ function vopt(opt, ctx) { return opt; } -/** - * DRIVER SLICE CONTRACT - * - * global slice operation run after all individual widget slice() complete - */ -export function slicePost(settings, onupdate) { - // future home of brim and anchor generation - let widgets = Object.values(self.kiri_worker.cache) - .filter(w => !w.meta.disabled) - .sort((a,b) => { - return a.slices[0].z - b.slices[0].z - }); - // assign grid_id which can be embedded in gcode and - // used by the controller to cancel objects during print - let { bounds } = settings; - for (let widget of widgets) { - let { pos, box } = widget.track; - // calculate top/left coordinate for widget - // relative to bounding box for all widgets - let tl = { - x: Math.round((pos.x - box.w/2 - bounds.min.x) / 10) + 1, - y: Math.round((pos.y - box.h/2 - bounds.min.y) / 10) + 1 - }; - widget.track.grid_id = tl.x * 100 + tl.y; - } - // count extruders used - let ext = []; - for (let w of widgets) { - if (w.anno && w.anno.extruder >= 0) { - let e = w.anno.extruder; - if (ext.indexOf(e) < 0) { - ext.push(e); - } - } - } - // sort widgets by first slice Z - widgets.sort((a,b) => { - return a.slices[0].z - b.slices[0].z; - }); - // give first widget a pass since it should have the anchor - widgets.shift(); - // remove anchor slices from other widgets (only with multi-material) - if (ext.length > 1) { - for (let w of widgets) { - w.slices = w.slices.filter(s => s.index >= 0); - } - } -}; - /** * DRIVER SLICE CONTRACT * @@ -258,7 +207,7 @@ export function sliceOne(settings, widget, onupdate, ondone) { shellOffset = lineWidth, fillSpacing = lineWidth, fillOffset = lineWidth * fillOffsetMult, - clipOffset = process.sliceSupportOffset, + clipOffset = process.sliceSupportOffset + lineWidth / 2, sliceFillAngle = process.sliceFillAngle, supportDensity = process.sliceSupportDensity, { sliceCompInner, sliceCompOuter } = process; @@ -344,6 +293,8 @@ export function sliceOne(settings, widget, onupdate, ondone) { } } + // create Slice objects for specified list of Z heights + // zGen() produces the list (or empty for slicer auto-detected) slice(points, { strict: true, debug: process.xray, @@ -372,7 +323,13 @@ export function sliceOne(settings, widget, onupdate, ondone) { onupdate(update) { return onupdate(0.0 + update * 0.5) } - }).then((output) => { + }) + .then(decodeSlices) + .then(processSlices) + .then(ondone); + + // turn slicer raw output into Slice objects + function decodeSlices(output) { // post process slices and re-incorporate missing meta-data return output.slices.map(data => { let { z, clip, lines, groups, changes } = data; @@ -397,9 +354,7 @@ export function sliceOne(settings, widget, onupdate, ondone) { } return slice; }).filter(s => s); - }).then(slices => { - return onSliceDone(slices); - }).then(ondone); + } // z index generator function zGen(zopt) { @@ -483,9 +438,9 @@ export function sliceOne(settings, widget, onupdate, ondone) { return zi; } - async function onSliceDone(slices) { + async function processSlices(slices) { /** - * Process automatic shadow-based support generation + * Process shadow-based support generation */ async function processAutoSupport() { if (process.sliceSupportType !== 'automatic') { @@ -504,17 +459,22 @@ export function sliceOne(settings, widget, onupdate, ondone) { stack.sort((a,b) => b.z - a.z); // accumulate deltas } + // 1. accumulate / union shadow coverage top down + // 2. trim to area outside slice.clips + for (let slice of stack) { let shadow = await widget.shadowAt(slice.z, true); if (process.sliceSupportExtra) { shadow = POLY.offset(shadow, process.sliceSupportExtra); } slice.supports = shadow; + slice.output().setLayer("shadow", 0xff0000).addPolys(shadow); } } /** - * Process solid layer fills (top/bottom layers) + * Process top and bottom layers or any other + * layers detected and marked for solid fill */ function processSolidLayers() { forSlices(0.15, 0.2, slice => { @@ -527,7 +487,7 @@ export function sliceOne(settings, widget, onupdate, ondone) { let solidWidth = isSolid ? range.sliceFillWidth || 1 : 0; if (solidWidth) { let fillSpace = fillSpacing * solidWidth; - doSolidLayerFill({ slice, spacing: fillSpace, angle: sliceFillAngle }); + layerMakeSolid({ slice, spacing: fillSpace, angle: sliceFillAngle }); } if (slice.index === slices.length - 1) { slice.isFlatsLayer = true; @@ -544,15 +504,16 @@ export function sliceOne(settings, widget, onupdate, ondone) { * Process layer diffs and project solid areas */ function processLayerDiffs() { + // boolean diff layers to detect bridges and flats profileStart("delta"); forSlices(0.2, 0.34, slice => { let params = slice.params || process; let solidMinArea = params.sliceSolidMinArea; let sliceFillGrow = params.sliceFillGrow; - doDiff(slice, { min: solidMinArea, grow: sliceFillGrow }); + layerDiff(slice, { min: solidMinArea, grow: sliceFillGrow }); }, "layer deltas"); profileEnd(); - + // project bridges and flats up and down into part profileStart("delta-project"); forSlices(0.34, 0.35, slice => { let params = slice.params || process; @@ -560,6 +521,7 @@ export function sliceOne(settings, widget, onupdate, ondone) { bottomLayers = params.sliceBottomLayers || 0; if (topLayers) projectFlats(slice, topLayers); if (bottomLayers) projectBridges(slice, bottomLayers); + if (slice.flats) POLY.setZ(slice.flats, slice.z); }, "layer deltas"); profileEnd(); } @@ -572,11 +534,10 @@ export function sliceOne(settings, widget, onupdate, ondone) { let promises = isConcurrent ? [] : undefined; forSlices(0.35, promises ? 0.4 : 0.5, slice => { let params = slice.params || process; - let first = slice.index === 0; let solidWidth = params.sliceFillWidth || 1; let fillSpace = fillSpacing * solidWidth; let solidMinArea = params.sliceSolidMinArea; - doSolidsFill({ slice, spacing: fillSpace, angle: sliceFillAngle, minArea: solidMinArea, promises }); + layerFillSolids({ slice, spacing: fillSpace, angle: sliceFillAngle, minArea: solidMinArea, promises }); sliceFillAngle = (sliceFillAngle + 90.0) % 360; }, "fill solids"); // very last layer (top) is set to finish solid rate @@ -601,7 +562,7 @@ export function sliceOne(settings, widget, onupdate, ondone) { return; } let newType = params.sliceFillType; - doSparseLayerFill(slice, { + layerSparseFill(slice, { settings, process, device, @@ -642,7 +603,7 @@ export function sliceOne(settings, widget, onupdate, ondone) { forSlices(0.8, promises ? 0.88 : 0.9, slice => { let params = slice.params || process; let density = params.sliceSupportDensity; - doSupportFill({ + layerSupportFill({ angle: process.sliceSupportFill, density, gap: process.sliceSupportGap, @@ -765,9 +726,6 @@ export function sliceOne(settings, widget, onupdate, ondone) { slice.params = getRangeParameters(process, slice.index); } - // do not hint polygon fill longer than a max span length - config.hint_len_max = util.sqr(process.sliceBridgeMax); - // reset for solids, support projections // and other annotations slices.forEach(slice => { @@ -781,8 +739,6 @@ export function sliceOne(settings, widget, onupdate, ondone) { // add lead in anchor when specified in belt mode (but not for synths) if (isBelt) { - let { slope } = widget.belt; - // Generate belt anchor generateBeltAnchor({ slices, @@ -841,7 +797,7 @@ export function sliceOne(settings, widget, onupdate, ondone) { if (render) { forSlices(0.9, 1.0, slice => { let params = slice.params || process; - doRender(slice, params, { + layerRender(slice, params, { dark: controller.dark, devel: controller.devel, renderContext @@ -899,7 +855,7 @@ function bound(v,min,max) { * @param {boolean} opt.devel - Enable development visualization * @param {RenderContext} opt.renderContext - Rendering context */ -function doRender(slice, params, opt = {}) { +function layerRender(slice, params, opt = {}) { const { dark, devel, renderContext: ctx } = opt; const Color = dark ? COLOR_DARK : COLOR; const output = slice.output(); @@ -961,15 +917,15 @@ function doRender(slice, params, opt = {}) { }); if (isThin && devel) { - if (slice.solids && slice.solids.length) output + if (slice.solids?.length) output .setLayer("solids", { face: 0xbbbb00, check: 0xbbbb00 }) .addAreas(slice.solids); - if (slice.bridges && slice.bridges.length) output + if (slice.bridges?.length) output .setLayer("bridges", { face: 0x00cccc, line: 0x00cccc, check: 0x00cccc }) .addAreas(slice.bridges); - if (slice.flats && slice.flats.length) output + if (slice.flats?.length) output .setLayer("flats", { face: 0xaa00aa, line: 0xaa00aa, check: 0xaa00aa }) .addAreas(slice.flats); } @@ -1004,6 +960,55 @@ function doRender(slice, params, opt = {}) { // console.log(slice.index, slice.render.stats); } +/** + * DRIVER SLICE CONTRACT + * + * global slice operation run after all individual widget slice() complete + */ +export function slicePost(settings, onupdate) { + // future home of brim and anchor generation + let widgets = Object.values(self.kiri_worker.cache) + .filter(w => !w.meta.disabled) + .sort((a,b) => { + return a.slices[0].z - b.slices[0].z + }); + // assign grid_id which can be embedded in gcode and + // used by the controller to cancel objects during print + let { bounds } = settings; + for (let widget of widgets) { + let { pos, box } = widget.track; + // calculate top/left coordinate for widget + // relative to bounding box for all widgets + let tl = { + x: Math.round((pos.x - box.w/2 - bounds.min.x) / 10) + 1, + y: Math.round((pos.y - box.h/2 - bounds.min.y) / 10) + 1 + }; + widget.track.grid_id = tl.x * 100 + tl.y; + } + // count extruders used + let ext = []; + for (let w of widgets) { + if (w.anno && w.anno.extruder >= 0) { + let e = w.anno.extruder; + if (ext.indexOf(e) < 0) { + ext.push(e); + } + } + } + // sort widgets by first slice Z + widgets.sort((a,b) => { + return a.slices[0].z - b.slices[0].z; + }); + // give first widget a pass since it should have the anchor + widgets.shift(); + // remove anchor slices from other widgets (only with multi-material) + if (ext.length > 1) { + for (let w of widgets) { + w.slices = w.slices.filter(s => s.index >= 0); + } + } +} + /** * Compute offset shell polygons. For FDM, the first offset is usually half * of the nozzle width. Each subsequent offset is a full nozzle width. User @@ -1018,9 +1023,9 @@ function doRender(slice, params, opt = {}) { * @param {number} fillOffset * @param {Obejct} options */ -export function doShells(slice, count, offset1, offsetN, fillOffset, opt = {}) { +export function layerProcessTops(slice, count, offset1, offsetN, fillOffset, opt = {}) { for (let top of slice.tops) { - doTopShells(slice.z, top, count, offset1, offsetN, fillOffset, opt); + layerProcessTop(slice.z, top, count, offset1, offsetN, fillOffset, opt); } } @@ -1039,9 +1044,7 @@ export function doShells(slice, count, offset1, offsetN, fillOffset, opt = {}) { * @param {number} args.spacing - Fill line spacing in mm * @param {number} args.angle - Fill angle in degrees */ -function doSolidLayerFill(args) { - const { slice, spacing, angle } = args; - +function layerMakeSolid({ slice, spacing, angle }) { if (slice.xray) { return; } @@ -1064,7 +1067,7 @@ function doSolidLayerFill(args) { * Take output from pluggable sparse infill algorithm and clip to * the bounds of the top polygons and their inner solid areas. */ -function doSparseLayerFill(slice, options = {}) { +function layerSparseFill(slice, options = {}) { if (slice.xray || options.type === 'none') { return; } @@ -1239,7 +1242,7 @@ function doSparseLayerFill(slice, options = {}) { * Used to calculate bridges, flats and then solid projections. * 'expand' is used for top offsets in SLA mode */ -export function doDiff(slice, options = {}) { +export function layerDiff(slice, options = {}) { const { sla, fakedown, grow, min } = options; if ((slice.index <= 0 && !fakedown) || slice.xray) { return; @@ -1277,47 +1280,7 @@ export function doDiff(slice, options = {}) { bridges.appendAll(newBridges); flats.appendAll(newFlats); -}; - -/** - * - * - * @param {Polygon[]} polys - */ -function addSolidFills(slice, polys) { - if (slice.solids) { - slice.solids.appendAll(polys); - } else if (polys && polys.length) { - console.log({no_solids_in: slice, for: polys}) - } -}; - -/** - * project bottom flats down - */ -export function projectFlats(slice, count, expand) { - if (!slice.down || !slice.flats) return; - // these flats are marked for finishing print speed - if (slice.flats?.length) { - slice.finishSolids = true; - slice.isFlatsLayer = true; - const flats = expand ? POLY.expand(slice.flats, expand) : slice.flats; - projectSolid({ slice, polys: flats, count, up: false, first: true }); - } -}; - -/** - * project top bridges up - */ -export 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; - slice.isBridgeLayer = true; - } - projectSolid({ slice, polys: slice.bridges, count, up: true, first: true }); -}; +} /** * Fill projected solid areas and store line data @@ -1330,8 +1293,7 @@ export function projectBridges(slice, count) { * @param {Promise[]} [args.promises] - Array for async operations * @return {boolean} true if filled, false if not */ -function doSolidsFill(args) { - const { slice, spacing, angle, minArea, promises: fillQ } = args; +function layerFillSolids({ slice, spacing, angle, minArea, promises: fillQ }) { let minarea = minArea || 1, tops = slice.tops, solids = slice.solids; @@ -1406,7 +1368,7 @@ function doSolidsFill(args) { for (let top of tops) { top.solids = []; } - doSolidLayerFill({ slice, spacing, angle }); + layerMakeSolid({ slice, spacing, angle }); return; } @@ -1435,12 +1397,12 @@ function doSolidsFill(args) { } } if (tofill.length > 0) { - doFillArea({ promises: fillQ, polys: tofill, angle, spacing, output: newfill }); + areaFill({ promises: fillQ, polys: tofill, angle, spacing, output: newfill }); } if (angfill.length > 0) { top.fill_lines_ang = {spacing:spacing,list:[],poly:[]}; for (let af of angfill) { - doFillArea({ + areaFill({ promises: fillQ, polys: [af], angle: af.fillang.angle + CONSTANTS.ANGLED_FILL_ROTATION, @@ -1464,8 +1426,7 @@ function doSolidsFill(args) { * @param {number} [args.minLen] - Minimum line length * @param {number} [args.maxLen] - Maximum line length */ -function doFillArea(args) { - const { promises: fillQ, polys, angle, spacing, output, minLen, maxLen } = args; +function areaFill({ promises: fillQ, polys, angle, spacing, output, minLen, maxLen }) { if (fillQ) { fillQ.push(self.kiri_worker.minions.fill(polys, angle, spacing, output, minLen, maxLen)); } else { @@ -1512,14 +1473,13 @@ function doFillArea(args) { * Each polygon has a .fill property with fill lines * @modifies {Slice} slice.supportOutline - Stores support outline polygons * - * @see fillSupportPolys - Called internally to generate fill patterns + * @see supportPolyFill - Called internally to generate fill patterns * @see CONSTANTS.SUPPORT_INSET_RATIO - Inset ratio (1/3 of line width) * @see CONSTANTS.SUPPORT_AUTO_ANGLE_WIDE - Auto angle for wide polygons (1090 = 90°) * @see CONSTANTS.SUPPORT_AUTO_ANGLE_TALL - Auto angle for tall polygons (1000 = 0°) * @see CONSTANTS.SUPPORT_CONNECT_DISTANCE_MULT - Distance multiplier for line connection (2x) */ - function doSupportFill(args) { - const { promises, slice, lineWidth, density, minArea, isBelt, angle, outline, gap } = args; + function layerSupportFill({ promises, slice, lineWidth, density, minArea, isBelt, angle, outline, gap }) { let supports = slice.supports, min = minArea || 0.1, sub; @@ -1546,7 +1506,7 @@ function doFillArea(args) { } if (supports) { - fillSupportPolys({ + supportPolyFill({ promises, polys: supports, lineWidth, density, z: slice.z, isBelt, angle, outline }); } @@ -1617,8 +1577,8 @@ function doFillArea(args) { * - Lines are either individual segments (outline=true) or * connected paths (outline=false) for travel reduction * - * @see doSupportFill - Parent function that calls this after clipping/union - * @see doFillArea - Lower-level function that generates the actual scan lines + * @see layerSupportFill - Parent function that calls this after clipping/union + * @see areaFill - Lower-level function that generates the actual scan lines * @see connect_lines - Utility that connects nearby line segments * @see CONSTANTS.SUPPORT_AUTO_ANGLE_WIDE - Auto angle for wide polygons (1090 = 90°) * @see CONSTANTS.SUPPORT_AUTO_ANGLE_TALL - Auto angle for tall polygons (1000 = 0°) @@ -1626,7 +1586,7 @@ function doFillArea(args) { * @see CONSTANTS.SUPPORT_CONNECT_DISTANCE_MULT - Distance multiplier for line connection (2x) */ -function fillSupportPolys({ promises, polys, lineWidth, density, z, isBelt, angle, outline }) { +function supportPolyFill({ promises, polys, lineWidth, density, z, isBelt, angle, outline }) { // calculate fill density let spacing = lineWidth * (1 / density); for (let poly of polys) { @@ -1636,7 +1596,7 @@ function fillSupportPolys({ promises, polys, lineWidth, density, z, isBelt, angl let inset = POLY.offset([poly], -lineWidth * CONSTANTS.SUPPORT_INSET_RATIO, {flat: true, z, wasm: true}); // do the fill if (inset && inset.length > 0) { - doFillArea({ + areaFill({ angle: angle || auto, output: poly.fill = [], polys: inset, @@ -1660,24 +1620,79 @@ function fillSupportPolys({ promises, polys, lineWidth, density, z, isBelt, angl * @param {boolean} args.up - Project upward (true) or downward (false) * @param {boolean} args.first - First projection (hint fill angles) */ -function projectSolid(args) { - const { slice, polys, count, up, first } = args; - +function projectSolid({ slice, polys, count, up, first }) { if (slice && !up && count === 1) { slice.isBridgeLayer = true; } + if (!slice || count <= 0) { return; } + let clones = polys.clone(true); if (first) { - clones.forEach(function(p) { - p.hintFillAngle(); - }); + for (let clone of clones) { + clone.hintFillAngle(); + } } - addSolidFills(slice, clones); + + if (slice.solids) { + slice.solids.appendAll(clones); + } else if (clones && clones.length) { + console.log({no_solids_in: slice, for: clones}) + } + if (count > 0) { - if (up) projectSolid({ slice: slice.up, polys, count: count-1, up: true, first: false }); - else projectSolid({ slice: slice.down, polys, count: count-1, up: false, first: false }); + projectSolid({ + count: count - 1, + first: false, + polys, + slice: up ? slice.up : slice.down, + up + }); + // if (up) { + // projectSolid({ + // count: count-1, + // first: false, + // polys, + // slice: slice.up, + // up: true + // }); + // } else { + // projectSolid({ + // count: count-1, + // first: false, + // polys, + // slice: slice.down, + // up: false + // }); + // } } } + +/** + * project bottom flats down into part + */ +export function projectFlats(slice, count, expand) { + if (!slice.down || !slice.flats) return; + // these flats are marked for finishing print speed + if (slice.flats?.length) { + slice.finishSolids = true; + slice.isFlatsLayer = true; + const flats = expand ? POLY.expand(slice.flats, expand) : slice.flats; + projectSolid({ slice, polys: flats, count, up: false, first: true }); + } +} + +/** + * project top bridges up into part + */ +export 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; + slice.isBridgeLayer = true; + } + projectSolid({ slice, polys: slice.bridges, count, up: true, first: true }); +} diff --git a/src/kiri/mode/sla/slice.js b/src/kiri/mode/sla/slice.js index 2c2e3d4e..f51caad5 100644 --- a/src/kiri/mode/sla/slice.js +++ b/src/kiri/mode/sla/slice.js @@ -5,7 +5,7 @@ import { slicer } from '../../../geo/slicer.js'; import { newPolygon } from '../../../geo/polygon.js'; import { polygons as POLY } from '../../../geo/polygons.js'; import { newSlice, newTop } from '../../core/slice.js'; -import { doShells, doDiff, projectFlats, projectBridges } from '../fdm/slice.js'; +import { layerProcessTops, layerDiff, projectFlats, projectBridges } from '../fdm/slice.js'; import { PNG } from '../../../ext/pngjs.esm.js'; import { SLA } from './driver.js'; @@ -149,14 +149,14 @@ export function sla_slice(settings, widget, onupdate, ondone) { work_remain = work_total; forSlices(slices, 5, (slice,index) => { if (process.slaShell) { - doShells(slice, 2, 0, process.slaShell); + layerProcessTops(slice, 2, 0, process.slaShell); } else { - doShells(slice, 1, 0); + layerProcessTops(slice, 1, 0); } }, "shells"); forSlices(slices, 10, (slice) => { if (slice.synth) return; - doDiff(slice, 0.000001, { + layerDiff(slice, 0.000001, { sla: true, fakedown: !process.slaOpenBase }); diff --git a/src/kiri/run/minion.js b/src/kiri/run/minion.js index 5186e6ee..c125f38d 100644 --- a/src/kiri/run/minion.js +++ b/src/kiri/run/minion.js @@ -8,7 +8,7 @@ import '../../add/three.js'; import { base } from '../../geo/base.js'; import { codec, encode, encodePointArray } from '../core/codec.js'; -import { doTopShells } from '../mode/fdm/post.js'; +import { layerProcessTop } from '../mode/fdm/post.js'; import { newPoint } from '../../geo/point.js'; import { newWidget } from '../core/widget.js'; import { polygons as POLY } from '../../geo/polygons.js'; @@ -92,7 +92,7 @@ const funcs = self.minion = { topShells(data, seq) { let top = codec.decode(data.top, {full: true}); let {z, count, offset1, offsetN, fillOffset, opt} = data; - doTopShells(z, top, count, offset1, offsetN, fillOffset, opt); + layerProcessTop(z, top, count, offset1, offsetN, fillOffset, opt); let state = { zeros: [] }; reply({ seq, top: codec.encode(top, {full: true}) }, state.zeros); },