Figures shown in the residential panels and schedules
Works out the numbers the residential tools show in Properties and on schedules: a roof plane's area, the cut list, board feet, cut and fill, a new stair's direction and a building's width on an elevation.
How the precision is kept
These are short 64-bit expressions on stored model values, formatted for display at the end. Board feet and volumes are shown with one decimal or none; the values behind them are not changed by the display.
Calculations under this policy
7 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 sloped area of a manual roof plane shown in its properties.
area = |½ Σ (xᵢ yᵢ₊₁ − yᵢ xᵢ₊₁)| ÷ cos θ
The shoelace sum on the plane's stored points, divided by the cosine of the pitch, then formatted. The points were stored with 3 decimals of the file's length unit.
res-ui.js
lines 260 to 261
BimCraft 0.8.1
let a = 0; for (let i = 0; i < P.length; i++) { const p = P[i], q = P[(i + 1) % P.length]; a += p[0] * q[1] - p[1] * q[0]; }
kit.rows.push(el('dt', {}, t('res.rp.area')), el('dd', {}, fmtArea(Math.abs(a / 2) / Math.cos(rp.pitch * D2R), A.units())));
Cut list schedule
64-bit
The lumber schedule's rows: size, stock length, pieces and board feet, with totals.
board feet shown = bf.toFixed(1)
Rows and totals come from lumberList. Board feet are shown with one decimal, each row and the total rounded on its own, so the shown rows need not add up to the shown total.
res-ui.js
lines 648 to 661
BimCraft 0.8.1
// the cut list as a schedule (model-ui.js Schedules panel): size, stock length, pieces, board feet
function lumberSchedule() {
const w = writer();
if (!w) return null;
const mm = isMetric(A.units()), lst = lumberList(w, { metric: mm });
if (!lst.rows.length) return { head: [t('res.fr.sch.size'), t('res.fr.sch.length'), t('res.fr.sch.count'), t('res.fr.sch.bf')], rows: [], nums: [2, 3], total: null };
const tj = R.frames.find((f) => f.kind === 'floor' && f.floorMode === 'tji' && f.tji?.Assumptions); // GH.3-E: the assumptions go on the schedule
return {
...(tj ? { note: String(tj.tji.Assumptions).replace(/\n/g, ' ') } : {}),
head: [t('res.fr.sch.size'), t('res.fr.sch.length'), t('res.fr.sch.count'), t('res.fr.sch.bf')],
rows: lst.rows.map((r) => [r.label, L(r.stock), String(r.count), r.bf.toFixed(1)]),
nums: [2, 3], total: [t('model.sch.total'), '', String(lst.pieces), lst.bf.toFixed(1)],
};
}
Board feet of a framing in Properties
64-bit
Shows the piece count and board feet of one framing.
shown = Math.round(BoardFeet)
The stored total, already rounded to 2 decimals, is shown as a whole number.
The overall width of the building across a view direction, used for the width note on an elevation when the wall-based width is not available.
x = q · r ± t ÷ 2 over every wall end; width from min to max
Half the wall thickness is added on both sides of every wall end whatever the wall's direction. That is exact for walls square to the view and overstates the width for a wall that runs across the view, by up to half its thickness at each end.
res-ui.js
line 1105
BimCraft 0.8.1
const widthOn = (dir) => { const r = [dir[1], -dir[0]], xs = []; for (const x of A.S.data.walls || []) for (const q of [x.a, x.b]) xs.push(q[0] * r[0] + q[1] * r[1] - x.t / 2, q[0] * r[0] + q[1] * r[1] + x.t / 2); /* the outside faces (square walls exactly) */ return xs.length ? { x0: Math.min(...xs), x1: Math.max(...xs) } : null; };
Inverse of a level's placement
64-bit
Inverts a level's 4×4 world matrix to bring site coordinates back into the level's plan.
R⁻¹ = Rᵀ; t⁻¹ = −Rᵀ t
Valid for rotation and translation only: the rotation is transposed, not inverted, so a matrix that also scales would not be inverted correctly. No test of the matrix is made.
res-ui.js
lines 73 to 79
BimCraft 0.8.1
function inv4m(m) {
// rigid transforms only (rotation + translation): the inverse is the transpose of the rotation and the moved origin
const r = [m[0], m[4], m[8], 0, m[1], m[5], m[9], 0, m[2], m[6], m[10], 0, 0, 0, 0, 1];
const t = apply4m(r, m[12], m[13], m[14]);
r[12] = -t[0]; r[13] = -t[1]; r[14] = -t[2];
return r;
}
In detail
Method
Shoelace area divided by cos(pitch); totals from lumberList; a rigid 4×4 inverse by transposing the rotation.
Number types
64-bit numbers.
Limits
The fallback building width adds half a wall thickness whatever the wall's direction, which is exact only for walls square to the view. The 4×4 inverse assumes rotation and translation only.
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.