From 7b1f230ded0b8888beac0a7505b67461c91340c7 Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Sun, 22 Jun 2025 22:09:02 -0400 Subject: [PATCH] fix numerous bounds issues with indexed stock fixes #340 fix state variable updates with indexex stock fix large tool animation fixes #352 --- src/kiri-mode/cam/animate2.js | 4 +- src/kiri-mode/cam/client.js | 16 ++-- src/kiri-mode/cam/ops.js | 12 ++- src/kiri-mode/cam/slice.js | 138 ++++++++++++++++++++-------------- src/kiri-mode/cam/tool.js | 2 +- src/kiri/slice.js | 3 - src/kiri/widget.js | 1 + 7 files changed, 104 insertions(+), 72 deletions(-) diff --git a/src/kiri-mode/cam/animate2.js b/src/kiri-mode/cam/animate2.js index 9cbc4ddd..c2d2618b 100644 --- a/src/kiri-mode/cam/animate2.js +++ b/src/kiri-mode/cam/animate2.js @@ -540,7 +540,7 @@ kiri.load(() => { const sd = Math.sqrt(mx*mx + my*my + Math.min(1,mz*mz) + dr*dr); const moves = []; for (let i=0, x=lp.x, y=lp.y, z=lp.z; i { if (!pos) { throw `no pos @ ${index} of ${moves.length}`; } + const { dx, dy, dz } = pos; toolMove(pos); // console.log('renderMoves', {id, moves, seed}); let subs = 0; + if (dx || dy || dz < 0) for (let slice of stockSlices) { if (slice.bounds.intersectsBox(toolMesh.bounds)) { slice.subtractTool(toolMesh); diff --git a/src/kiri-mode/cam/client.js b/src/kiri-mode/cam/client.js index db3b83b8..8edaee87 100644 --- a/src/kiri-mode/cam/client.js +++ b/src/kiri-mode/cam/client.js @@ -474,13 +474,11 @@ CAM.init = function(kiri, api) { return; } let index = 0; - let indexing = false; for (let op of oplist) { if (op.type === '|') { break; } if (op.type === 'index' && !op.disabled) { - indexing = true; if (op.absolute) { index = op.degrees } else { @@ -2190,6 +2188,8 @@ function updateStock() { return; } + api.platform.update_bounds(); + const settings = API.conf.get(); const widgets = API.widgets.all(); @@ -2197,9 +2197,13 @@ function updateStock() { const { x, y, z, center } = stock; UI.func.animate.classList.add('disabled'); + if (camStock) { + SPACE.world.remove(camStock); + camStock = null; + } if (x && y && z) { UI.func.animate.classList.remove('disabled'); - if (!camStock) { + { let geo = new THREE.BoxGeometry(1, 1, 1); let mat = new THREE.MeshBasicMaterial({ color: 0x777777, @@ -2231,21 +2235,17 @@ function updateStock() { let lines = new THREE.LineSegments(ligeo, limat); camStock.lines = lines; camStock.add(lines); - SPACE.world.add(camStock); } + // fight z fighting in threejs camStock.scale.x = x + 0.005; camStock.scale.y = y + 0.005; camStock.scale.z = z + 0.005; camStock.position.x = center.x; camStock.position.y = center.y; camStock.position.z = center.z; - camStock.rotation.x = currentIndex || 0; camStock.lines.material.color = new THREE.Color(isDark() ? 0x555555 : 0xaaaaaa); - } else if (camStock) { - SPACE.world.remove(camStock); - camStock = null; } SPACE.world.remove(camZTop); diff --git a/src/kiri-mode/cam/ops.js b/src/kiri-mode/cam/ops.js index b025431d..9caff5b7 100644 --- a/src/kiri-mode/cam/ops.js +++ b/src/kiri-mode/cam/ops.js @@ -45,12 +45,17 @@ class OpIndex extends CamOp { super(state, op); } - slice() { + async slice() { let { op, state } = this; if (!state.isIndexed) { throw 'index op requires indexed stock'; } - this.degrees = state.setAxisIndex(op.degrees, op.absolute); + let { widget, updateSlicer, computeShadows, setAxisIndex } = state; + this.degrees = setAxisIndex(op.degrees, op.absolute); + // force recompute of topo + widget.topo = undefined; + updateSlicer(); + await computeShadows(); } prepare(ops, progress) { @@ -483,8 +488,7 @@ class OpOutline extends CamOp { async slice(progress) { let { op, state } = this; let { settings, widget, slicer, addSlices, tshadow, thruHoles, unsafe, color } = state; - let { updateToolDiams, tabs, cutTabs, cutPolys, workarea } = state; - let { zMax } = state; + let { updateToolDiams, tabs, cutTabs, cutPolys, workarea, zMax } = state; let { process, stock } = settings; if (op.down <= 0) { diff --git a/src/kiri-mode/cam/slice.js b/src/kiri-mode/cam/slice.js index ef4795f2..5843c98c 100644 --- a/src/kiri-mode/cam/slice.js +++ b/src/kiri-mode/cam/slice.js @@ -32,7 +32,6 @@ const POLY = polygons; CAM.slice = async function(settings, widget, onupdate, ondone) { let proc = settings.process, sliceAll = widget.slices = [], - // slices = widget.slices = [], camOps = widget.camops = [], isIndexed = proc.camStockIndexed; @@ -48,8 +47,17 @@ CAM.slice = async function(settings, widget, onupdate, ondone) { // allow recomputing later if widget or settings changes const var_compute = () => { - stock = settings.stock || {}; + let { camStockX, camStockY, camStockZ, camStockOffset } = proc; bounds = widget.getBoundingBox(); + stock = camStockOffset ? { + x: bounds.dim.x + camStockX, + y: bounds.dim.y + camStockY, + z: bounds.dim.z + camStockZ, + } : { + x: camStockX, + y: camStockY, + z: camStockZ + } track = widget.track; ({ camZTop, camZBottom, camZThru } = proc); wztop = track.top; @@ -73,7 +81,7 @@ CAM.slice = async function(settings, widget, onupdate, ondone) { bottom_part = 0; bottom_stock = -bottom_gap; bottom_thru = zThru; - bottom_z = Math.max( + bottom_z = isIndexed ? zBottom : Math.max( (camZBottom ? bottom_stock + camZBottom : bottom_part) - bottom_thru, (camZBottom ? bottom_stock + camZBottom : bottom_stock - bottom_thru) ); @@ -145,15 +153,55 @@ CAM.slice = async function(settings, widget, onupdate, ondone) { } let mark = Date.now(); - let slicer = new kiri.cam_slicer(widget); + let opList = []; + let opSum = 0; + let opTot = 0; + let shadows = {}; + let slicer; + let state = { + settings, + widget, + bounds, + tabs, + cutTabs, + cutPolys, + healPolys, + shadowAt, + slicer, + addSlices, + isIndexed, + setAxisIndex, + updateToolDiams, + updateSlicer, + computeShadows, + zBottom, + zThru, + ztOff, + zMax, + zTop, + unsafe, + color, + dark, + ops: opList + }; + let tracker = setSliceTracker({ rotation: 0 }); + + function updateSlicer() { + slicer = state.slicer = new kiri.cam_slicer(widget); + } + + async function computeShadows() { + shadows = {}; + await new CAM.OPS.shadow(state, { type: "shadow", silent: true }).slice(progress => { + // console.log('reshadow', progress.round(3)); + }); + } function updateToolDiams(toolDiam) { minToolDiam = Math.min(minToolDiam, toolDiam); maxToolDiam = Math.max(maxToolDiam, toolDiam); } - let shadows = {}; - function shadowAt(z) { let cached = shadows[z]; if (cached) { @@ -216,44 +264,22 @@ CAM.slice = async function(settings, widget, onupdate, ondone) { } } - let state = { - settings, - widget, - bounds, - tabs, - cutTabs, - cutPolys, - healPolys, - shadowAt, - slicer, - addSlices, - isIndexed, - setAxisIndex, - updateToolDiams, - zBottom, - zThru, - ztOff, - zMax, - zTop, - unsafe, - color, - dark, - }; - - let opList = [ - // silently preface op list with OpShadow - new CAM.OPS.shadow(state, { type: "shadow", silent: true }) - ]; - if (false) { opList.push(new CAM.OPS.xray(state, { type: "xray" })); } - let opSum = 0; - let opTot = opList.length ? opList.map(op => op.weight()).reduce((a,v) => a + v) : 0; + let activeOps = proc.ops.filter(op => !op.disabled); + + // silently preface op list with OpShadow + if (isIndexed) { + if (activeOps.length === 0 || activeOps[0].type !== 'index') + opList.push(new CAM.OPS.index(state, { type: "index", index: 0 })); + } else { + opList.push(new CAM.OPS.shadow(state, { type: "shadow", silent: true })); + } // determing # of steps and step weighting for progress bar - for (let op of proc.ops.filter(op => !op.disabled)) { + for (let op of activeOps) { if (op.type === '|') { break; } @@ -265,39 +291,41 @@ CAM.slice = async function(settings, widget, onupdate, ondone) { } } - // give ops access to entire sequence - state.ops = opList; - // call slice() function on all ops in order - let tracker = setSliceTracker({ rotation: 0 }); setAxisIndex(); + updateSlicer(); for (let op of opList) { let weight = op.weight(); // apply operation override vars let workover = var_compute(); let valz = op.op; if (valz.ov_topz) { - workover.top_z = bottom_stock + valz.ov_topz; + workover.top_z = isIndexed ? valz.ov_topz : bottom_stock + valz.ov_topz; } if (valz.ov_botz) { - workover.bottom_z = bottom_stock + valz.ov_botz; + workover.bottom_z = isIndexed ? valz.ov_botz : bottom_stock + valz.ov_botz; workover.bottom_cut = Math.max(workover.bottom_z, -zThru); } - state.workarea = workover; + // state.workarea = workover; + Object.assign(state, { + zBottom, + zThru, + ztOff, + zMax, + zTop, + workarea: workover + }); + // console.log({ + // op, + // workover, + // bounds: structuredClone(bounds), + // stock: structuredClone(stock) + // }); await op.slice((progress, message) => { onupdate((opSum + (progress * weight)) / opTot, message || op.type()); }); + // update tracker rotation for next slice output() visualization tracker.rotation = isIndexed ? axisRotation : 0; - // setup new state when indexing the workspace - if (op.op.type === "index") { - widget.topo = undefined; - // let points = base.verticesToPoints(); - slicer = state.slicer = new kiri.cam_slicer(widget); - shadows = {}; - await new CAM.OPS.shadow(state, { type: "shadow", silent: true }).slice(progress => { - // console.log('reshadow', progress.round(3)); - }); - } camOps.push(op); opSum += weight; } diff --git a/src/kiri-mode/cam/tool.js b/src/kiri-mode/cam/tool.js index 4ef46085..a7a8d9fa 100644 --- a/src/kiri-mode/cam/tool.js +++ b/src/kiri-mode/cam/tool.js @@ -137,7 +137,7 @@ class Tool { drill_tip_length = this.drillTipLength(), shaft_offset = this.fluteLength(), flute_diameter = this.fluteDiameter(), - shaft_diameter = this.shaftDiameter(), + shaft_diameter = Math.max(flute_diameter, this.shaftDiameter()), max_diameter = Math.max(flute_diameter, shaft_diameter), shaft_pix_float = max_diameter / resolution, shaft_pix_int = Math.round(shaft_pix_float), diff --git a/src/kiri/slice.js b/src/kiri/slice.js index 612bcde6..c858c082 100644 --- a/src/kiri/slice.js +++ b/src/kiri/slice.js @@ -7,11 +7,8 @@ gapp.register("kiri.slice", [], (root, exports) => { const { base, kiri } = root; -const { key, polygons } = base; -const { util } = base; const POLY = base.polygons; -const NOKEY = key.NONE; let tracker; diff --git a/src/kiri/widget.js b/src/kiri/widget.js index 79e95bb2..4500ff2d 100644 --- a/src/kiri/widget.js +++ b/src/kiri/widget.js @@ -472,6 +472,7 @@ class Widget { let rad = deg * (Math.PI / 180); if (rad !== this.track.indexRad) { this.track.indexRad = rad; + this.setModified(); this._updateMeshPosition(); } }