Scales a body by a factor per axis about a chosen point, including a shrinkage allowance given as a percent.
How the precision is kept
The factors are 64-bit numbers taken from the feature, or from the shrinkage percent through shrinkFactor in scale-factors.js. The scale is stored as a 4 × 4 matrix whose translation is a × (1 − f), and each point is then one product and one addition per axis.
Calculations under this policy
3 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.
The three factors a scale feature multiplies by, from the feature or from its shrinkage allowance.
With a shrinkage allowance each factor comes from shrinkFactor (scale-factors.js) and falls back to 1 when that returns nothing; otherwise the stored factors are copied unchanged.
print-features.js
lines 35 to 39
PartCraft 0.8.1
export function scaleFactors(f) {
const s = f.shrink;
if (s && Array.isArray(s.pct)) return s.pct.map((p) => shrinkFactor(p, s.mode) ?? 1);
return f.factors.slice();
}
Scale matrix about a fixed point
64-bit
The 4 × 4 matrix that scales a body about the center, minimum corner, base center or origin of its box.
a = (min + max) ÷ 2 (center); translation = a × (1 − f)
The center is one addition and a halving per axis. The translation multiplies a by 1 − f; for a factor between 0.5 and 2 that subtraction is exact in binary floating point, so only the product rounds.
One 64-bit product and one addition per coordinate, using only the diagonal and the translation of the matrix. The box is the plain minimum and maximum of the corners.
print-features.js
lines 50 to 56
PartCraft 0.8.1
export function scaleTris(tris, f) {
const min = [Infinity, Infinity, Infinity], max = [-Infinity, -Infinity, -Infinity];
for (const tr of tris) for (const p of corners(tr)) for (let i = 0; i < 3; i++) { if (p[i] < min[i]) min[i] = p[i]; if (p[i] > max[i]) max[i] = p[i]; }
const m = scaleMatrix({ min, max }, f);
const at = (p) => [m[0] * p[0] + m[12], m[5] * p[1] + m[13], m[10] * p[2] + m[14]];
return tris.map((tr) => (Array.isArray(tr) ? tr.map(at) : { ...tr, p: tr.p.map(at) }));
}
In detail
Method
x′ = f·(x − a) + a written as x′ = f·x + a·(1 − f); a is the box center, its minimum corner, the center of its base or the origin.
Number types
64-bit numbers in plain arrays.
Tolerances
A factor read from a file is accepted between 1e-6 and 1e6; a shrinkage percent from 0 to under 50.
Limits
The fixed point is not reproduced bit for bit: a point at a becomes f·a + a·(1 − f), two rounded products added.
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.