Resources Numerical accuracy Calculation policy

G-code and toolpath exports

Writes a program's moves as G-code, CSV or JSON.

How the precision is kept

G-code coordinates are written in millimeters with 3 decimals, as the file's header states, and CSV values with 6 decimals; the JSON export writes the 64-bit numbers as they are. The G-code that is actually produced comes from text post definitions run in cam-postdef.js; the function in this file is the reference those are tested against.

Calculations under this policy

4 calculations in 1 source file. The code is read from the released app when this page loads. It is the calculation people run, not a copy kept for this page.

cam-post.js PartCraft 0.8.1 64-bit 4 calculations Reviewed

Tests tools/partcraft-test/test-cam-post.mjs

Arc center words I and J

64-bit

The arc center written relative to the arc's start point.

I = round₃(c_x − round₃(start_x)); J = round₃(c_y − round₃(start_y))

The offset is taken from the start point as it was written (already rounded to 0.001) to the unrounded center, then rounded again. The code comment says this keeps the end radius within 1 µm. This function is the reference for the text posts; the posts that run are in cam-postdef.js.

  • cam-post.js
  • lines 96 to 99
  • PartCraft 0.8.1
// I J from the start as written (rounded), to the exact centre, rounded: the end radius stays within 1 µm
const i = q(m.c[0] - q(st.x)), j = q(m.c[1] - q(st.y));
const fw = q(m.f) !== st.f ? ' F' + F(m.f) : '';
line('G' + g + w + ' I' + F(i) + ' J' + F(j) + fw);

Axis words

64-bit

Writes X, Y and Z only when they change at the output resolution.

write an axis when round₃(new) ≠ round₃(last written)

Values are compared after rounding to 0.001 mm, so a move smaller than the output resolution in an axis writes no word for it. The last position kept is the unrounded one.

  • cam-post.js
  • lines 72 to 79
  • PartCraft 0.8.1
const axes = (p, force = false) => {
  let w = '';
  if (force || st.x === null || q(p[0]) !== q(st.x)) w += ' X' + F(p[0]);
  if (force || st.y === null || q(p[1]) !== q(st.y)) w += ' Y' + F(p[1]);
  if (force || st.z === null || q(p[2]) !== q(st.z)) w += ' Z' + F(p[2]);
  return w;
};
const set = (p) => { st.x = p[0]; st.y = p[1]; st.z = p[2]; };

Toolpath as CSV

64-bit

Writes every segment's start, end, arc center, sweep and feed as text.

value = toFixed(6); sweep in degrees = sweep × 180 ÷ π

Every number is rounded to 6 decimals (1e-6 mm, or 1e-6 degree for the sweep). An arc's sweep in the file is therefore the rounded degree value, not the radians used inside.

  • cam-post.js
  • lines 172 to 178
  • PartCraft 0.8.1
/** Every segment as CSV: op, kind, start, end, arc centre and sweep, feed (mm, mm/min). */
export function toolpathCsv(program) {
  const rows = ['op,kind,x0,y0,z0,x1,y1,z1,cx,cy,sweep_deg,feed'];
  const f = (v) => (v === undefined || v === null ? '' : String(+v.toFixed(6)));
  for (const s of segments(program.paths)) rows.push([s.op, s.k, ...s.a.map(f), ...s.b.map(f), s.c ? f(s.c[0]) : '', s.c ? f(s.c[1]) : '', s.sw !== undefined ? f((s.sw * 180) / Math.PI) : '', f(s.f)].join(','));
  return rows.join('\n') + '\n';
}

Toolpath as JSON

64-bit

Writes the setup, tools and every operation's moves.

JSON.stringify of the moves

Numbers are written by JSON.stringify, which uses the shortest text that reads back to the same 64-bit number, so this export does not round.

  • cam-post.js
  • lines 179 to 186
  • PartCraft 0.8.1
/** The program as JSON: setup, tools, and each operation's moves (canned cycles kept as cycles). */
export function toolpathJson(program) {
  return JSON.stringify({
    format: 'partcraft-toolpath', version: 1, units: 'mm', setup: program.setup,
    stock: program.model.stock, tools: program.tools,
    ops: program.paths.map((p) => ({ id: p.op.id, name: p.op.name, type: p.op.type, tool: p.tool ? p.tool.id : null, rpm: p.speeds ? p.speeds.rpm : null, error: p.error || null, moves: p.moves })),
  });
}

In detail

Method
Modal G-code: an axis word is written only when its rounded value changes. Arc centers are written as I and J relative to the start point as it was written.
Number types
64-bit numbers rounded to 0.001 for G-code (helpers in cam-fmt.js) and to 0.000001 for CSV; unrounded in JSON.
Tolerances
G-code resolution 0.001 mm. CSV resolution 1e-6.
Limits
Each coordinate is rounded on its own, so an arc's written end point can be up to about a micrometer off the circle given by its written center.

Approach: 64-bit, stated limit

The arithmetic is 64-bit, but the method or the data sets the accuracy: a solver tolerance, a mesh, a step size, a datum shift, a table. The limit is stated where the result is shown.

Every policy that takes this approach