Area operation on engine thinks toolbit is too big

I’m using an area operation on the Engine API to clear out my flats, but I’m getting unexpected results when there’s a hole or other thru profiles within the same area. However, in the model I’m working with, a 1.6 toolbit size is small enough to clear the flat countersunk area, but it fails to generate that path unless I reduce the bit to 0.6 or below. I’m attaching the engine code below. Any help solving this issue would be appreciated.

const projectUnits = "MM";
const isMetric = projectUnits === "MM";
const toolSize = 1.6;
const CUT_THROUGH = 0; // Default cut-through thickness if not provided
const passes = 2;
const speed = 1500;
const plunge = 635;
const stock_offset = {
  x: 0,
  y: 0,
  z: 0,
};

new Engine()
  .setListener(display_message)
  .load(
    "https://raw.githubusercontent.com/alzatin/A-Test-project-6/refs/heads/main/test_area_1.stl",
  )
  .then((eng) => {
    eng.setMode("CAM");
    eng.moveTo(50, 0, 0);
    eng.setTools([
      {
        id: 1000,
        number: 1,
        type: "endmill",
        name: "endmill",
        metric: isMetric,
        shaft_diam: toolSize,
        shaft_len: 1,
        flute_diam: toolSize,
        flute_len: 2,
        taper_tip: 0,
        order: 5,
      },
    ]);

    const bounds = eng.widget.getBoundingBox();
    const down = (bounds.dim.z + CUT_THROUGH) / passes;
    const stepOver = 0.6;

    // camZAnchor is only for UI
    eng.setOrigin(bounds.mid.x, bounds.mid.y, bounds.max.z);

    // camStockOffset is only reliable in UI
    eng.setStock({
      x: bounds.dim.x + stock_offset.x,
      y: bounds.dim.y + stock_offset.y,
      z: bounds.dim.z + stock_offset.z,
    });

    eng.setProcess({
      camDepthFirst: true,
      camEaseAngle: 40,
      camEaseDown: true,
      camOriginTop: true,
      camOriginCenter: true,
      camStockOffset: false,
      camToolInit: true,
      ops: [
        {
          all: false,
          disabled: false,
          down: down,
          flats: false,
          inside: true,
          leave: 0,
          leavez: 0,
          omitthru: true,
          ov_botz: 0,
          ov_conv: false,
          ov_topz: 0,
          plunge: plunge,
          rate: speed,
          spindle: 13000,
          step: stepOver,
          tool: 1000,
          type: "rough",
          voids: false,
        },
        {
          disabled: false,
          down: 0,
          flats: [2.5],
          leave: 0,
          leavez: 0,
          mode: "clear",
          ov_botz: 0,
          ov_conv: false,
          ov_topz: bounds.max.z,
          plunge: plunge,
          rate: speed,
          shadow: true,
          spindle: 13000,
          step: stepOver,
          tool: 1000,
          type: "area",
        },
        {
          disabled: false,
          dogbones: false,
          down: down,
          inside: false,
          omitthru: false,
          omitvoid: false,
          outside: true,
          ov_botz: 0,
          ov_conv: true,
          ov_topz: 0,
          plunge: plunge,
          rate: speed,
          spindle: 13000,
          step: stepOver,
          steps: 1,
          tool: 1000,
          top: false,
          type: "outline",
          wide: false,
        },
      ],
    });

    const unitsCommand =
      projectUnits === "MM"
        ? "G21 ; set units to MM (required)"
        : "G20 ; set units to inches (required)";

    return eng.setDevice({
      mode: "CAM",
      internal: 0,
      bedHeight: 2.5,
      bedWidth: 678.18,
      bedDepth: 1524,
      maxHeight: 150,
      spindleMax: 24000,
      gcodePre: [unitsCommand, "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((gcode) => {
    localStorage.gcode = gcode;
    display_gcode(gcode);
  });

it would help if you would post your .kmz workspace file

1 Like

Thanks for that suggestion. I haven’t found the UI very useful for testing the engine since they are still so different, but here is a kmz workspace replicating what I’m trying to do on the engine. I purposefully made the bit too big so it skips the interior hole to demonstrate how it also skips the “area clear” operation, even though the bit should fit that space easily. The one thing that is different about what i’m doing on the engine is using “shadow:true” but I’m unsure on how to pass the flats array on the UI so i just selected the surface i’m trying to clear.

workspace_countersink_test_1.kmz (304.3 KB)

The tool paths are somewhat a mystery but the work arounds certainly beat building the G code by had…..here is my mod of your file . Would not work with 1 inch but did work with 1/2 inch….if you want to not tool change just change all operations to 1/2 inch.

workspace_countersink_test_1 MOD.kmz (278.2 KB)

1 Like

sorry I haven’t had a chance to look at it. in the current state, engine debugging takes a great deal of time that I don’t have right now.

1 Like

Hi, thanks for working on a solution for me. I’m looking for specific ops that work on the engine but I really appreciate you taking the time to make these mods!

No problem Stewart. I found a hack to make it work with a different op in the end. Thanks for all the work you’re putting into it.