Unit factors
ExactThe 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.
const SCALE = { mm: 1, cm: 10, m: 1000, in: 25.4, '': 1 };
Resources Numerical accuracy Calculation policy
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.
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.
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.
Tests tools/partcraft-test/test-cam-sheets.mjs
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.
const SCALE = { mm: 1, cm: 10, m: 1000, in: 25.4, '': 1 };
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.
/** 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;
}
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.
// 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 };
};
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.
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 } : {}) }));
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.