diff --git a/release.md b/release.md index 4198441b..40eddca6 100644 --- a/release.md +++ b/release.md @@ -26,6 +26,7 @@ Full docs @ https://docs.grid.space/projects/kiri-moto * add FDM gcode feature macros for transitions * add FDM option to alternate shell winding direction * add FDM print time estimate fudge factor for devices +* add `clear top` option to CNC outline operation ## Mesh:Tool (1.2.0) diff --git a/src/kiri-mode/cam/client.js b/src/kiri-mode/cam/client.js index 57f80bf6..2f39fc98 100644 --- a/src/kiri-mode/cam/client.js +++ b/src/kiri-mode/cam/client.js @@ -962,7 +962,8 @@ CAM.init = function(kiri, api) { omitthru: 'camOutlineOmitThru', outside: 'camOutlineOut', inside: 'camOutlineIn', - wide: 'camOutlineWide' + wide: 'camOutlineWide', + top: 'camOutlineTop' }).inputs = { tool: UC.newSelect(LANG.cc_tool, {}, "tools"), sep: UC.newBlank({class:"pop-sep"}), @@ -976,7 +977,8 @@ CAM.init = function(kiri, api) { inside: UC.newBoolean(LANG.co_olin_s, undefined, {title:LANG.co_olin_l, show:(op) => { return !op.inputs.outside.checked }}), outside: UC.newBoolean(LANG.co_olot_s, undefined, {title:LANG.co_olot_l, show:(op) => { return !op.inputs.inside.checked }}), omitthru: UC.newBoolean(LANG.co_omit_s, undefined, {title:LANG.co_omit_l, xshow:(op) => { return op.inputs.outside.checked }}), - wide: UC.newBoolean(LANG.co_wide_s, undefined, {title:LANG.co_wide_l, show:(op) => { return !op.inputs.inside.checked }}) + wide: UC.newBoolean(LANG.co_wide_s, undefined, {title:LANG.co_wide_l, show:(op) => { return !op.inputs.inside.checked }}), + top: UC.newBoolean(LANG.co_clrt_s, undefined, {title:LANG.co_clrt_l}), }; createPopOp('contour', { diff --git a/src/kiri-mode/cam/ops.js b/src/kiri-mode/cam/ops.js index 13181d7a..1c5a4090 100644 --- a/src/kiri-mode/cam/ops.js +++ b/src/kiri-mode/cam/ops.js @@ -420,6 +420,7 @@ class OpOutline extends CamOp { let { op, state } = this; let { settings, widget, slicer, sliceAll, tshadow, thruHoles, unsafe, color } = state; let { updateToolDiams, zThru, zBottom, shadowTop, tabs, cutTabs, cutPolys } = state; + let { zMax, ztOff } = state; let { process, stock } = settings; if (op.down <= 0) { @@ -431,7 +432,11 @@ class OpOutline extends CamOp { let shadow = []; let slices = []; - let indices = slicer.interval(op.down, { down: true, min: zBottom, fit: true, off: 0.01 }); + let intopt = { + down: true, min: zBottom, fit: true, off: 0.01, + max: op.top ? zMax + ztOff : undefined + }; + let indices = slicer.interval(op.down, intopt); let trueShadow = process.camTrueShadow === true; // shift out first (top-most) slice indices.shift(); @@ -470,6 +475,19 @@ class OpOutline extends CamOp { }, genso: true }); shadow = POLY.union(shadow.appendAll(shadowTop.tops), 0.01, true); + // start slices at top of stock when `clear top` enabled + if (op.top) { + let first = slices[0]; + for (let z of indices.filter(v => v >= zMax)) { + console.log({synth: z}); + let add = first.clone(true); + add.tops.forEach(top => top.poly.setZ(add.z)); + add.shadow = first.shadow.clone(true); + add.z = z; + slices.splice(0,0,add); + } + } + // extend cut thru (only when z bottom is 0) if (zThru) { let last = slices[slices.length-1]; diff --git a/web/kiri/lang/en.js b/web/kiri/lang/en.js index c00d6d36..5960081f 100644 --- a/web/kiri/lang/en.js +++ b/web/kiri/lang/en.js @@ -474,6 +474,8 @@ self.kiri.lang['en-us'] = { co_menu: "outline", co_dogb_s: "dogbones", co_dogb_l: ["insert dogbone cuts","into inside corners"], + co_clrt_s: "clear top", + co_clrt_l: ["cut starting at the top of stock","when stock is enabled"], co_wide_s: "wide cutout", co_wide_l: ["widen outside cutout paths","for deep cuts in hard material"], co_olin_s: "inside only",