Resources Numerical accuracy Calculation policy

Nested sheets from DXF to toolpaths

Reads nested sheets and parts from a DXF file, converts them to millimeters and to lines and arcs, and hands them to the contour toolpath.

How the precision is kept

Unit factors are exact (25.4 for inches, 10 and 1000 for centimeters and meters). Bulged polyline segments become true arcs in closed form. Coordinates are shifted to each sheet's corner and scaled in 64-bit. The extent of an outline with arcs is found by sampling the arcs at 0.05 mm chord tolerance.

Open item. Use the exact arc box from cam-offset.js (boxOf) for outline extents instead of sampling at 0.05.

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-sheets.js PartCraft 0.8.1 64-bit 4 calculations Reviewed

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

Unit factors

Exact

The factor from the file's units to millimeters.

mm 1; cm 10; m 1000; in 25.4

25.4 is the exact definition of the inch in millimeters. The other factors are whole numbers.

  • cam-sheets.js
  • line 31
  • PartCraft 0.8.1
const SCALE = { mm: 1, cm: 10, m: 1000, in: 25.4, '': 1 };

Bulged segments to arcs

64-bit

Turns a polyline with bulges into lines and true arcs.

r = (d ÷ 2)(1 + b²) ÷ (2|b|); offset = (d ÷ 2)(1 − b²) ÷ (2b); sweep = 4 atan(b)

Closed form from the chord and the bulge. For a very small bulge the radius and the center offset are both very large and the arc is nearly straight; bulges below 1e-12 are written as lines. The arc keeps the polyline's own points as its ends.

  • cam-sheets.js
  • lines 33 to 51
  • PartCraft 0.8.1
/** A closed polyline with bulges → arcs and lines (counter-clockwise when the polyline is). */
export function loopToPrims(pts) {
  const n = pts.length, out = [];
  for (let i = 0; i < n; i++) {
    const a = pts[i], b = pts[(i + 1) % n];
    const s = [a.x, a.y], e = [b.x, b.y];
    const d = Math.hypot(e[0] - s[0], e[1] - s[1]);
    if (d < 1e-9) continue;
    const bu = a.b || 0;
    if (Math.abs(bu) < 1e-12) { out.push(O.line(s, e)); continue; }
    const half = d / 2, r = half * (1 + bu * bu) / (2 * Math.abs(bu));
    const off = half * (1 - bu * bu) / (2 * bu);               // signed distance from the chord's middle to the centre (left of s → e when b > 0)
    const mx = (s[0] + e[0]) / 2, my = (s[1] + e[1]) / 2;
    const nx = -(e[1] - s[1]) / d, ny = (e[0] - s[0]) / d;
    const c = [mx + nx * off, my + ny * off];
    out.push(O.arc(c, r, Math.atan2(s[1] - c[1], s[0] - c[0]), 4 * Math.atan(bu), s, e));
  }
  return out;
}

Extent of an outline

64-bit

The box round a sheet or a part outline, used for sheet size and for placing parts on sheets.

min and max over points sampled along each piece at 0.05 chord tolerance

Arcs are sampled, so where an arc bulges past its end points the box can fall short of the true extreme by up to the 0.05 tolerance. Lines contribute their exact ends.

  • cam-sheets.js
  • lines 55 to 62
  • PartCraft 0.8.1
// a bulged segment can swing outside its end points: sample the arcs for the box
const bboxExact = (loops) => {
  let x0 = Infinity, y0 = Infinity, x1 = -Infinity, y1 = -Infinity;
  for (const l of loops) for (const p of loopToPrims(l)) {
    for (const q of O.samplePrim(p, 0.05)) { x0 = Math.min(x0, q[0]); y0 = Math.min(y0, q[1]); x1 = Math.max(x1, q[0]); y1 = Math.max(y1, q[1]); }
  }
  return { x0, y0, x1, y1 };
};

Part coordinates on its sheet

64-bit

Moves a part's points so its sheet's lower left corner is the origin, in millimeters.

x′ = (x − sheet x₀) × k; y′ = (y − sheet y₀) × k

One subtraction and one multiplication per coordinate. The sheet corner is the sampled box's minimum; bulges are carried over unchanged.

  • cam-sheets.js
  • line 102
  • PartCraft 0.8.1
const move = (l) => l.map((q) => ({ x: (q.x - s.box.x0) * k, y: (q.y - s.box.y0) * k, ...(q.b ? { b: q.b } : {}) }));

In detail

Method
DXF bulge b = tan(sweep ÷ 4): radius = (chord ÷ 2)(1 + b²) ÷ (2|b|); center offset from the chord's middle = (chord ÷ 2)(1 − b²) ÷ (2b); sweep = 4 atan(b).
Number types
64-bit numbers.
Tolerances
Segments shorter than 1e-9 are skipped; a bulge below 1e-12 is a straight line. A part belongs to a sheet when its box center is inside the sheet's box within 1e-6 (file units).
Limits
The function named bboxExact samples arcs, so the box of an outline with arcs can be up to 0.05 mm (file units) inside the true extent. Sheets drawn as plain rectangles are not affected.

Approach: 64-bit, direct

Every value is a 64-bit number from input to result. Formulas are closed form or a direct solve, and every comparison uses a stated tolerance.

Every policy that takes this approach