Turns a length in millimeters, an area or a volume into text in the display unit a person picked.
How the precision is kept
Values stay in millimeters (or SI) inside the app; these functions only write text. The inch is 25.4 mm, the legal definition, and the foot is 12 × 25.4. Each value is divided once by its factor and then rounded to a fixed number of decimals for the unit, or to the nearest 1/16 inch. The rounding is the limit of what the text shows, not of the stored value.
Calculations under this policy
9 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.
25.4 is the exact definition of the inch. The length is rounded once, to whole sixteenths, and everything after that is whole-number arithmetic, so 11 15/16 inches plus rounding rolls over to 1 foot correctly. Decimal units divide once and round with toFixed; a result of −0 is written as 0.
display-units.js
lines 23 to 43
BimCraft 0.8.1
/** Millimetres as text. `ftin`: feet-inches to 1/16" (fractions reduced); `mm`: whole millimetres (0.1 below 10). */
export function fmtLen(mm, units = 'ftin', { unit = false } = {}) {
if (!Number.isFinite(mm)) return '';
if (units !== 'ftin' && FACTOR[units]) {
const value = mm / FACTOR[units];
const digits = units === 'mm' ? (Math.abs(value) < 10 ? 1 : 0) : units === 'in' ? 3 : 2;
const rounded = Number(value.toFixed(digits));
return (Object.is(rounded, -0) ? 0 : rounded) + (unit ? ' ' + (units === 'ftdec' ? 'ft' : units) : '');
}
const neg = mm < 0;
let sixteenths = Math.round(Math.abs(mm) / INCH * 16);
const ft = Math.floor(sixteenths / 192);
sixteenths -= ft * 192;
const inch = Math.floor(sixteenths / 16);
let frac = sixteenths - inch * 16, den = 16;
while (frac && frac % 2 === 0) { frac /= 2; den /= 2; }
const whole = ft || inch || !frac; // 10'-0 1/4", but 1/4" alone
const inText = (whole ? String(inch) : '') + (frac ? (whole ? ' ' : '') + frac + '/' + den : '') + '"';
const s = ft ? ft + "'-" + inText : inText;
return (neg && sixteenths + ft ? '-' : '') + s;
}
Unit factors
64-bit
How many millimeters, square millimeters and cubic millimeters one display unit is.
in = 25.4 mm; ft = 12 × 25.4 mm; cm = 10 mm; m = 1000 mm
The inch is written from its definition, 25.4 mm, and the foot is 12 times that, computed in 64-bit when the file loads. The metric factors are powers of ten.
A coordinate in millimeters as a number in the display unit, with a fixed count of decimals.
value = mm ÷ factor, to 1 (mm), 2 (cm, in) or 3 (m, ft) decimals
One division and one toFixed. Feet and inches show decimal feet here. The decimals are fixed per unit, so a state-plane coordinate in feet shows to 0.001 ft.
display-units.js
lines 48 to 55
BimCraft 0.8.1
/** The number of fmtCoord alone (the unit goes beside it): decimal feet for feet-inches. */
export function coordNumber(mm, units = 'ftin') {
if (!Number.isFinite(mm)) return '';
const u = units === 'ftin' ? 'ftdec' : units;
const digits = { mm: 1, cm: 2, m: 3, in: 2, ftdec: 3 }[u] ?? 3;
const rounded = Number(((mm) / (FACTOR[u] || 1)).toFixed(digits));
return (Object.is(rounded, -0) ? 0 : rounded).toLocaleString('en-US', { minimumFractionDigits: digits, maximumFractionDigits: digits, useGrouping: false });
}
A small length to three figures
64-bit
A tolerance or a scale per pixel as text with three significant figures.
value = mm ÷ factor, toPrecision(3)
One division, then rounded to three significant figures for the text. Feet and inches show decimal inches.
display-units.js
lines 58 to 64
BimCraft 0.8.1
/** A small length (a scale in length per pixel, a tolerance) with three significant figures and its unit: feet-inches shows decimal inches. */
export function fmtFine(mm, units = 'ftin') {
if (!Number.isFinite(mm)) return '';
const u = units === 'ftin' ? 'in' : units;
const v = Number((mm / (FACTOR[u] || 1)).toPrecision(3));
return (Object.is(v, -0) ? 0 : v) + ' ' + unitMark(u);
}
An area or a volume as text
64-bit
Square or cubic millimeters as text in the matching square or cubic display unit.
value = v ÷ factor, to the unit's decimals; in² = 25.4² mm²; ft² = (12 × 25.4)² mm²; ft³ = (12 × 25.4)³ mm³
One division by the squared or cubed factor and one toFixed. The squared and cubed inch and foot factors are computed from 25.4 in 64-bit when the file loads, so each carries the rounding of its multiplications. Thousands separators are added only from 10,000 up.
What calculations give in SI, handed to the same formatters.
mm = m × 1000; mm² = m² × 10⁶; mm³ = m³ × 10⁹
Each value is multiplied by a power of ten and then divided by the unit factor, two rounded steps instead of one. Both are far below the decimals the text shows.
Rewrites plain "N mm" and "N m" inside a message into the display unit.
The number is read back from the text of the message, so it is the value as the message printed it. A message that already carries a foot or inch mark is left as written, and m², m³ and rates are not touched.
display-units.js
lines 86 to 94
BimCraft 0.8.1
/**
* A refusal's limits ("at least 10 mm thick", "up to 12 m") in the display unit. Only plain "N mm" / "N m" are rewritten
* (never m² m³ m/s), and a message that already gives feet-inches or inches (3'-4", 4") is left as written.
*/
export function localizeLengths(text, units = 'ftin') {
const s = String(text ?? '');
if (/\d\s?['"]/.test(s)) return s;
return s.replace(/(\d+(?:\.\d+)?) ?(mm|m)\b(?![²³\/])/g, (all, n, u) => lenMark(Number(n) * (u === 'm' ? 1000 : 1), units));
}
Quantities inside a sentence
64-bit
Rewrites lengths, areas and volumes inside a calculation's sentence into the display unit.
The number is parsed from text that was already rounded when the sentence was written, then converted and rounded again. The converted figure therefore carries the first rounding as well as its own. Units after a slash (W/m², kg/m³, m/s) and mm², mm³ are left alone.
display-units.js
lines 96 to 110
BimCraft 0.8.1
/**
* A calculation's sentence in the pick: lengths ("4.2 m", "300 mm"), areas ("24 m²") and volumes ("60 m³") after a number.
* A rate or density ("W/m²", "kg/m³", "m/s", "kN/m", "mm²/m") has no number straight before its unit and is left alone. A
* sentence that already carries feet-inches marks is left as written.
*/
export function localizeQuantities(text, units = 'ftin') {
const s = String(text ?? '');
if (/\d\s?['"]/.test(s)) return s;
return s.replace(/(-?\d+(?:\.\d+)?) ?(mm|m)(²|³)?(?![A-Za-z\/²³])/g, (all, n, u, pow) => {
const v = Number(n);
if (!pow) return lenMark(v * (u === 'm' ? 1000 : 1), units);
if (u === 'mm') return all; // mm² / mm³ are the calculation's own (bar areas), not a room's
return pow === '²' ? fmtM2(v, units) : fmtM3(v, units);
});
}
A paper size as text
64-bit
A sheet's width and height in the display unit.
value = mm ÷ factor, to 1 (mm, cm), 2 (in) or 3 (m, ft) decimals
One division and one toFixed per side. The paper table is in millimeters, with Letter as 215.9 × 279.4, which is 8.5 × 11 inches exactly.
display-units.js
lines 112 to 119
BimCraft 0.8.1
/** A paper size's dimensions in the pick (the paper's name, A3 or Letter, stays as it is). Feet-inches → decimal inches. */
export function fmtPaper(wMm, hMm, units = 'ftin') {
if (!Number.isFinite(wMm) || !Number.isFinite(hMm)) return '';
const u = units === 'ftin' ? 'in' : units;
const d = { mm: 1, cm: 1, m: 3, in: 2, ftdec: 3 }[u] ?? 1;
const n = (v) => String(Number((v / FACTOR[u]).toFixed(d)));
return n(wMm) + ' × ' + n(hMm) + ' ' + unitMark(u);
}
In detail
Method
value in the unit = millimeters ÷ factor, then toFixed to the unit's decimals. Feet and inches: the length is turned into whole sixteenths of an inch with Math.round, then split into feet, inches and a reduced fraction by integer steps.
Number types
64-bit numbers. Sixteenths of an inch are whole numbers once rounded.
Tolerances
None. Decimals shown: mm 0 (1 below 10 mm), cm 2, m 2, inches 3, decimal feet 2 for lengths; coordinates mm 1, cm 2, m 3, inches 2, feet 3; areas m² 2, ft² 1, in² 1, cm² 1, mm² 0; volumes m³ 2, ft³ 1, others 0.
Limits
The text carries only the decimals listed. Two functions rewrite numbers found inside a sentence: they convert the number as printed there, which was already rounded when the sentence was written.
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.