v0.7.6: geen wolfsdak bij een overkapping (veranda, inpandig of uitpandig: het dak van een unit steekt buiten zijn vloer, HouseModel.hasCover): de keuze verdwijnt in configurator en light, een bestaand wolfsdak wordt een zadeldak met dezelfde goot en nok; afdekker op een stenen trasraam onder rabat, felsplaten of stuc (WallModel.TRAS_CAP): zetwerk achter de bekleding, 5° aflopend, neus 25 mm over de steen, onderbroken bij openingen, bij een buitenhoek door tot voorbij de buursteen, zwart/antraciet/wit (WallModel.TRIM_COLORS), in 3D, PDF-aanzichten, materialen, rapport en kosten; ventilatierooster van 40 mm op de gevel direct onder de onderplaat van alle boeidelen (RoofModel.VENT, niet boven een veranda of tegen een hogere gevel), sleuven in de textuur, aan/uit en kleur bij Dak › Boeideel, in 3D, PDF, rapport en kosten; light-versie: boeidelen of daktrim met kleur boeidelen (Dak) en één zetwerk-kleur voor afdekker en rooster (Gevel); 3D zijwaarts schuiven ook met de middelste muisknop, Shift/Ctrl/⌘ + slepen en de pijltjestoetsen met de muis boven de weergave (configurator en light, hints en sneltoetsenoverzicht bijgewerkt)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
432e0f494a
commit
118ccf9098
+31
-4
@@ -36,7 +36,7 @@ window.HouseModel = (() => {
|
||||
spacing: { exterior: { min: 240, max: 480 }, interior: { min: 300, max: 600 } },
|
||||
facade: { type: 'rabat', stone: 'K490', rabatColor: 'naturel', stucColor: 'wit', felsColor: 'antraciet' },
|
||||
cladding: 'horizontaal',
|
||||
trasraam: { enabled: true, height: WallModel.TRASRAAM_DEFAULT_MM, finish: 'cementplaat' },
|
||||
trasraam: { enabled: true, height: WallModel.TRASRAAM_DEFAULT_MM, finish: 'cementplaat', capColor: 'antraciet' },
|
||||
interiorPaint: true,
|
||||
interiorColor: '#f2efe9',
|
||||
ceilingColor: '#f4f3ef',
|
||||
@@ -67,7 +67,7 @@ window.HouseModel = (() => {
|
||||
}
|
||||
function facadeMaterials(state, fc) {
|
||||
const tr = state.settings.trasraam;
|
||||
const trasraam = tr.enabled ? WallModel.trasraamFor(tr.height, tr.finish) : null;
|
||||
const trasraam = tr.enabled ? WallModel.trasraamFor(tr.height, tr.finish, tr.capColor) : null;
|
||||
const cladding = state.settings.cladding;
|
||||
if (fc.type === 'steen') return { exterior: 'cementplaat', stone: fc.stone, stuc: null, cladding, trasraam, rabatColor: null, fels: null };
|
||||
if (fc.type === 'stuc') return { exterior: 'cementplaat', stone: null, stuc: fc.stuc, cladding, trasraam, rabatColor: null, fels: null };
|
||||
@@ -1121,10 +1121,33 @@ window.HouseModel = (() => {
|
||||
}
|
||||
});
|
||||
state.interiorWalls.forEach(iw => { iw.wall.wall.minSpacing = sp.interior.min; iw.wall.wall.maxSpacing = sp.interior.max; });
|
||||
// Geen wolfsdak boven een overkapping: wordt een zadeldak met dezelfde goot en nok.
|
||||
if (houseRoofOn(state)) {
|
||||
if (state.settings.roof.house.form.type === 'wolf' && state.units.some(u => roofCovers(u, cover))) state.settings.roof.house.form.type = 'zadel';
|
||||
} else state.units.forEach(u => {
|
||||
const f = UnitModel.roofForm(u.unit);
|
||||
if (f.type === 'wolf' && roofCovers(u, cover)) UnitModel.applyRoofForm(u.unit, Object.assign(f, { type: 'zadel' }));
|
||||
});
|
||||
applyHouseRoof(state);
|
||||
applyRoofJoins(state);
|
||||
}
|
||||
|
||||
// Overkapping (veranda, inpandig of uitpandig): het dak van de unit steekt buiten zijn vloer. Een vrije dakmaat
|
||||
// telt pas vanaf de kleinste paal-uitkraging; daaronder is het overstek.
|
||||
function roofCovers(u, cover) {
|
||||
if (!u.roof.followFloor) {
|
||||
const d = u.roof.deck.floor, f = u.unit.floor.floor, m = 400;
|
||||
return (d.width - f.width) / 2 + Math.abs(u.roof.offsetX || 0) > m || (d.depth - f.depth) / 2 + Math.abs(u.roof.offsetZ || 0) > m;
|
||||
}
|
||||
const c = cover[u.id] || {}, x = u.roof.extend || {};
|
||||
return ['l', 'r', 'f', 'b'].some(k => (c[k] || 0) + (x[k] || 0) > EPS);
|
||||
}
|
||||
// Overkapping onder het dak van de unit (unitId) of ergens onder de woning (geen unitId): dan geen wolfsdak.
|
||||
function hasCover(state, unitId) {
|
||||
const cover = coverExtensions(state);
|
||||
return state.units.some(u => (!unitId || u.id === unitId) && roofCovers(u, cover));
|
||||
}
|
||||
|
||||
const EXTEND_MAX = 4000;
|
||||
function normalizeExtend(e) {
|
||||
return Object.fromEntries(['f', 'r', 'b', 'l'].map(k => [k, Math.max(0, Math.min(EXTEND_MAX, Math.round(Number((e || {})[k]) || 0)))]));
|
||||
@@ -1873,7 +1896,7 @@ window.HouseModel = (() => {
|
||||
};
|
||||
const facadeDepth = (a, b, nrm) => {
|
||||
const e = edgePiece(a, b, nrm);
|
||||
return e ? Math.sign(e.dot) * WallModel.claddingOffset(e.p.buitenMateriaal, e.p.stone, e.p.stuc) : 0;
|
||||
return e ? Math.sign(e.dot) * WallModel.claddingOffset(e.p.buitenMateriaal, e.p.stone, e.p.stuc) : null; // null: geen gevel (veranda)
|
||||
};
|
||||
const facadeFels = (a, b, nrm) => { const e = edgePiece(a, b, nrm); return !!(e && e.dot > 0 && e.p.fels); };
|
||||
const roofEdge = units.length ? RoofModel.computeEdge(state.settings.roof,
|
||||
@@ -2219,6 +2242,7 @@ window.HouseModel = (() => {
|
||||
woodM3: sumU(u => u.floorSpecs.joistWoodM3 + u.roof.specs.joistWoodM3) + sumP(p => p.stats.woodVolumeM3),
|
||||
woodKg: sumU(u => u.floorSpecs.joistWoodKg + u.roof.specs.joistWoodKg) + sumP(p => p.specs.woodKg),
|
||||
battens: { count: sumP(p => p.stats.battenCount || 0), lengthM: sumP(p => p.stats.battenLengthM || 0), kg: sumP(p => p.specs.battenKg || 0) },
|
||||
trasraamCap: { lengthM: sumP(p => p.stats.trasraamCapM || 0), color: (WallModel.TRIM_COLORS[(pieces.find(p => p.stats.trasraamCapM > 0 && p.trasraam) || { trasraam: {} }).trasraam.capColor] || {}).label || '' },
|
||||
isolatie,
|
||||
isolatieM3: isolatie.reduce((a, r) => a + r.m3, 0),
|
||||
plaatwerk: [
|
||||
@@ -2292,6 +2316,8 @@ window.HouseModel = (() => {
|
||||
overhang: parts.roofEdge.overhang,
|
||||
soffitM2: parts.roofEdge.soffitM2,
|
||||
trimLengthM: parts.roofEdge.trimLengthMM / 1000,
|
||||
ventLengthM: (parts.roofEdge.ventLengthMM || 0) / 1000,
|
||||
ventColor: parts.roofEdge.vent ? (WallModel.TRIM_COLORS[parts.roofEdge.ventColor] || {}).label || '' : '',
|
||||
trimHeight: parts.roofEdge.trimHeight,
|
||||
spots: parts.roofEdge.spots.length
|
||||
} : null,
|
||||
@@ -2357,6 +2383,7 @@ window.HouseModel = (() => {
|
||||
state.settings.trasraam.enabled = state.settings.trasraam.enabled !== false;
|
||||
if (!(state.settings.trasraam.height > 0)) state.settings.trasraam.height = WallModel.TRASRAAM_DEFAULT_MM;
|
||||
if (!WallModel.isStoneFinish(state.settings.trasraam.finish)) state.settings.trasraam.finish = 'cementplaat';
|
||||
if (!WallModel.isTrimColor(state.settings.trasraam.capColor)) state.settings.trasraam.capColor = 'antraciet';
|
||||
state.settings.sandwich = state.settings.sandwich !== false;
|
||||
if (!/^#[0-9a-f]{6}$/i.test(state.settings.interiorColor || '')) state.settings.interiorColor = def.interiorColor;
|
||||
if (!/^#[0-9a-f]{6}$/i.test(state.settings.ceilingColor || '')) state.settings.ceilingColor = def.ceilingColor;
|
||||
@@ -2393,7 +2420,7 @@ window.HouseModel = (() => {
|
||||
ALIGN_LABELS, SIDE_LABELS, DEFAULT_INTERIOR_THICKNESS, FACADE_TYPES, facadeFor, facadeMaterials,
|
||||
clone, createEmptyProject, createDefaultSettings, createUnitEntry, applyGlobalSettings, nextUnitId, MODELS, createDefaultState, unitRects, computeSeams, overlappingPairs,
|
||||
interiorWallDefaults, setThickness, thicknessOf, interiorLayout, ensureSeamWalls, syncSeamWalls, missingSeamWalls,
|
||||
houseRoofShape, houseRoofFits, setHouseRoof, coverExtensions, EXTEND_MAX,
|
||||
houseRoofShape, houseRoofFits, hasCover, setHouseRoof, coverExtensions, EXTEND_MAX,
|
||||
computeParts, placeGroups, rootGroups, groundOrigin, sectionCaps, allWallPieces, computeTotals, computeDimensions, dimensionRows, TRANSPORT, TRANSPORT_CLASSES, computeTransport, validateState, fromUnitDesign, normalize
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -271,6 +271,12 @@ window.HousePdf = (() => {
|
||||
const trColor = WallModel.isStoneFinish(tr.finish) ? (WallModel.STONE_COLORS[tr.finish] || '#a0724f') : VIEW_COLORS.cementplaat;
|
||||
const zT = p.place.thickness / 2 + (WallModel.isStoneFinish(tr.finish) ? WallModel.STONE.THICK_MM : 12);
|
||||
faces.push({ kind: 'trasraam', pts: band.map(q => toWorld(p, q.x, q.y, zT)), n, color: trColor, bias: 1 });
|
||||
// Afdekker: neus over de bovenkant van de steen (alleen in 3D onderbroken bij openingen).
|
||||
if (p.stats && p.stats.trasraamCapM > 0) {
|
||||
const C = WallModel.TRAS_CAP, yLo = tr.top - C.DROP_MM, yHi = tr.top + C.THICK_MM;
|
||||
faces.push({ kind: 'trasraam', pts: [[-W / 2, yLo], [W / 2, yLo], [W / 2, yHi], [-W / 2, yHi]].map(([lx, ly]) => toWorld(p, lx, ly, zT + C.GAP_MM + C.THICK_MM)),
|
||||
n, color: WallModel.trimHex(tr.capColor), bias: 1.5 });
|
||||
}
|
||||
}
|
||||
(p.config.openings || []).filter(op => op.type !== 'schoorsteen').forEach(op => {
|
||||
if (WallModel.openingTopMax(op) <= y0) return;
|
||||
@@ -328,6 +334,17 @@ window.HousePdf = (() => {
|
||||
top.push({ x: O.x, y: Math.max(tI, tO), z: O.z });
|
||||
bottom.push({ x: O.x, y: Math.min(tI, tO) - h, z: O.z });
|
||||
}
|
||||
// Rooster op de gevel, onder de onderplaat.
|
||||
if (sg.fascia && sg.facadeUnder && edge.vent) {
|
||||
const V = RoofModel.VENT, d = RoofModel.ventFace(sg) + V.THICK_MM - (sg.a.x * sg.normal.x + sg.a.z * sg.normal.z);
|
||||
const vTop = [];
|
||||
for (let k = 0; k <= n; k++) {
|
||||
const I = lerp(sg.a, sg.b, k / n), q = { x: I.x + sg.normal.x * d, z: I.z + sg.normal.z * d };
|
||||
vTop.push({ x: q.x, y: sg.topAt(q) - h, z: q.z });
|
||||
}
|
||||
faces.push({ kind: 'dakrand', pts: vTop.concat(vTop.map(q => ({ x: q.x, y: q.y - V.HEIGHT_MM, z: q.z })).reverse()),
|
||||
n: { x: sg.normal.x, z: sg.normal.z }, color: WallModel.trimHex(edge.ventColor), bias: 2.5 });
|
||||
}
|
||||
faces.push({ kind: 'dakrand', pts: top.concat(bottom.reverse()), n: { x: sg.normal.x, z: sg.normal.z }, color: RoofModel.edgeColor(edge, sg), bias: 3 });
|
||||
});
|
||||
}
|
||||
@@ -371,7 +388,11 @@ window.HousePdf = (() => {
|
||||
items.push(WallModel.isStoneFinish(tf)
|
||||
? { label: `Trasraam (${st.trasraam.height} mm)`, value: `Steen ${tf}`, thumb: WallModel.stoneThumbUrl(tf, 64), color: WallModel.STONE_COLORS[tf] }
|
||||
: { label: `Trasraam (${st.trasraam.height} mm)`, value: 'Cementplaat', color: VIEW_COLORS.cementplaat });
|
||||
const tc = WallModel.TRIM_COLORS[st.trasraam.capColor];
|
||||
if (parts && tc && HouseModel.allWallPieces(parts).some(p => p.stats && p.stats.trasraamCapM > 0)) items.push({ label: 'Afdekker trasraam', value: tc.label, color: tc.hex });
|
||||
}
|
||||
const vc = parts && parts.roofEdge && parts.roofEdge.vent && parts.roofEdge.ventLengthMM > 0 && WallModel.TRIM_COLORS[parts.roofEdge.ventColor];
|
||||
if (vc) items.push({ label: 'Ventilatierooster', value: vc.label, color: vc.hex });
|
||||
(parts ? parts.units : state.units).forEach(u => {
|
||||
const cov = parts ? u.roof.covering : (u.roof.covering || 'dakleer');
|
||||
const c = RoofModel.COVERINGS[cov] || RoofModel.COVERINGS.dakleer;
|
||||
@@ -618,6 +639,8 @@ window.HousePdf = (() => {
|
||||
rows.push(['Onderplaat boeideel', fmt(e.soffitM2, 2) + ' m2']);
|
||||
}
|
||||
if (e.trimLengthM > 0) rows.push(['Daktrim', `${fmt(e.trimLengthM, 2)} m, ${e.trimHeight} mm hoog`]);
|
||||
if (e.ventLengthM > 0) rows.push(['Ventilatierooster', `${fmt(e.ventLengthM, 2)} m op de gevel onder de boeidelen, ${RoofModel.VENT.HEIGHT_MM} mm hoog, ${e.ventColor.toLowerCase()}`]);
|
||||
if (totals.trasraamCap && totals.trasraamCap.lengthM > 0) rows.push(['Afdekker trasraam', `${fmt(totals.trasraamCap.lengthM, 2)} m, ${totals.trasraamCap.color.toLowerCase()}`]);
|
||||
rows.push(['Boeideel-spots', e.spots + ' stuks']);
|
||||
rows.push(['Gevellampen', `${L.total} stuks (boven+onder ${L.both}, onder ${L.down}, boven ${L.up})`]);
|
||||
rows.push(['Binnenspots', `${L.indoor} stuks (plafond)`]);
|
||||
|
||||
+25
-10
@@ -1312,6 +1312,8 @@ function mountHouseEditor(container, callbacks) {
|
||||
const fmtDeg = (d) => String(Math.round(d * 10) / 10).replace('.', ',');
|
||||
const stoneOptions = Object.assign({}, ...WallModel.TRASRAAM_STONES.map(c => ({ [c]: `Steen ${c}` })));
|
||||
const trasraamFinishes = Object.assign({ cementplaat: 'Cementplaat' }, stoneOptions);
|
||||
const TRIM_OPTS = Object.fromEntries(Object.entries(WallModel.TRIM_COLORS).map(([k, c]) => [k, c.label]));
|
||||
const NO_WOLF = Object.fromEntries(Object.entries(UnitModel.ROOF_TYPES).filter(([k]) => k !== 'wolf'));
|
||||
const stucColors = Object.fromEntries(Object.entries(WallModel.STUC_COLORS).map(([k, c]) => [k, c.label]));
|
||||
const felsColors = Object.fromEntries(Object.entries(WallModel.FELS.COLORS).map(([k, c]) => [k, c.label]));
|
||||
const swatchOf = (hex) => `<div class="ins-swatch" style="background:${hex}"></div>`;
|
||||
@@ -1352,7 +1354,10 @@ function mountHouseEditor(container, callbacks) {
|
||||
(st.trasraam.enabled
|
||||
? UI.range('hs-trasraam-h', 'Hoogte', st.trasraam.height, { min: 100, max: 1000, step: 10, hint: 'Vanaf bovenkant vloer' }) +
|
||||
pair(sel('hs-trasraam-finish', 'Vormgeving', trasraamFinishes, st.trasraam.finish),
|
||||
WallModel.isStoneFinish(st.trasraam.finish) ? thumb(WallModel.stoneThumbUrl(st.trasraam.finish, 64), st.trasraam.finish) : '')
|
||||
WallModel.isStoneFinish(st.trasraam.finish) ? thumb(WallModel.stoneThumbUrl(st.trasraam.finish, 64), st.trasraam.finish) : '') +
|
||||
(WallModel.isStoneFinish(st.trasraam.finish)
|
||||
? pair(sel('hs-trasraam-cap', 'Afdekker', TRIM_OPTS, st.trasraam.capColor, { hint: 'Zetwerk op de steen waar de gevel erboven minder ver uitsteekt (rabat, felsplaat, stuc): 5° aflopend, neus 25 mm over de steen' }),
|
||||
swatchOf(WallModel.trimHex(st.trasraam.capColor))) : '')
|
||||
: '') },
|
||||
{ label: 'Onderzijde', html: toggle('hs-sandwich', 'Sandwichpanelen', st.sandwich,
|
||||
{ hint: `${SandwichModel.PANEL_WIDTH_MM} × ${SandwichModel.PANEL_LENGTH_MM} × ${SandwichModel.THICK_MM} mm rondom, vanaf bovenkant vloer ${SandwichModel.DEPTH_MM} mm naar beneden` }) +
|
||||
@@ -1371,6 +1376,7 @@ function mountHouseEditor(container, callbacks) {
|
||||
UI.onToggle('hs-trasraam', v => { st.trasraam.enabled = v; }, rerender);
|
||||
UI.onRange('hs-trasraam-h', v => { if (v > 0) st.trasraam.height = v; }, after);
|
||||
UI.onSel('hs-trasraam-finish', v => { st.trasraam.finish = v; }, rerender);
|
||||
UI.onSel('hs-trasraam-cap', v => { st.trasraam.capColor = v; }, rerender);
|
||||
UI.onToggle('hs-sandwich', v => { st.sandwich = v; }, rerender);
|
||||
UI.onRange('hs-ground', v => { if (v >= 0) st.groundLevel = v; }, after);
|
||||
}
|
||||
@@ -1381,9 +1387,9 @@ function mountHouseEditor(container, callbacks) {
|
||||
key: 'dak', label: 'Dak', order: 30,
|
||||
groups: () => {
|
||||
const r = state.settings.roof, hr = r.house;
|
||||
const wolfOk = HouseModel.houseRoofFits(state);
|
||||
const wolfOk = HouseModel.houseRoofFits(state) && !HouseModel.hasCover(state);
|
||||
houseRoofUi = hr.enabled && hr.form ? roofFormUi('hs', hr.form, {
|
||||
types: wolfOk || hr.form.type === 'wolf' ? null : Object.fromEntries(Object.entries(UnitModel.ROOF_TYPES).filter(([k]) => k !== 'wolf')),
|
||||
types: wolfOk || hr.form.type === 'wolf' ? null : NO_WOLF,
|
||||
notice: !wolfOk && hr.form.type === 'wolf' ? 'Wolfsdak alleen als de units samen een rechthoek vormen; bij deze L-/T-vorm wordt het een zadeldak.' : null,
|
||||
span: () => { const sh = HouseModel.houseRoofShape(state); return sh ? sh.span : 1000; },
|
||||
apply: () => HouseModel.applyGlobalSettings(state),
|
||||
@@ -1404,7 +1410,9 @@ function mountHouseEditor(container, callbacks) {
|
||||
{ label: 'Boeideel', html:
|
||||
UI.range('hs-overhang', 'Overstek', r.overhang, { min: RoofModel.OVERHANG_MIN, max: RoofModel.OVERHANG_MAX, step: 10, hint: 'Vanaf de gevel' }) +
|
||||
UI.range('hs-fascia-h', 'Hoogte', r.fasciaHeight, { min: 150, max: 500, step: 10 }) +
|
||||
sel('hs-fascia-color', 'Kleur', Object.fromEntries(Object.entries(RoofModel.FASCIA_COLORS).map(([k, c]) => [k, c.label])), r.fasciaColor) },
|
||||
sel('hs-fascia-color', 'Kleur', Object.fromEntries(Object.entries(RoofModel.FASCIA_COLORS).map(([k, c]) => [k, c.label])), r.fasciaColor) +
|
||||
toggle('hs-vent', 'Ventilatierooster', r.vent !== false, { hint: `${RoofModel.VENT.HEIGHT_MM} mm hoog op de gevel, direct onder alle boeidelen` }) +
|
||||
(r.vent !== false ? pair(sel('hs-vent-color', 'Kleur rooster', TRIM_OPTS, r.ventColor || 'antraciet'), swatchOf(WallModel.trimHex(r.ventColor))) : '') },
|
||||
{ label: 'Daktrim', html: num('hs-trim-h', 'Hoogte', r.trimHeight, { step: 5, hint: 'Bij units zonder boeidelen' }) },
|
||||
{ label: 'Palen overkapping', html:
|
||||
toggle('hs-posts', 'Palen', r.posts.enabled, { hint: `Onder een dak dat minstens de min. uitkraging buiten de vloer steekt (veranda); per unit: Overkapping. Nu ${parts ? parts.posts.count : 0} st.` }) +
|
||||
@@ -1426,6 +1434,8 @@ function mountHouseEditor(container, callbacks) {
|
||||
UI.onRange('hs-overhang', v => { if (v > 0) r.overhang = Math.min(RoofModel.OVERHANG_MAX, Math.max(RoofModel.OVERHANG_MIN, v)); }, after);
|
||||
UI.onRange('hs-fascia-h', v => { if (v > 0) r.fasciaHeight = v; }, after);
|
||||
UI.onSel('hs-fascia-color', v => { r.fasciaColor = v; }, rerender);
|
||||
UI.onToggle('hs-vent', v => { r.vent = v; }, rerender);
|
||||
UI.onSel('hs-vent-color', v => { r.ventColor = v; }, rerender);
|
||||
UI.onNum('hs-trim-h', v => { r.trimHeight = v; }, after, pos);
|
||||
UI.onToggle('hs-posts', v => { r.posts.enabled = v; }, rerender);
|
||||
UI.onToggle('hs-posts-side', v => { r.posts.sideWall = v; }, rerender);
|
||||
@@ -1889,7 +1899,7 @@ function mountHouseEditor(container, callbacks) {
|
||||
const f = (k) => `${id}-roof-${k}`;
|
||||
const groups = () => {
|
||||
const g = [
|
||||
{ label: 'Dakvorm', html: sel(f('type'), 'Vorm', o.types || UnitModel.ROOF_TYPES, form.type) + (o.notice ? note(o.notice) : '') +
|
||||
{ label: 'Dakvorm', html: sel(f('type'), 'Vorm', (typeof o.types === 'function' ? o.types() : o.types) || UnitModel.ROOF_TYPES, form.type) + (o.notice ? note(o.notice) : '') +
|
||||
(form.type === 'lessenaar' ? sel(f('dir'), 'Hoge zijde', SIDE_SHORT, form.dir) : '') +
|
||||
(UnitModel.hasRidge(form.type) ? sel(f('ridge'), 'Nok', UnitModel.RIDGES, form.ridge) : '') +
|
||||
UI.range(f('low'), sloped() ? 'Goot' : 'Hoogte', form.low, { min: 2100, max: LIM.eave, step: 10, hint: `Vanaf bovenkant vloer tot onderkant dak (max ${LIM.eave} mm)` }) }
|
||||
@@ -1959,6 +1969,7 @@ function mountHouseEditor(container, callbacks) {
|
||||
const form = UnitModel.roofForm(u.unit);
|
||||
const roofUi = roofFormUi('hp', form, {
|
||||
gable: true,
|
||||
types: () => HouseModel.hasCover(state, u.id) ? NO_WOLF : null,
|
||||
span: () => {
|
||||
const pu = partsOf();
|
||||
const s = UnitModel.WALL_SIDES.find(x => x.key === UnitModel.gableOf(form));
|
||||
@@ -2030,13 +2041,15 @@ function mountHouseEditor(container, callbacks) {
|
||||
UI.onToggle('hp-fascia', v => { u.roof.fascia = v; }, rerender);
|
||||
UI.onToggle('hp-steel-ridge', v => { u.roof.steelRidge = v; }, rerender);
|
||||
UI.onToggle('hp-roof-follow', v => { u.roof.followFloor = v; }, rerender);
|
||||
// Een overkapping maakt van een wolfsdak een zadeldak: dan het paneel opnieuw opbouwen.
|
||||
const afterCover = () => (form.type === 'wolf' ? rerender : after)();
|
||||
['f', 'r', 'b', 'l'].forEach(k => UI.onNum('hp-ext-' + k, v => {
|
||||
u.roof.extend = Object.assign({ f: 0, r: 0, b: 0, l: 0 }, u.roof.extend, { [k]: Math.max(0, Math.min(HouseModel.EXTEND_MAX, v)) });
|
||||
}, after));
|
||||
UI.onNum('hp-roof-w', v => { if (v >= 500) u.roof.deck.floor.width = v; }, after);
|
||||
UI.onNum('hp-roof-d', v => { if (v >= 500) u.roof.deck.floor.depth = v; }, after);
|
||||
UI.onNum('hp-roof-ox', v => { u.roof.offsetX = v; }, after);
|
||||
UI.onNum('hp-roof-oz', v => { u.roof.offsetZ = v; }, after);
|
||||
}, afterCover));
|
||||
UI.onNum('hp-roof-w', v => { if (v >= 500) u.roof.deck.floor.width = v; }, afterCover);
|
||||
UI.onNum('hp-roof-d', v => { if (v >= 500) u.roof.deck.floor.depth = v; }, afterCover);
|
||||
UI.onNum('hp-roof-ox', v => { u.roof.offsetX = v; }, afterCover);
|
||||
UI.onNum('hp-roof-oz', v => { u.roof.offsetZ = v; }, afterCover);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -2334,6 +2347,8 @@ function mountHouseEditor(container, callbacks) {
|
||||
const e = totals.roofEdge, rows = [];
|
||||
if (e.fasciaLengthM > 0) rows.push([`Boeidelen · ${e.fasciaHeight} mm`, f(e.fasciaLengthM, 2), 'm'], ['Onderplaat boeideel', f(e.soffitM2, 2), 'm²']);
|
||||
if (e.trimLengthM > 0) rows.push([`Daktrim · ${e.trimHeight} mm`, f(e.trimLengthM, 2), 'm']);
|
||||
if (e.ventLengthM > 0) rows.push([`Ventilatierooster · ${e.ventColor.toLowerCase()}`, f(e.ventLengthM, 2), 'm']);
|
||||
if (totals.trasraamCap.lengthM > 0) rows.push([`Afdekker trasraam · ${totals.trasraamCap.color.toLowerCase()}`, f(totals.trasraamCap.lengthM, 2), 'm']);
|
||||
rows.push(['Boeideel-spots', e.spots, 'st.'], ['Gevellampen', totals.lamps.total, 'st.'], ['Binnenspots', totals.lamps.indoor, 'st.']);
|
||||
cards.push(UI.specCard('Dakrand & verlichting', 'lightbulb', rows));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user