diff --git a/release.md b/release.md
index 8ae013b9..eac680c7 100644
--- a/release.md
+++ b/release.md
@@ -19,9 +19,10 @@ Full docs @ https://docs.grid.space/projects/kiri-moto
* add option to ignore z bottom in CAM contouring
* add CAM pocket option to ignore interior features (outline only)
* add CAM Z bottom visualization, make it relative to stock instead of part
-* add CAM z bottom inversion option to flip operator
+* add CAM Z bottom inversion option to flip operator
* add CAM custom gcode operator (can be used for pausing, too)
* add optional CAM operation notes (helps with many similar ops)
+* add option to limit CAM trace ops to Z bottom limit (when in use)
* extend url loading of workspaces to all formats
* alert when healing is enabled and non-manifold geometries are detected
* fix thin output start and end point tracking which broke retraction
diff --git a/src/kiri-mode/cam/client.js b/src/kiri-mode/cam/client.js
index 55a58eca..542205d9 100644
--- a/src/kiri-mode/cam/client.js
+++ b/src/kiri-mode/cam/client.js
@@ -1077,6 +1077,7 @@ CAM.init = function(kiri, api) {
down: 'camTraceDown',
rate: 'camTraceSpeed',
plunge: 'camTracePlunge',
+ bottom: 'camTraceBottom',
select: 'camTraceMode'
}).inputs = {
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
@@ -1090,6 +1091,8 @@ CAM.init = function(kiri, api) {
plunge: UC.newInput(LANG.cc_plng_s, {title:LANG.cc_plng_l, convert:UC.toInt, units:true}),
sep: UC.newBlank({class:"pop-sep"}),
select: UC.newSelect(LANG.cc_sele_s, {title:LANG.cc_sele_l}, "select"),
+ sep: UC.newBlank({class:"pop-sep", show:(op,conf) => conf.process.camZBottom}),
+ bottom: UC.newBoolean(LANG.cf_botm_s, undefined, {title:LANG.cf_botm_l, show:(op,conf) => conf.process.camZBottom}),
menu: UC.newRow([
UC.newButton(undefined, func.traceAdd, {icon:''}),
UC.newButton(undefined, func.traceDone, {icon:''}),
diff --git a/src/kiri-mode/cam/ops.js b/src/kiri-mode/cam/ops.js
index 77895459..ce823143 100644
--- a/src/kiri-mode/cam/ops.js
+++ b/src/kiri-mode/cam/ops.js
@@ -772,6 +772,7 @@ class OpTrace extends CamOp {
let { settings, widget, sliceAll, zMax, zTop, zThru, tabs } = state;
let { updateToolDiams, cutTabs, cutPolys, healPolys, color } = state;
let { process, stock } = settings;
+ let { camStockClipTo, camZBottom } = process;
// generate tracing offsets from chosen features
let sliceOut = this.sliceOut = [];
let areas = op.areas[widget.id] || [];
@@ -807,7 +808,7 @@ class OpTrace extends CamOp {
} else {
slice.camLines = [ poly ];
}
- if (process.camStockClipTo && stockRect) {
+ if (camStockClipTo && stockRect) {
slice.camLines = cutPolys([stockRect], slice.camLines, z, true);
}
slice.output()
@@ -929,9 +930,13 @@ class OpTrace extends CamOp {
}
break;
case "clear":
+ const zbo = widget.track.top - widget.track.box.d;
let zmap = {};
for (let poly of polys) {
let z = poly.getZ();
+ if (op.bottom && camZBottom) {
+ z = Math.max(z, camZBottom) - zbo;
+ }
(zmap[z] = zmap[z] || []).push(poly);
}
for (let [zv, polys] of Object.entries(zmap)) {
diff --git a/src/kiri-mode/cam/topo.js b/src/kiri-mode/cam/topo.js
index 5b7f1ac9..1167acb0 100644
--- a/src/kiri-mode/cam/topo.js
+++ b/src/kiri-mode/cam/topo.js
@@ -32,7 +32,7 @@ class Topo {
bounds = widget.getBoundingBox().clone(),
tolerance = contour.tolerance,
flatness = contour.flatness || 0.005,
- bridge = contour.bridging || 10,
+ bridge = contour.bridging || 0,
proc = settings.process,
shadow = tshadow,
minX = bounds.min.x,
diff --git a/src/kiri/conf.js b/src/kiri/conf.js
index a726bec1..a29ad62f 100644
--- a/src/kiri/conf.js
+++ b/src/kiri/conf.js
@@ -500,6 +500,7 @@ const conf = exports({
camTraceSpeed: 250,
camTracePlunge: 200,
camTraceLines: false,
+ camTraceBottom: false,
camPocketSpindle: 1000,
camPocketTool: 1000,
camPocketOver: 0.5,