Works out where every stud, plate, header, joist, rafter, truss and collar tie goes, which lumber size a span needs, and the lengths and board feet written on each piece.
How the precision is kept
Positions and lengths are 64-bit millimeters from the wall, floor and roof geometry. Sizes come from span tables the file labels as defaults, not engineering. Truss tops are sampled at 41 points and collar ties are found by bisection, so those two shapes carry the sampling and step limits stated below. The length written on each piece is rounded to 3 decimals of the file's length unit, and the cut list reads that rounded value back.
Open item. Store each piece's Length with 6 decimals like the other lengths, so the cut list does not read back a length rounded to 3 decimals of the file unit.
Calculations under this policy
21 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.
Picks the smallest size in a span table whose maximum span reaches the span, or the largest size flagged as over.
first size with span ≤ max + 1e-6 mm
The span and the table maxima are 64-bit millimeters; the tolerance is an absolute 1e-6 mm. The maxima are decimal feet times 304.8, and the file's comments label them defaults, not engineering.
res-framing.js
lines 59 to 63
BimCraft 0.8.1
/** The smallest size in a span table that reaches `span` (else the largest, flagged). */
export function sizeFor(table, span) {
for (const [size, max] of table) if (span <= max + 1e-6) return { size, over: false };
return { size: table[table.length - 1][0], over: true };
}
Span table column for a spacing
64-bit
Chooses the 16 inch or the 24 inch column of a span table from the framing spacing.
|spacing − 609.6| < 50 → 24 inch column, else 16 inch column
Only two columns exist. Any spacing more than 50 mm away from 609.6 mm, including one between 16 and 24 inches such as 19.2 inches, is looked up in the 16 inch column, whose maximum spans are longer.
Picks a two-ply header size from the rough opening width, or three plies of 2x12 flagged as over.
first size with width ≤ max + 1e-6 mm; non-bearing: 2x4 up to 8 ft
The width is compared with table limits of 3, 4, 6 and 8 feet times 304.8, with an absolute tolerance of 1e-6 mm. The file's comment labels the table a default for a one-story roof load.
res-framing.js
lines 64 to 68
BimCraft 0.8.1
export function headerFor(width, bearing = true) {
if (!bearing) return { size: width > 8 * FT ? '2x12' : '2x4', plies: 2, over: width > 8 * FT };
for (const [max, size] of HEADER_TABLE) if (width <= max + 1e-6) return { size, plies: 2, over: false };
return { size: '2x12', plies: 3, over: true };
}
Board feet of a piece
64-bit
The board feet of one piece from its nominal size and its length.
bf = t_nominal × d_nominal × (L ÷ 304.8) ÷ 12
One 64-bit expression. The nominal inches are whole numbers and 304.8 mm per foot is exact, so the only rounding is in the two divisions.
res-framing.js
lines 69 to 70
BimCraft 0.8.1
/** Board feet of a piece: nominal thickness × depth (in) × length (ft) / 12. */
export function boardFeet(size, length) { const L = LUMBER[size]; return L ? L.nom[0] * L.nom[1] * (length / FT) / 12 : 0; }
Stud layer position across a wall
64-bit
Finds where the stud layer sits across the wall's thickness, from the wall type's layers.
y = ±(t ÷ 2 − Σ layers before − layer thickness)
The total thickness is a sum of the layer thicknesses added in order, and the band edges are differences of those sums; no tolerance is used.
res-framing.js
lines 76 to 88
BimCraft 0.8.1
/** The stud layer's band across a wall (y in the wall's axes: +y = its left), or null for a wall with no studs. */
export function studBand(wall) {
const ty = (wall.assembly || wallType(wall.typeKey));
if (!ty) return null;
const t = ty.layers.reduce((s, l) => s + l.t, 0);
let cum = 0, band = null;
const sgn = wall.extSide === 'right' ? -1 : 1; // the exterior face's side
for (const l of ty.layers) {
if (l.mat === 'studs') { const y0 = sgn * (t / 2 - cum - l.t), y1 = sgn * (t / 2 - cum); band = { y0: Math.min(y0, y1), y1: Math.max(y0, y1), depth: l.t }; }
cum += l.t;
}
return band;
}
Where a wall's framing starts and stops
64-bit
Finds the framed start and end of a wall at corners and T junctions with other walls.
t = cross(q − p, e) ÷ cross(d, e)
The framed end is the intersection of the wall's stud center line with the other wall's stud band edge, computed by lineHit, which returns nothing when |cross| of the two unit directions is below 1e-9. A shared end is recognized within half the thicker wall + 1 mm, and walls count as in line when |cross| of their unit directions is below 0.05.
res-framing.js
lines 123 to 148
BimCraft 0.8.1
const shared = [o.a, o.b].find((q) => Math.hypot(q[0] - e.p[0], q[1] - e.p[1]) < Math.max(wall.t, o.t) / 2 + 1);
if (shared) {
if (Math.abs(cross(u, ou)) < 0.05) continue; // in line: a straight joint, no corner
const through = wall.guid < o.guid;
// the other wall's stud band edges, as lines; which is farther from this wall's body
const mid = toPlan(wall.len / 2, 0);
const e0 = oEdge(ob.y0), e1 = oEdge(ob.y1);
const far0 = Math.abs(dot(sub(mid, e0), on)) > Math.abs(dot(sub(mid, e1), on));
const outer = far0 ? e0 : e1, inner = far0 ? e1 : e0;
const tOut = lineHit(toPlan(0, yc), u, outer, ou), tIn = lineHit(toPlan(0, yc), u, inner, ou);
if (tOut === null || tIn === null) continue;
if (e.at === 'a') x0 = through ? Math.min(tOut, tIn) : Math.max(tOut, tIn); else x1 = through ? Math.max(tOut, tIn) : Math.min(tOut, tIn);
if (through) cornerAt.push({ at: e.at, depth: ob.depth });
continue;
}
// this end on the other wall's middle: a T — stop against its studs
const s = dot(sub(e.p, o.a), ou), d = Math.abs(dot(sub(e.p, o.a), on));
if (s > 1 && s < o.len - 1 && d < o.t / 2 + 1) {
const mid = toPlan(wall.len / 2, 0);
const e0 = oEdge(ob.y0), e1 = oEdge(ob.y1);
const near0 = Math.abs(dot(sub(mid, e0), on)) < Math.abs(dot(sub(mid, e1), on));
const face = near0 ? e0 : e1;
const tf = lineHit(toPlan(0, yc), u, face, ou);
if (tf !== null) { if (e.at === 'a') x0 = tf; else x1 = tf; }
}
}
Length of a wall piece
64-bit
Records a wall piece as a box and takes its length as the longer of its extent along the wall and its height.
length = max(x₁ − x₀, z₁ − z₀)
Two 64-bit differences. A piece is dropped unless both differences are greater than 1 mm.
Places the jack and king studs, the header, the cripples and the rough sill around each door and window.
header top = min(head + header depth, underside of top plate); cripples at x₀ + k × spacing
Positions are sums of the opening's offset, width and multiples of the 38.1 mm stud thickness. Cripple positions are x₀ + k × spacing with k starting at ⌈(a − x₀) ÷ spacing⌉, with no tolerance on the ceiling. An opening wider than 6 feet gets two jacks each side.
res-framing.js
lines 174 to 192
BimCraft 0.8.1
const ro0 = o.offset, ro1 = o.offset + o.width, head = o.sill + o.height;
const hd = headerFor(o.width, ctx.bearing !== false);
const jacks = o.width > 6 * FT ? 2 : 1;
const hx0 = ro0 - jacks * T, hx1 = ro1 + jacks * T;
const hDepth = LUMBER[hd.size].d;
for (let j = 0; j < jacks; j++) { stud('jack', ro0 - T * (j + 0.5), zs0, head); stud('jack', ro1 + T * (j + 0.5), zs0, head); }
stud('king', hx0 - T / 2); stud('king', hx1 + T / 2);
const hTop = Math.min(head + hDepth, zs1);
box('header', hd.size, hx0, hx1, head, hTop, yb0, yb0 + yd, { plies: hd.plies });
if (hd.over) notes.push('header');
if (head + hDepth > zs1 + 1) notes.push('headerroom');
// cripples above the header and below a window, on the layout
const lay = (a, b) => { const out = []; for (let k = Math.ceil((a - x0) / spacing); x0 + k * spacing < b; k++) out.push(x0 + k * spacing); return out; };
if (zs1 - hTop > T) for (const x of lay(hx0 + T / 2, hx1 - T / 2)) stud('cripple', x, hTop, zs1);
if (o.kind === 'window' && o.sill > 2 * T) {
box('sill', size, ro0, ro1, o.sill - T, o.sill);
for (const x of [ro0 + T / 2, ...lay(ro0 + T, ro1 - T), ro1 - T / 2]) stud('cripple', x, zs0, o.sill - T);
}
blocked.push([hx0 - T, hx1 + T]);
Studs on layout
64-bit
Places the common studs on center from the wall's framed start.
x = x₀ + k × spacing, k = 1, 2, … while x < x₁ − T
Each position is one multiplication and one addition from the start, so the rounding does not build up along the wall. A stud is skipped where it falls inside an opening or within 1 mm of a piece already placed.
res-framing.js
lines 203 to 207
BimCraft 0.8.1
for (let k = 1; x0 + k * spacing < x1 - T; k++) {
const x = x0 + k * spacing;
if (blocked.some(([a, b]) => x > a && x < b) || taken(x)) continue;
stud('stud', x);
}
Line clipped to a polygon
64-bit
Finds the stretches of a joist, rafter or truss line that lie inside a floor outline or a roof face.
t = cross(a − p, e) ÷ cross(d, e); s = cross(a − p, d) ÷ cross(d, e)
An edge is skipped when |cross(d, e)| < 1e-12, where d is a unit direction and e is the edge in millimeters, so the test scales with the edge length. A crossing counts when −1e-9 ≤ s < 1 − 1e-9, the crossings are sorted and paired, and a stretch of 1 mm or less is dropped.
res-framing.js
lines 222 to 235
BimCraft 0.8.1
/** Clip a line (point p, direction d) to a polygon → [t0, t1] intervals inside it. */
function clipLine(p, d, poly) {
const ts = [];
for (let i = 0; i < poly.length; i++) {
const a = poly[i], b = poly[(i + 1) % poly.length], e = sub(b, a), c = cross(d, e);
if (Math.abs(c) < 1e-12) continue;
const t = cross(sub(a, p), e) / c, s = cross(sub(a, p), d) / c;
if (s >= -1e-9 && s < 1 - 1e-9) ts.push(t);
}
ts.sort((x, y) => x - y);
const out = [];
for (let i = 0; i + 1 < ts.length; i += 2) if (ts[i + 1] - ts[i] > 1) out.push([ts[i], ts[i + 1]]);
return out;
}
Outline moved in by a distance
64-bit
Moves every edge of a floor outline inward by a fixed distance and finds the new corners.
Each corner is the intersection of the two neighboring offset edges. When |cross| of the two unit directions is below 1e-9 the offset point of the edge is used. A near-zero edge length is replaced by 1 to avoid dividing by zero. Edges are not removed when the inset makes them vanish.
Sets the joist lines across a floor and takes the longest clipped joist as the span that sizes them.
c = c₀ + spacing, then + spacing while c < c₁ − 1; span = max(t₁ − t₀)
The joist positions are found by adding the spacing to the previous position, so each step adds one more rounding. The span is the longest inside stretch of any joist line through the outline inset by 1.5 inches.
res-framing.js
lines 266 to 272
BimCraft 0.8.1
const cs = inner.map((p) => dot(p, across)), c0 = Math.min(...cs), c1 = Math.max(...cs);
const lines = [];
for (let c = c0 + sp; c < c1 - 1; c += sp) lines.push(c);
const openings = (ctx.openings || []).map((op) => { const ss = op.map((p) => dot(p, ax)), cc = op.map((p) => dot(p, across)); return { s0: Math.min(...ss), s1: Math.max(...ss), c0: Math.min(...cc), c1: Math.max(...cc) }; });
let span = 0;
const segsAt = (c) => clipLine([across[0] * c, across[1] * c], ax, inner);
for (const c of lines) for (const [t0, t1] of segsAt(c)) span = Math.max(span, t1 - t0);
Joists cut round floor openings
64-bit
Makes each joist piece, cutting it 3 inches short of an opening it crosses, and records its length.
length = s₁ − s₀
Lengths are differences of 64-bit positions along the joist. An opening is the bounding box of its outline in the joist axes, so an opening that is not square to the joists is framed as its box. Pieces of 1 mm or less are dropped.
res-framing.js
lines 288 to 297
BimCraft 0.8.1
const joist = (role, c, s0, s1, sz = pick.size) => { if (s1 - s0 > 1) pieces.push({ role, size: sz, line: [[...P(c, s0), top - D / 2], [...P(c, s1), top - D / 2]], depth: D, width, length: s1 - s0, flat: true, tji: engineered }); };
for (const c of lines) {
for (const [t0, t1] of segsAt(c)) {
// cut round openings (tail joists), the trimmer lines skip them
const hit = openings.filter((o) => c > o.c0 - 3 * IN && c < o.c1 + 3 * IN);
let s = t0;
for (const o of hit.sort((p, q) => p.s0 - q.s0)) { joist('joist', c, s, Math.max(s, o.s0 - 3 * IN)); s = Math.max(s, o.s1 + 3 * IN); }
joist('joist', c, s, t1);
}
}
Trusses across a roof
64-bit
Places a truss at each spacing along the roof and takes its top profile from the roof's underside.
top profile sampled at t₀ + (t₁ − t₀) × k ÷ 40, k = 0 … 40
The top chord is 41 samples of the roof height, kept where the height is more than 10 mm above the plate, so a ridge that falls between two samples is cut off flat between them. Truss positions are found by adding the spacing repeatedly, with a tolerance of 1e-6 mm on the last one.
res-framing.js
lines 331 to 341
BimCraft 0.8.1
const ss = ctx.outline.map((p) => dot(p, dir)), s0 = Math.min(...ss), s1 = Math.max(...ss);
for (let s = s0 + 0.75 * IN; s <= s1 - 0.75 * IN + 1e-6; s += sp) {
const p = [dir[0] * s, dir[1] * s];
for (const [t0, t1] of clipLine(p, acr, ctx.outline)) {
const pts = [];
for (let k = 0; k <= 40; k++) { const tt = t0 + (t1 - t0) * k / 40, q = [p[0] + acr[0] * tt, p[1] + acr[1] * tt], z = heightAt(plan, q); if (z !== null && z > ctx.plate + 10) pts.push([tt, z]); }
if (pts.length < 3) continue;
pieces.push({ role: 'truss', size: '2x4', truss: { p, acr, t0, t1, plate: ctx.plate, top: pts }, length: t1 - t0, width: 1.5 * IN });
}
if (s + sp > s1 - 0.75 * IN && s < s1 - 0.75 * IN - 1) s = s1 - 0.75 * IN - sp; // a truss at the far end too
}
Rafters and their size
64-bit
Sizes the rafters from the longest horizontal run, places them along each roof face and records each one's sloped length.
The length uses Math.hypot of the horizontal run and the rise, with both heights taken from faceZ in res-skeleton.js. Rafter positions start half a spacing from the face's end and are found by adding the spacing repeatedly.
res-framing.js
lines 345 to 360
BimCraft 0.8.1
let run = 0; // the longest rafter's horizontal run, from its eave to the top of its face
for (const f of plan.faces) for (const p of f.poly) run = Math.max(run, dot(sub(p, [f.n[0] * f.c, f.n[1] * f.c]), f.n));
const pick = sizeFor(tableFor(RAFTER_TABLE, sp), run);
if (pick.over) notes.push('rafter');
const R = LUMBER[pick.size], up = SIZES[Math.min(SIZES.length - 1, SIZES.indexOf(pick.size) + 1)];
for (const f of plan.faces) {
const o = [f.n[0] * f.c, f.n[1] * f.c];
const us = f.poly.map((q) => dot(sub(q, o), f.u)), u0 = Math.min(...us), u1 = Math.max(...us);
for (let uu = u0 + sp / 2; uu < u1; uu += sp) {
const base = [o[0] + f.u[0] * uu, o[1] + f.u[1] * uu];
for (const [t0, t1] of clipLine(base, f.n, f.poly)) {
const a = [base[0] + f.n[0] * t0, base[1] + f.n[1] * t0], b = [base[0] + f.n[0] * t1, base[1] + f.n[1] * t1];
pieces.push({ role: 'rafter', size: pick.size, line: [[...a, faceZ(f, a)], [...b, faceZ(f, b)]], depth: R.d, width: R.t, length: Math.hypot(t1 - t0, faceZ(f, b) - faceZ(f, a)) });
}
}
}
Collar ties
64-bit
Places a collar tie every 4 feet under each ridge, two thirds of the way from the plate to the ridge, and finds how far it reaches each way.
z_c = plate + (z_ridge − plate) × 2 ÷ 3; reach by 40 halvings of [0, 20000 mm]
The reach each way is found by bisection on the roof height: 40 halvings of a 20000 mm bracket, which ends 20000 ÷ 2⁴⁰ ≈ 1.8e-8 mm wide. The lower end of the bracket is kept, so the tie stops just inside the roof. A reach beyond 20 m is not found.
res-framing.js
lines 373 to 383
BimCraft 0.8.1
const zR = l.a[2], zc = ctx.plate + (zR - ctx.plate) * 2 / 3;
for (let s = 2 * FT; s < L - 1; s += 4 * FT) {
const m = [l.a[0] + u[0] * s, l.a[1] + u[1] * s];
// how far each way the roof's underside is above zc
const reach = (sgn) => { let lo = 0, hi = 20000; for (let k = 0; k < 40; k++) { const mid = (lo + hi) / 2, q = [m[0] + acr[0] * sgn * mid, m[1] + acr[1] * sgn * mid], z = heightAt(plan, q); if (z !== null && z > zc) lo = mid; else hi = mid; } return lo; };
const r1 = reach(1), r2 = reach(-1);
if (r1 + r2 < 300) continue;
const a = [m[0] - acr[0] * r2, m[1] - acr[1] * r2], b = [m[0] + acr[0] * r1, m[1] + acr[1] * r1];
pieces.push({ role: 'collar', size: '2x6', line: [[...a, zc], [...b, zc]], depth: LUMBER['2x6'].d, width: R.t, length: r1 + r2, flat: true, low: true });
}
}
Ceiling joists
64-bit
Lays ceiling joists out like floor joists at the plate and sizes them from the ceiling span table.
span = max(joist length); z = plate + depth ÷ 2
The layout is frameFloor's, so the positions carry the same repeated addition of the spacing. The size comes from the longest joist's length through sizeFor.
res-framing.js
lines 386 to 394
BimCraft 0.8.1
function frameFloorLike(poly, sp, z, table) {
const r = frameFloor(poly, { spacing: sp, top: z + 0.75 * IN });
let span = 0;
for (const p of r.pieces) if (p.role === 'joist') span = Math.max(span, p.length);
const pick = sizeFor(tableFor(table, sp), span), L = LUMBER[pick.size];
// ceiling joists bear on the plates: their underside at the plate
const pieces = r.pieces.filter((p) => p.role === 'joist').map((p) => ({ ...p, role: 'ceilingjoist', size: pick.size, depth: L.d, line: p.line.map((q) => [q[0], q[1], z + L.d / 2]) }));
return { pieces, over: pick.over };
}
Solid of a sloped member
64-bit
Builds the solid of a joist, rafter, hip, valley or ridge as a rectangle swept along its 3D line with plumb ends.
The plumb depth uses a square root of 1 plus a square, so nothing cancels. A vertical line would divide by zero; the horizontal length is replaced by 1 in that case. The frame, profile and sweep then pass through the model writer, which rounds coordinates to 6 decimals of the file's length unit and directions to 12 decimals.
res-framing.js
lines 418 to 427
BimCraft 0.8.1
const [a3, b3] = pc.line, A = P(...a3), B = P(...b3), d = [B[0] - A[0], B[1] - A[1], B[2] - A[2]], L = Math.hypot(...d);
const hz = Math.hypot(d[0], d[1]) || 1, x = [d[0] / hz, d[1] / hz, 0], z = [-x[1], x[0], 0];
const slope = Math.abs(d[2]) / hz, vd = pc.depth * Math.sqrt(1 + slope * slope); // the depth square to the slope, measured plumb
const zb = pc.flat ? A[2] - vd / 2 : A[2]; // rafters, hips, valleys and ridges stand on the roof's underside; flat pieces are centred on their line
const frame = w.axisFrame([A[0] - z[0] * pc.width / 2, A[1] - z[1] * pc.width / 2, zb], x, z);
const dl = [d[0] / L, d[1] / L, d[2] / L], ex = [dl[0] * z[0] + dl[1] * z[1], dl[2], dl[0] * x[0] + dl[1] * x[1]];
// shortcut: schematic I section; manufacturer-specific flange/web dimensions require a product catalog.
const f = Math.min(1.25 * IN, vd / 4), web = Math.min(0.375 * IN, pc.width / 4), mid = pc.width / 2;
const profile = pc.tji ? [[0, 0], [pc.width, 0], [pc.width, f], [mid + web / 2, f], [mid + web / 2, vd - f], [pc.width, vd - f], [pc.width, vd], [0, vd], [0, vd - f], [mid - web / 2, vd - f], [mid - web / 2, f], [0, f]] : [[0, 0], [pc.width, 0], [pc.width, vd], [0, vd]];
return w.extrudeAt(w.profile(profile), frame, L, ex);
Length and board feet written on a piece
64-bit
Writes each piece's role, size, length and board feet into the model, and adds up the board feet of the framing.
The length is rounded to 3 decimals of the file's length unit before it is stored: 1 mm in a file in meters, 0.001 mm in a file in millimeters. The cut list reads this rounded length back. The running total of board feet is added from the unrounded values.
The length is the stored Length, which was rounded to 3 decimals of the file's unit, times the unit in millimeters. The ceiling has no tolerance: a 12 foot piece (3657.6 mm) stored in a file in meters reads back as 3658 mm and is counted as 14 foot stock. Board feet are counted on the stock length, not the cut length.
res-framing.js
lines 658 to 681
BimCraft 0.8.1
/** The cut list: every framing piece (of these framings, or all) by size and stock length (whole 2' from 8'), with counts
* and board feet. → { rows: [{ size, stock (mm), count, bf }], pieces, bf } */
export function lumberList(w, { guids = null, metric = false } = {}) {
const map = new Map();
let pieces = 0, bf = 0;
for (const fr of readFraming(w)) {
if (guids && !guids.includes(fr.guid)) continue;
for (const pid of fr.parts) {
const ps = w.readPset(pid, LUMBER_PSET);
if (!ps) continue;
const len = Number(ps.Length) * w.unitMm, sz = String(ps.Size || '');
const base = sz.replace(/ × \d+$/, ''), plies = Number((sz.match(/× (\d+)/) || [])[1] || 1);
const stock = metric ? Math.max(2400, Math.ceil(len / 600) * 600) : Math.max(8 * FT, Math.ceil(len / (2 * FT)) * 2 * FT);
const k = base + '|' + stock;
const row = map.get(k) || { size: base, label: metric ? (LUMBER[base]?.metric || base) : base, stock, count: 0, bf: 0 };
row.count += plies;
row.bf += boardFeet(base, stock) * plies;
map.set(k, row);
pieces += plies; bf += boardFeet(base, stock) * plies;
}
}
const rows = [...map.values()].sort((a, b) => SIZES.indexOf(a.size) - SIZES.indexOf(b.size) || a.stock - b.stock);
return { rows, pieces, bf };
}
In detail
Method
Stud layout on center from the wall's framed start; kings, jacks, headers and cripples from each opening; joists as lines clipped to the floor polygon inset by 1.5 inches; rafters square to each roof face's eave clipped to the face; span tables for header, joist, rafter and ceiling joist sizes.
Number types
64-bit numbers throughout. Inch and foot factors are 25.4 and 304.8 millimeters, both exact.
Tolerances
Span table comparison: span ≤ maximum + 1e-6 mm. Wall ends meet when closer than half the thicker wall + 1 mm; walls are in line when |sin of the angle between them| < 0.05. Parallel tests: |cross| < 1e-9 on unit vectors (lineHit, insetPoly) and < 1e-12 on a unit direction times an edge in millimeters (clipLine). Pieces 1 mm or shorter are dropped. Truss profile points are dropped when collinear within 1e-3 mm².
Limits
A spacing that is not within 50 mm of 24 inches uses the 16 inch span column. Joist, rafter and truss positions are found by adding the spacing repeatedly. The change detection key rounds every number to 0.1 before hashing, so a change smaller than that does not remake the framing.
Approach: 64-bit, stated limit
The arithmetic is 64-bit, but the method or the data sets the accuracy: a solver tolerance, a mesh, a step size, a datum shift, a table. The limit is stated where the result is shown.