Documentation
Setups and saved programs
Capture the stock, work frame, cutter assignments, ordered operations, and source evidence used to produce a program.
A setup is manufacturing context
A manufacturing setup defines how a part sits relative to stock, fixtures, and tools. cam.ManufacturingSetup records an identifier, revision, rigid work frame, world-coordinate stock and fixture envelopes, and tool assemblies. The native kernel accepts a CAD snapshot and resources and produces ordered operation results and one posted program.
Saved application programs use CamProgramDocument, the portable document also stored in Toolpath.data. This contract retains NC and its program representation together with the settings, stock, and drawing snapshot needed to reopen the workspace. Optional operations preserve separate operation identities; optional kernel data retains native source evidence.
Portable document contract
A document identifies itself with format: "cadcamfun-cam" and version: 1. Required fields are gcode, program, generator settings, printer extras, stock, and a free-form drawing snapshot. Optional fields are operations, kernelArtifact, and kernelRequest.
Each stored operation has a unique id, name, gcode, and program, with optional tool, settings, and source element identifiers. Keeping its NC and identity makes an operation round-trip independently of its display label.
Operation order and composition
combineCamOperations preserves operation order. It namespaces toolpath identifiers with the operation identifier, uses an explicit operation tool when supplied, and prefixes display names when there is more than one operation. The combined program takes units and work offset from the first operation.
For a single operation, combined NC is the original text. For multiple operations, the helper joins their existing NC sections with operation comments. This helper does not re-post all sections into a single controller program. The native kernel is the route that generates ordered operations and emits one integrated program.
Callers composing pre-generated sections must ensure compatible units, work offsets, tool numbering, headers, and program endings. A successful document composition proves ordering and consistency with its stored sections; it does not add machine-clearance evidence.
Generate and save
- Capture the drawing elements and stock to be machined. Choose a material, machine, tools, work offset, and quality controls.
- Call
POST /api/toolpaths/manufacturewithschemaVersion: 1, job identity, name, and the captured elements. Supply operations explicitly in machining order or allow the kernel to plan them. - Inspect the returned result, issues, individual claims, and
release. An artifact can be a preview or blocked; receiving a result does not imply verified output. - Build a
CamProgramDocumentwhose G-code, program, artifact, and captured request describe the same result. Save it through a toolpath create or update endpoint, together with that G-code.
The manufacture endpoint evaluates the supplied snapshot without writing the drawing or creating a toolpath. Generator /generate is a separate settings-driven route and can also supply NC for a portable document.
Persistence validation
The sidecar recognizes portable documents by their format and decodes the full schema before saving. The document's G-code must match the toolpath row's G-code. Operation identifiers must be unique, and their ordered composition must reproduce the saved text. The sidecar reparses operation NC to reconstruct program moves rather than trusting client-provided move data.
For a new native artifact with a captured request, the sidecar reruns that request and compares the resulting artifact, program, and original NC. Failed or blocked results, altered artifacts, and mismatched text are rejected. A newly supplied artifact without its captured request is removed unless it is an unchanged artifact already retained on the row.
When the supplied source elements and stock match the associated stored drawing, the service computes a drawing revision digest. Clients cannot provide a trusted sourceRevision or arbitrary verification claim. The saved revision is derived by the service or retained only for the same existing artifact.
Editing NC and retaining evidence
An update can replace NC while sending the unchanged prior portable document. The service recognizes that case, rebuilds the parsed program from the new text, and removes operations and native source evidence that no longer match. An inconsistent new document is rejected instead of silently combining unrelated programs.
Ordinary free-form toolpath data remains supported. A change to NC removes stale native artifact metadata where it no longer matches. Client-supplied verification and response fields do not become trusted native evidence.
The validation implementation is apps/sidecar/src/services/cam-program.ts; runKernelRequest, prepareCamProgramData, and drawingRevision share the same request adapter and identity logic used by generation and saves.
A saved program can contain subprograms generated from repeated toolpaths. The rules for which toolpaths may share a subprogram are described on the CAM page.
Rigid work frames
A WorkFrame has an origin and X/Y/Z axes. validateWorkFrame requires finite coordinates, unit axes, pairwise orthogonality, and right-handed orientation within its numerical tolerance. workToWorld applies the frame; worldToWork projects back. Invalid frames, invalid points, and numeric overflow produce a range error.
validateSetup also checks a non-empty setup identifier, non-negative safe-integer revision, positive-volume finite envelopes, unique fixture/tool identifiers, and positive finite cutter and holder dimensions. Cutting length must not exceed stickout. Validation returns field-specific issues so the caller can identify the value that needs correction.
Indexed table machining
cam/indexing.ts solves indexed orientations for table-AC and table-BC layouts. It rotates the selected work-plane normal onto machine +Z, respects rotary limits, and prefers the smaller reachable tilt. Program points pass through the work frame and table rotation about the machine pivot.
This adapter models table indexing with a fixed tool axis. Tilting heads, controller tilted-plane cycles, and simultaneous five-axis motion are separate capabilities. Rotary positions are degrees; frame axes remain unit vectors.
Shared setup types
ManufacturingSetup, WorkFrame, ToolAssembly, validateSetup, validateWorkFrame, workToWorld, and worldToWork are exported through cam. Portable operation and document schemas are exported from @cadcamfun/api, which makes them available to both sidecar persistence and desktop restore logic.
Reopening in the desktop
saved-program.ts captures current settings, stock, drawing, and the exact NC being saved. It retains a kernel artifact only when its NC and hash match those bytes. On restore, it checks the stored artifact and release, restores compatible operation results, resets replay verification, loads the editor, and restores generator and stock controls from the snapshot.
When only ordinary G-code is available, the desktop parses it for display. Opening text successfully does not recreate a missing generation request or upgrade the program's evidence level.
Keep source and result together
Regenerate after changing geometry, stock, tool dimensions, work frame, machine, material, or operation order. Preserve source snapshots for reproducibility, and treat a changed NC file as new output requiring its own analysis. Source revision checks and artifact replay prevent an earlier result from being presented as evidence for different program bytes.
Evaluate a captured setup
The snapshot adapter is the common boundary for the native manufacture request. This self-contained example captures a polymer blank and a slightly larger stock box, then returns the artifact's actual release level. It writes neither a drawing nor a toolpath.
import { cam } from "@cadcamfun/core"
const prepared = cam.kernel.jobOfSnapshot({
schemaVersion: 1, id: "blank-job", name: "Blank", material: "POM",
elements: [{ id: "blank", type: "cube", x: 20, y: 20, z: 5,
width: 40, height: 40, depth: 10 }],
stock: { x: 20, y: 20, width: 44, height: 44, depth: 11 },
resolution: 0.5
})
if (prepared.status === "failed") throw new Error(JSON.stringify(prepared.issues))
const result = cam.kernel.runJob(prepared.value)
if (result.status === "failed") throw new Error(JSON.stringify(result.issues))
console.log(result.value.release)
console.log(result.value.claims)
console.log(result.value.identity.nc) The cube position is its center; its bottom is Z0. Snapshot stock X/Y are its center and width/height are full dimensions. The adapter places the stock bottom at the selected part's lowest Z, then adds the declared depth. Kernel work origin defaults to stock-center at the stock top; stock-corner selects its minimum X/Y and top Z instead.
Source: packages/core/src/cam/kernel/snapshot.ts, execute.ts, and kernel.test.ts.
Snapshot options and bounds
The HTTP native request requires 1–2,000 elements, a version of 1, non-empty job ID/name, and a material name up to 80 characters. It accepts up to 500 explicit operations and, when supplied, 1–200 cutters. Omitting operations invokes the planner; an explicit empty operation list is not a request to invent operations.
finishAllowance accepts 0–5 mm; scallop is positive and at most 1 mm; deburr is positive and at most 5 mm. Native defaults use the material's finish allowance, 0.01 mm scallop, and 0.01 mm path tolerance. Replay resolution can be supplied separately. Optional subprograms: true requests translated repeat emission only where the selected dialect supports it.
A snapshot machine field names a registered preset. The lower-level ManufacturingJob can carry a full machine record, including explicit travel and table geometry; the public snapshot machine string does not itself accept an arbitrary machine record.
Source: packages/api/src/cam-kernel.ts, ai-cam.ts, and packages/core/src/cam/kernel/contracts.ts.
Resolve rejected saves
| Response message | Cause and remedy |
|---|---|
| Invalid CADCAMFUN toolpath document | The recognized portable format failed its schema. Preserve all required settings, printer, stock, drawing, program, and G-code fields. |
| Toolpath document and G-code must contain the same program | The row NC and new document NC differ. Rebuild the snapshot from the exact bytes being saved. |
| Saved operations must have unique IDs and compose the stored G-code in order | Operation identity or ordering no longer reproduces the document. Recompose after editing, reordering, or deleting operations. |
| The saved kernel artifact does not match its source request and original NC | Replaying the captured request failed, returned blocked output, or differed from the claimed artifact/program/NC. Regenerate rather than editing the evidence fields. |
A valid native artifact may be retained without a source drawing revision when its source selection/stock does not match the associated stored drawing. That absence does not imply the saved NC was regenerated against the current drawing. Read the drawing revision and source snapshot independently when reporting freshness.
Source: apps/sidecar/src/services/cam-program.ts and apps/sidecar/test/cam-program.test.ts.
See a native job in 3D
| Op | Strategy | Tool | Cut length | Time | Removed |
|---|---|---|---|---|---|
| Face stock top | face | facemill-50 | 334.0 mm | 12.4 s | 1936 mm³ |
| 3D adaptive roughing | surface | flat-16 | 472.2 mm | 5.3 s | 3360 mm³ |
| 3D steep and shallow finishing | surface | ball-10 | 5660.6 mm | 113.4 s | 0 mm³ |
Machine vmc-standard (Vertical machining centre (BT40, 12 000 rpm, 11 kW), post fanuc), material pom-c (Acetal POM-C (Delrin)). Stock volume 21296 mm³, final 16000 mm³, equal to the part volume, so remaining volume is 0. Estimated cycle time 149 s. Release: verified-program. The NC is 3071 lines long.
| Claim | Status |
|---|---|
cutting-data | passed |
machine-limits | passed |
operations-complete | passed |
no-rapid-in-stock | passed |
holder-clearance | passed |
no-gouge | passed |
material-removed | passed |
nc-replay | passed |
machine-travel | unsupported |
machine-clearance | passed |
machine-travel is unsupported here because the preset has no explicit travel envelope to check against. An unsupported claim is not a failure, but it is also not evidence; the verified-program release covers the claims that passed.
Work frame math, worked through
import { cam } from "@cadcamfun/core"
const frame = cam.frameFromNormal({ x: 40, y: 0, z: 10 }, { x: 1, y: 0, z: 1 })
// xAxis (0.707, 0, -0.707) yAxis (0, 1, 0) zAxis (0.707, 0, 0.707)
cam.validateWorkFrame(frame) // []
const world = cam.workToWorld(frame, { x: 10, y: 5, z: 0 }) // (47.071, 5, 2.929)
cam.worldToWork(frame, world) // (10, 5, 0)
cam.validateWorkFrame({ origin: { x: 0, y: 0, z: 0 },
xAxis: { x: 1, y: 0, z: 0 }, yAxis: { x: 0, y: 0, z: 1 }, zAxis: { x: 0, y: 1, z: 0 } })
// [{ field: "frame", message: "Work frame axes must be orthonormal and right-handed" }] frameFromNormal takes the normal as Z and projects the X hint (world X by default) onto the plane. When the hint is parallel to the normal it picks another perpendicular. Y is always Z × X, so the result is right-handed by construction.
Rotary solutions for common faces
anglesFor(normal, layout, limits) returns every way the table can bring a part direction to machine +Z, smallest tilt first, with the tilt inside the limits (default −120° to 120°). C is wrapped into (−180°, 180°]. These are real outputs:
| Part normal | table-AC | table-BC |
|---|---|---|
| (1, 0, 1), 45° side | A45 C90, then A−45 C−90 | B−45 C0, then B45 C180 |
| (1, 0, 0), +X face | A90 C90, then A−90 C−90 | B−90 C0, then B90 C180 |
| (0, −1, 0), front face | A90 C180, then A−90 C0 | B−90 C90, then B90 C−90 |
| (0, 0, −1), underside | none (empty array) | none (empty array) |
An underside needs a 180° tilt, outside the default limits, so the list is empty and indexToolpath throws "The machine's rotary axes cannot reach this work plane within their limits". Machine the underside in a second setup instead.
const [angles] = cam.anglesFor({ x: 1, y: 0, z: 1 }, "table-BC") // { b: -45, c: 0 }
cam.partToMachine({ x: 40, y: 0, z: 10 }, angles, "table-BC", { x: 0, y: 0, z: 0 })
// (21.213, 0, 35.355): the origin rotated -45° about Y around the pivot Setup validation messages
cam.validateSetup({
id: "", revision: -1, frame,
stock: { min: { x: 0, y: 0, z: 0 }, max: { x: 0, y: 10, z: 10 } },
fixtures: [],
tools: [{ toolId: "t", cuttingDiameter: 6, cuttingLength: 30, stickout: 20,
holderDiameter: 32, holderLength: 40 }],
}) | field | message |
|---|---|
id | Setup ID must not be empty |
revision | Setup revision must be a non-negative safe integer |
stock | Envelope must have finite coordinates and positive volume |
tools.t | Cutting length must not exceed stickout |
Issues are returned, not thrown, and all are reported in one pass, so a form can mark every bad field together.