From 367bf32b0a90d353224de9c7095e6f691966d766 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Fri, 12 Dec 2025 18:10:06 -0500 Subject: [PATCH] add roughing flat passes option --- src/kiri/core/conf.js | 1 + src/kiri/mode/cam/cl-ops.js | 2 ++ src/kiri/mode/cam/op-area.js | 10 +++++++--- src/kiri/mode/cam/op-rough.js | 33 +++++++++++++++++++++++++++++---- src/kiri/mode/cam/slice.js | 9 +++++++-- web/kiri/lang/en.js | 2 ++ 6 files changed, 48 insertions(+), 9 deletions(-) diff --git a/src/kiri/core/conf.js b/src/kiri/core/conf.js index 9d83ae4b..39ccea78 100644 --- a/src/kiri/core/conf.js +++ b/src/kiri/core/conf.js @@ -565,6 +565,7 @@ export const conf = { camRegisterThru: 5, camRoughAll: true, camRoughDown: 2, + camRoughFlat: false, camRoughIn: true, camRoughOmitThru: false, camRoughOmitVoid: false, diff --git a/src/kiri/mode/cam/cl-ops.js b/src/kiri/mode/cam/cl-ops.js index b43a61ed..68c10241 100644 --- a/src/kiri/mode/cam/cl-ops.js +++ b/src/kiri/mode/cam/cl-ops.js @@ -227,6 +227,7 @@ export function createPopOps() { leave: 'camRoughStock', leavez: 'camRoughStockZ', all: 'camRoughAll', + flats: 'camRoughFlat', inside: 'camRoughIn', omitthru: 'camRoughOmitThru', ov_topz: 0, @@ -246,6 +247,7 @@ export function createPopOps() { sep: UC.newBlank({ class: "pop-sep" }), all: UC.newBoolean(LANG.cr_clst_s, undefined, { title: LANG.cr_clst_l, show: () => !env.poppedRec.inside || env.poppedRec.all }), inside: UC.newBoolean(LANG.cr_olin_s, undefined, { title: LANG.cr_olin_l, show: () => !env.poppedRec.all || env.poppedRec.inside }), + flats: UC.newBoolean(LANG.cr_clrf_s, undefined, { title: LANG.cr_clrf_l }), omitthru: UC.newBoolean(LANG.co_omit_s, undefined, { title: LANG.co_omit_l }), sep: UC.newBlank({ class: "pop-sep" }), exp: UC.newExpand("overrides"), diff --git a/src/kiri/mode/cam/op-area.js b/src/kiri/mode/cam/op-area.js index 20c4bf23..80cf57bd 100644 --- a/src/kiri/mode/cam/op-area.js +++ b/src/kiri/mode/cam/op-area.js @@ -28,7 +28,8 @@ class OpArea extends CamOp { async slice(progress) { let { op, state } = this; - let { direction, down, expand, follow, mode, outline, over, rename, smooth, tool } = op; + let { direction, down, expand, flats, flatOff, follow } = op; + let { mode, outline, over, rename, smooth, tool } = op; let { addSlices, color, cutTabs, settings } = state; let { shadowAt, setToolDiam, tabs, widget, workarea } = state; @@ -129,7 +130,10 @@ class OpArea extends CamOp { newArea(); if (mode === 'clear') { - let zs = down ? base_util.lerp(zTop, zBottom, down) : [ bounds.min.z ]; + let zMov = flatOff ?? 0; + let zs = flats ? + flats.filter(z => z <= zTop && z >= zBottom).map(v => v + zMov ?? 0) : + down ? base_util.lerp(zTop, zBottom, down) : [ bounds.min.z ]; let zroc = 0; let zinc = 1 / zs.length; let lzo; @@ -152,7 +156,7 @@ class OpArea extends CamOp { let firstOff = -(toolDiam / 2 + (op.leave_xy ?? 0)); POLY.subtract([ area ], shadow, clip, undefined, undefined, 0); POLY.offset(clip, [ firstOff, -toolOver ], { - count: op.steps ?? 999, outs, flat: true, z, minArea: 0 + count: op.steps ?? 999, outs, flat: true, z: z - zMov, minArea: 0 }); // if we see no offsets, re-check the mesh bottom Z then exit if (outs.length === 0) { diff --git a/src/kiri/mode/cam/op-rough.js b/src/kiri/mode/cam/op-rough.js index ef874aa9..4f8f1774 100644 --- a/src/kiri/mode/cam/op-rough.js +++ b/src/kiri/mode/cam/op-rough.js @@ -14,10 +14,8 @@ class OpRough extends CamOp { async slice(progress) { let { op, state } = this; - let { shadow, stock, tool, widget } = state; - let { workarea } = state; + let { newSlicer, shadow, stock, tool, widget } = state; - let cutThruBypass = op.down > workarea.top_stock - workarea.bottom_part; let cutOutside = !op.inside; let shadowBase = shadow.base; @@ -54,9 +52,36 @@ class OpRough extends CamOp { surfaces: {} })); + if (op.flats) { + let slicer = newSlicer(); + ops_list.push(new OpArea(state, { + rename: op.rename ?? "flats", + spindle: op.spindle, + direction: op.direction, + tool: op.tool, + rate: op.rate, + plunge: op.plunge, + mode: 'clear', + over: op.step, + down: op.down, + expand: 0, + smooth: 0, + outline: true, + omitthru: op.omitthru, + leave_xy: op.leave, + leave_z: op.leavez, + ov_botz: op.ov_botz, + ov_topz: op.ov_topz, + areas: { [widget.id]: areas.map(p => p.toArray()) }, + surfaces: {}, + flats: Object.keys(slicer.zFlat).map(v => parseFloat(v)).sort((a,b) => b-a), + flatOff: 0.01 + })); + } + if (cutOutside) { ops_list.push(new OpArea(state, { - rename: op.rename ?? "rough", + rename: op.rename ?? "cutout", spindle: op.spindle, direction: op.direction === 'climb' ? 'conventional' : 'climb', tool: op.tool, diff --git a/src/kiri/mode/cam/slice.js b/src/kiri/mode/cam/slice.js index fdfa24fd..91039d57 100644 --- a/src/kiri/mode/cam/slice.js +++ b/src/kiri/mode/cam/slice.js @@ -173,6 +173,7 @@ export async function cam_slice(settings, widget, onupdate, ondone) { cutTabs, dark, isIndexed, + newSlicer, ops: opList, setAxisIndex, setToolDiam, @@ -218,8 +219,12 @@ export async function cam_slice(settings, widget, onupdate, ondone) { } } - function updateSlicer() { - slicer = state.slicer = new cam_slicer(widget); + function newSlicer(opts) { + return new cam_slicer(widget, opts); + } + + function updateSlicer(opts) { + return slicer = state.slicer = new cam_slicer(widget, opts); } async function computeShadows() { diff --git a/web/kiri/lang/en.js b/web/kiri/lang/en.js index f79fbd49..88c5ec07 100644 --- a/web/kiri/lang/en.js +++ b/web/kiri/lang/en.js @@ -544,6 +544,8 @@ self.lang['en-us'] = { cr_clrt_l: ["run a clearing pass over","the bounding area of the part","at z = 0"], cr_olin_s: "inside only", cr_olin_l: ["limit cutting to","inside part boundaries"], + cr_clrf_s: "clear faces", + cr_clrf_l: ["add additional clearing passes","for detected z planar flat areas"], // CNC OUTLINE co_menu: "outline",