Measures the sew line of a pattern piece: edge lengths, the distance round the outline between two points, seam walking against another piece, and the perimeter and area per size.
How the precision is kept
The calculations are 64-bit sums over the points of the sew line. The curve length and area routines themselves are in curve.js, which is not in this review, so the lengths here are only as exact as that code.
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.
Calls length() on the edge path from curve.js; no rounding or conversion in this function, and 0 when the edge is not found.
addons/apparel/lib/measure.js
lines 29 to 33
CadCraft 0.8.2
export function edgeLength(data, i, size) {
const pts = sewAt(data, size);
const e = edges(pts, true).find((x) => x.start === i);
return e ? length(edgePath(pts, e, true)) : 0;
}
Distance round the outline between two points
64-bit
The forward and backward length along the sew line between two snapped points.
fwd = ((d_b − d_a) mod L + L) mod L; back = (L − fwd) mod L
Joins the edge paths into one path, takes the distance of each point along it, and computes the forward distance with ((db − da) % L + L) % L. The backward distance is (L − fwd) % L. If L is 0 the modulo gives NaN.
addons/apparel/lib/measure.js
lines 35 to 46
CadCraft 0.8.2
/** Lengths round the sew line between two places on it (each snapped to the line). */
export function along(data, a, b, size) {
const pts = sewAt(data, size);
const es = edges(pts, true);
// one continuous path round the outline, starting at the first edge
const path = [];
for (const e of es) { const p = edgePath(pts, e, true); if (path.length) p.shift(); path.push(...p); }
const L = length(path);
const da = nearest(path, a).d, db = nearest(path, b).d;
const fwd = ((db - da) % L + L) % L;
return { fwd, back: (L - fwd) % L, total: L };
}
Seam walking
64-bit
The lengths of two edges, their difference and the notch offsets along the seam.
diff = lenB − lenA; off = bₖ − aₖ
Notch distances are clamped to the edge length with Math.min, the second piece is walked from its end by lenB − d when reversed, and pairs are matched in sorted order. Differences are plain 64-bit subtractions.
addons/apparel/lib/measure.js
lines 48 to 57
CadCraft 0.8.2
/** Seam walking: edge ia of A against edge ib of B. */
export function walk(A, ia, B, ib, { size = null, reverse = true } = {}) {
const lenA = edgeLength(A, ia, size), lenB = edgeLength(B, ib, size);
const notchA = (A.notches || []).filter((n) => n.i === ia).map((n) => Math.min(n.d, lenA)).sort((x, y) => x - y);
let notchB = (B.notches || []).filter((n) => n.i === ib).map((n) => Math.min(n.d, lenB));
notchB = (reverse ? notchB.map((d) => lenB - d) : notchB).sort((x, y) => x - y);
const pairs = [];
for (let k = 0; k < Math.min(notchA.length, notchB.length); k++) pairs.push({ a: notchA[k], b: notchB[k], off: notchB[k] - notchA[k] });
return { lenA, lenB, diff: lenB - lenA, pairs, onlyA: notchA.slice(pairs.length), onlyB: notchB.slice(pairs.length) };
}
Perimeter and area per size
64-bit
The sew and cut perimeter and area of each size of a piece.
area = |Σ shoelace|
Uses length() and area() from curve.js on the sew line and the cut line; areas are taken as absolute values. The cut line comes from cutLine in seam.js when seam allowance is set, otherwise it is the sew line.
addons/apparel/lib/measure.js
lines 59 to 73
CadCraft 0.8.2
/** One row per size (just one, the base, when the piece has no size range). */
export function pieceRows(data) {
const sizes = data.sizes ? data.sizes.list : [data.size || ''];
return sizes.map((size) => {
const d = data.sizes ? gradeData(data, size) : data;
const pts = ptsOf(d.pts);
const es = edges(pts, true);
const sp = [];
for (const e of es) { const p = edgePath(pts, e, true); if (sp.length) p.shift(); sp.push(...p); }
const hasSa = !!d.sa && es.some((e) => widthOf(d.sa, e.start) > 0);
const cut = hasSa ? cutLine(pts, d.sa) : sp.slice(0, -1);
const closedLen = (q) => length([...q, q[0]]);
return { size, sewPerimeter: length(sp), cutPerimeter: hasSa ? closedLen(cut) : length(sp), sewArea: Math.abs(area(sp)), cutArea: Math.abs(area(cut)) };
});
}
In detail
Method
Lengths are taken along the edge path; distance round the outline is a modulo of the total length; notch offsets are plain differences along the seam.
Number types
64-bit numbers.
Tolerances
None in this file.
Limits
along takes the result modulo the total length L, so a zero-length outline gives NaN; this is not guarded.
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.