Hello, I’m using the API engine to run a basic CAM outline operation with a single full-depth pass but I’m running into some issues. If i set my zThru setting to anything > 0, it generates correctly but i’m left with an extra pass of the zThru depth. On the other hand, if i set my zThru to 0, it generates an extra top pass.
This is what i’m expecting:
But this is what I’m getting:
I’m attaching the engine code and settings that I’m using below. Anyone have any ideas on what setting might need to change to turn that extra pass off, or does it seem like a bug in the API?
Here is the code I’m running in Kiri:Moto Javascript Engine API :
const STOCK_MARGIN = 10;
const CUT_THROUGH = 0;
new Engine()
.setListener(display_message)
.load("https://raw.githubusercontent.com/alzatin/A-Test-project-6/refs/heads/main/A-Test-project-6.stl")
// should to call widget.setTopZ here ideally
.then(eng => eng.setMode("CAM"))
.then(eng =>{
const bounds = eng.widget.getBoundingBox();
const x = bounds.max.x - bounds.min.x;
const y = bounds.max.y - bounds.min.y;
const z = bounds.max.z - bounds.min.z;
return eng.setStock({
x: x + STOCK_MARGIN,
y: y + STOCK_MARGIN,
z: z + CUT_THROUGH, // stock thickness = part thickness + cut-through
center: {
x: x / 2,
y: y / 2,
z: (z + CUT_THROUGH) / 2, // correct center for full stock thickness
},
})})
.then(eng => eng.moveTo(0, 0, 0))
.then(eng=> eng.setTools([{
id: 1000,
number: 1,
type: "endmill",
name: "end 1/4",
metric: false,
shaft_diam: 0.1,
shaft_len: 1,
flute_diam: 0.1,
flute_len: 2,
taper_tip: 0,
order: 5
}]))
.then(eng => {
const passes = 1;
const speed = 1500;
const bounds = eng.widget.getBoundingBox();
const z = bounds.max.z - bounds.min.z;
const zBottom = -z; //- CUT_THROUGH; // cut through part thickness plus cut-through
const down = Math.abs(zBottom) / passes; // Add small epsilon to avoid floating point errors causing extra pass
console.log("CAM pass debug:", { passes, z, zBottom, down });
return eng.setProcess({
camEaseAngle: 10,
camEaseDown: true,
camZAnchor: "bottom",
camDepthFirst: false,
camZThru: CUT_THROUGH,
camZClearance: 2.5,
camZTop: 0, // top of stock
camZPass: down, // depth per pass
camZBottom: zBottom, // temp hack to get around setTopZ bug
camToolInit: true,
ops: [
{
type: "outline",
tool: 1000,
spindle: speed,
step: 0.4,
steps: 1,
down: down, // correct depth per pass
rate: 635,
plunge: 51,
dogbones: false,
omitvoid: false,
omitthru: true,
outside: false,
inside: false,
wide: false,
top: false,
ov_topz: 0,
ov_botz: 0,
ov_conv: true,
},
/*{
type: "outline",
tool: 1000,
spindle: 13000,
step: 0.4,
steps: 1,
down: down, // correct depth per pass
rate: 635,
plunge: 51,
dogbones: false,
omitvoid: false,
omitthru: false,
outside: false,
inside: false,
wide: false,
top: false,
ov_topz: 0,
ov_botz: 0,
ov_conv: true,
},*/
],
});})
.then(eng => eng.setDevice({
mode: "CAM",
internal: 0,
bedHeight: 2.5,
bedWidth: 678.18,
bedDepth: 1524,
maxHeight: 150,
originCenter: false,
spindleMax: 24000,
gcodePre: [
"G20 ; set units to inches (required)",
"G90 ; absolute position mode (required)"
],
gcodePost: [
"M05 ; spindle off",
"M30 ; program end"
],
gcodeDwell: [
"G4 P{time} ; dwell for {time}ms"
],
gcodeSpindle: [
"M3 S{speed} ; spindle on at {spindle} rpm"
],
gcodeChange: [
"M05 ; spindle off",
"M6 T{tool} ; change tool to '{tool_name}'",
"G37; get tool offset with ETS"
],
gcodeFExt: "nc",
gcodeSpace: true,
gcodeStrip: false,
deviceName: "Tormach.24R",
useLaser: false
}))
.then(eng => eng.slice())
.then(eng => eng.prepare())
.then(eng => eng.export())
.then(display_gcode);



