diff --git a/src/cli/kiri-cam-process.json b/src/cli/kiri-cam-process.json index 7055d629..867aaafc 100644 --- a/src/cli/kiri-cam-process.json +++ b/src/cli/kiri-cam-process.json @@ -111,6 +111,7 @@ "camTraceBottom": false, "cmaPocketOutline": false, "camRegisterThru": 5, + "camRegisterOffset": 10, "camFlatness": 0, "camContourBridge": 10, "camForceZMax": false, diff --git a/src/kiri-mode/cam/client.js b/src/kiri-mode/cam/client.js index 8edaee87..784d736c 100644 --- a/src/kiri-mode/cam/client.js +++ b/src/kiri-mode/cam/client.js @@ -1814,7 +1814,8 @@ CAM.init = function(kiri, api) { dwell: 'camDrillDwell', lift: 'camDrillLift', feed: 'camRegisterSpeed', - thru: 'camRegisterThru' + offset: 'camRegisterOffset', + thru: 'camRegisterThru', }).inputs = { tool: UC.newSelect(LANG.cc_tool, {}, "tools"), axis: UC.newSelect(LANG.cd_axis, {}, "regaxis"), @@ -1828,6 +1829,7 @@ CAM.init = function(kiri, api) { dwell: UC.newInput(LANG.cd_dwll_s, {title:LANG.cd_dwll_l, convert:UC.toFloat, show:() => poppedRec.axis !== '-'}), lift: UC.newInput(LANG.cd_lift_s, {title:LANG.cd_lift_l, convert:UC.toFloat, units:true, show:() => poppedRec.axis !== '-'}), sep: UC.newBlank({class:"pop-sep"}), + offset: UC.newInput(LANG.cd_rego_s, {title:LANG.cd_rego_l, convert:UC.toFloat, units:true, }), thru: UC.newInput(LANG.cd_thru_s, {title:LANG.cd_thru_l, convert:UC.toFloat, units:true}), }; diff --git a/src/kiri-mode/cam/ops.js b/src/kiri-mode/cam/ops.js index 74200790..1b7a687c 100644 --- a/src/kiri-mode/cam/ops.js +++ b/src/kiri-mode/cam/ops.js @@ -1583,112 +1583,108 @@ class OpRegister extends CamOp { updateToolDiams(tool.fluteDiameter()); let { stock } = settings, - tz = widget.track.pos.z, - lx = bounds.min.x, - hx = bounds.max.x, - ly = bounds.min.y, - hy = bounds.max.y, - o3 = tool.fluteDiameter() * 2, - mx = (lx + hx) / 2, - my = (ly + hy) / 2, - mz = op.thru || zThru || 0, - dx = (stock.x - (hx - lx)) / 4, - dy = (stock.y - (hy - ly)) / 4, - dz = stock.z, - points = [], - wo = stock.z - bounds.max.z, - z1 = bounds.max.z + wo + tz, - z2 = tz - mz; + toolZ = widget.track.pos.z, + boundMinX = bounds.min.x, + boundMaxX = bounds.max.x, + boundMinY = bounds.min.y, + boundMaxY = bounds.max.y, + toolOffset = tool.fluteDiameter() * 2, + centerX = (boundMinX + boundMaxX) / 2, + centerY = (boundMinY + boundMaxY) / 2, + cutDepth = op.thru || zThru || 0, + pathPoints = [], + stockToSurfaceOffset = stock.z - bounds.max.z, + startZ = bounds.max.z + stockToSurfaceOffset + toolZ, + endZ = toolZ - cutDepth, + cutOffset = op.offset; if (!(stock.x && stock.y && stock.z)) { return; } - switch (op.axis) { - case "X": + switch (op.axis.toLowerCase()) { case "x": if (op.points == 3) { - points.push(newPoint(lx - dx, my, 0)); - points.push(newPoint(hx + dx, my - o3, 0)); - points.push(newPoint(hx + dx, my + o3, 0)); + pathPoints.push(newPoint(boundMinX - cutOffset, centerY, 0)); + pathPoints.push(newPoint(boundMaxX + cutOffset, centerY - toolOffset, 0)); + pathPoints.push(newPoint(boundMaxX + cutOffset, centerY + toolOffset, 0)); } else { - points.push(newPoint(lx - dx, my, 0)); - points.push(newPoint(hx + dx, my, 0)); + pathPoints.push(newPoint(boundMinX - cutOffset, centerY, 0)); + pathPoints.push(newPoint(boundMaxX + cutOffset, centerY, 0)); } break; - case "Y": case "y": if (op.points == 3) { - points.push(newPoint(mx, ly - dy, 0)); - points.push(newPoint(mx - o3, hy + dy, 0)); - points.push(newPoint(mx + o3, hy + dy, 0)); + pathPoints.push(newPoint(centerX, boundMinY - cutOffset, 0)); + pathPoints.push(newPoint(centerX - toolOffset, boundMaxY + cutOffset, 0)); + pathPoints.push(newPoint(centerX + toolOffset, boundMaxY + cutOffset, 0)); } else { - points.push(newPoint(mx, ly - dy, 0)); - points.push(newPoint(mx, hy + dy, 0)); + pathPoints.push(newPoint(centerX, boundMinY - cutOffset, 0)); + pathPoints.push(newPoint(centerX, boundMaxY + cutOffset, 0)); } break; case "-": - let o2 = o3 / 2, - x0 = lx - dx, - x1 = hx + dx, - y0 = ly - dy - o2, - y1 = hy + dy + o2, - x4 = (x1 - x0 - o2) / 4, - y4 = (y1 - y0 - o2 * 3) / 4, - poly, cp, cz; + let halfOffset = toolOffset / 2, + loopMinX = boundMinX - cutOffset, + loopMaxX = boundMaxX + cutOffset, + loopMinY = boundMinY - cutOffset - halfOffset, + loopMaxY = boundMaxY + cutOffset + halfOffset, + deltaX = (loopMaxX - loopMinX - halfOffset) / 4, + deltaY = (loopMaxY - loopMinY - halfOffset * 3) / 4, + poly, currentPoint, currentZ; function start(z) { - cz = z; - cp = {x:x0 + o2 * 0.5, y:y0 + o2 * 1.5}; - poly = newPolygon().add(cp.x, cp.y, z); + currentZ = z; + currentPoint = { x: loopMinX + halfOffset * 0.5, y: loopMinY + halfOffset * 1.5 }; + poly = newPolygon().add(currentPoint.x, currentPoint.y, z); } function move(dx, dy) { - cp.x += dx; - cp.y += dy; - poly.add(cp.x, cp.y, cz); + currentPoint.x += dx; + currentPoint.y += dy; + poly.add(currentPoint.x, currentPoint.y, currentZ); } - function rept(count, tv, fn) { + function rept(count, step, fn) { while (count-- > 0) { - fn(tv, count === 0); - tv = -tv; + fn(step, count === 0); + step = -step; } } - for (let z of base.util.lerp(z1, z2, op.down)) { + for (let z of base.util.lerp(startZ, endZ, op.down)) { let slice = newSlice(z); addSlices(slice); sliceOut.push(slice); start(z); - rept(4, o2, oy => { + rept(4, halfOffset, oy => { move(0, -oy); - move(x4, 0); + move(deltaX, 0); }); - rept(4, o2, ox => { + rept(4, halfOffset, ox => { move(ox, 0); - move(0, y4); + move(0, deltaY); }); - rept(4, o2, oy => { + rept(4, halfOffset, oy => { move(0, oy); - move(-x4, 0); + move(-deltaX, 0); }); - rept(4, o2, ox => { + rept(4, halfOffset, ox => { move(-ox, 0); - move(0, -y4); + move(0, -deltaY); }); poly.points.pop(); slice.camTrace = { tool: tool.getID(), rate: op.feed, plunge: op.rate }; slice.camLines = [ poly ]; slice.output() - .setLayer("register", {line: color}, false) + .setLayer("register", { line: color }, false) .addPolys(slice.camLines) } break; } - if (points.length) { + if (pathPoints.length) { let slice = newSlice(0,null), polys = []; - points.forEach(point => { + pathPoints.forEach(point => { polys.push(newPolygon() - .append(point.clone().setZ(z1)) - .append(point.clone().setZ(z2))); + .append(point.clone().setZ(startZ)) + .append(point.clone().setZ(endZ))); }); slice.camLines = polys; slice.output() diff --git a/src/kiri/conf.js b/src/kiri/conf.js index 36400e98..90a6ba75 100644 --- a/src/kiri/conf.js +++ b/src/kiri/conf.js @@ -526,6 +526,7 @@ const conf = exports({ camDrillingOn: false, camRegisterSpeed: 1000, camRegisterThru: 5, + camRegisterOffset: 10, camFlipAxis: "X", camFlipOther: "", camLaserEnable: ["M321"], diff --git a/web/kiri/lang/en.js b/web/kiri/lang/en.js index 0e90a13a..a8bc366e 100644 --- a/web/kiri/lang/en.js +++ b/web/kiri/lang/en.js @@ -591,8 +591,6 @@ self.kiri.lang['en-us'] = { cd_dwll_l: ["dwell time","between plunges in","in milliseconds"], cd_lift_s: "drill lift", cd_lift_l: ["lift between plunges","after dwell period","in workspace units","0 to disable"], - cd_regi_s: "register", - cd_regi_l: ["drill registration holes","for double-sided parts","independent of enable","drilling but uses same","tool and settings"], cd_thru_s: "z extend", cd_thru_l: ["extend downward cut through stock","in workspace units"], cd_dtru_s: "drill through", @@ -608,6 +606,13 @@ self.kiri.lang['en-us'] = { cd_sela_s: "Select Matching Diameter", cd_sela_l: ["select all holes that", "match selected tool diameter"], + //CNC Registration + cd_regi_s: "register", + cd_regi_l: ["drill registration holes","for double-sided parts","independent of enable","drilling but uses same","tool and settings"], + cd_rego_s: "part offset", + cd_rego_l: ["offset of hole center","from part bounding box","in workspace units"], + + // CNC FLIP cf_menu: "flip", cf_nvrt_s: "z bottom",