v0.4.9: naadwanden (2 delen, deur), kopbalken op naden, isolatie niet meer getekend
- HouseModel: naadwand per naad (ensureSeamWalls bij nieuwe woning en unit toevoegen), twee delen met beplating alleen aan de kamerzijde, openingen gespiegeld - WallModel: buitenzijde 'geen', thicknessOf eenzijdig - FloorModel: kopbalken (rims) voor vloer en dak op naden, ook in PDF en totalen - isolatie: 3D-lagen en filter verwijderd, berekening blijft Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
f163f4deb1
commit
9bd7faeaa6
+40
-7
@@ -135,7 +135,11 @@ function mountHouseEditor(container, callbacks) {
|
||||
if (kind === 'floor' && unitById(a)) unitById(a).unit.floor = activeEditor.getStateJson();
|
||||
else if (kind === 'wall' && unitById(a)) unitById(a).unit.walls[b] = activeEditor.getStateJson();
|
||||
else if (kind === 'roof' && unitById(a)) unitById(a).roof.deck = activeEditor.getStateJson();
|
||||
else if (kind === 'iw' && iwById(Number(a))) iwById(Number(a)).wall = activeEditor.getStateJson();
|
||||
else if (kind === 'iw' && iwById(Number(a))) {
|
||||
const iw = iwById(Number(a));
|
||||
iw.wall = activeEditor.getStateJson();
|
||||
if (iw.seam) iw.wall.materials = Object.assign({}, iw.wall.materials, { exterior: 'geen' }); // naadzijde blijft zonder plaat
|
||||
}
|
||||
}
|
||||
|
||||
function showPart(part) {
|
||||
@@ -172,7 +176,8 @@ function mountHouseEditor(container, callbacks) {
|
||||
activeEditor.loadStateJson(HouseModel.clone(u.roof.deck));
|
||||
} else if (kind === 'iw' && iwById(Number(a))) {
|
||||
HouseModel.applyGlobalSettings(state);
|
||||
HouseModel.interiorLayout(iwById(Number(a))); // breedte bijwerken
|
||||
if (iwById(Number(a)).seam) HouseModel.computeParts(state, { skip3D: true }); // breedte naadwand-deel
|
||||
else HouseModel.interiorLayout(iwById(Number(a))); // breedte bijwerken
|
||||
activeEditor = WallEditor.mount(host, { cameraKey: camKey(part), lockWidth: 'De lengte van een binnenwand volgt uit de tekening (overzicht).', lockSpacing: SPACING_LOCK_MSG });
|
||||
activeEditor.loadStateJson(HouseModel.clone(iwById(Number(a)).wall));
|
||||
} else {
|
||||
@@ -205,7 +210,15 @@ function mountHouseEditor(container, callbacks) {
|
||||
});
|
||||
if (parts.interior.length) {
|
||||
html += `<div class="hn-group"><div class="hn-item hn-unit hn-static"><span class="hn-label">${UI.icon('distribute-horizontal')}Binnenwanden</span></div>`;
|
||||
parts.interior.forEach(p => { html += item(`iw:${p.id}`, p.element, `${p.place.width} mm`, 'hn-sub', 'distribute-horizontal'); });
|
||||
const seen = new Set();
|
||||
parts.interior.forEach(p => {
|
||||
if (seen.has(p.id)) return; // naadwand: twee delen, één item
|
||||
seen.add(p.id);
|
||||
if (p.seam) {
|
||||
const els = parts.interior.filter(x => x.id === p.id).map(x => x.element).join(', ');
|
||||
html += item(`iw:${p.id}`, `Naadwand ${p.seam.a}|${p.seam.b}`, els, 'hn-sub', 'layout-split');
|
||||
} else html += item(`iw:${p.id}`, p.element, `${p.place.width} mm`, 'hn-sub', 'distribute-horizontal');
|
||||
});
|
||||
html += `</div>`;
|
||||
}
|
||||
document.getElementById('house-nav-tree').innerHTML = html;
|
||||
@@ -234,6 +247,7 @@ function mountHouseEditor(container, callbacks) {
|
||||
const side = ['rechts', 'achter', 'links', 'voor'].find(s => !taken.has(s)) || 'rechts';
|
||||
const id = HouseModel.nextUnitId(state);
|
||||
state.units.push(HouseModel.createUnitEntry(id, { to: parent.id, side, align: 'start', offset: 0 }, { width: 3000, depth: 3000, windowOn: [] }));
|
||||
HouseModel.ensureSeamWalls(state, id); // tussenwand met deur op de nieuwe naad
|
||||
selection = { type: 'unit', id };
|
||||
showPart('overzicht');
|
||||
}
|
||||
@@ -299,7 +313,7 @@ function mountHouseEditor(container, callbacks) {
|
||||
let dakVisible = true;
|
||||
// Opgeslagen camerastand gaat voor; anders eenmalig passend maken.
|
||||
let cameraFitted = CameraMemory.restore(overviewCamKey, camera, controls);
|
||||
let beplatingVisible = true, isolatieVisible = true, lampenVisible = true;
|
||||
let beplatingVisible = true, lampenVisible = true;
|
||||
let fullRender = false;
|
||||
let skyMode = Skybox.getMode();
|
||||
const skyEnv = Skybox.createEnvironment(scene);
|
||||
@@ -308,12 +322,10 @@ function mountHouseEditor(container, callbacks) {
|
||||
// en plafondplaten, dakleer en boeideel/daktrim.
|
||||
createViewFilter(document.getElementById('ho-toolbar-3d'), [
|
||||
{ key: 'beplating', label: 'Beplating' },
|
||||
{ key: 'isolatie', label: 'Isolatie' },
|
||||
{ key: 'dak', label: 'Dak' },
|
||||
{ key: 'lampen', label: 'Lampen' }
|
||||
], (v) => {
|
||||
beplatingVisible = v.beplating;
|
||||
isolatieVisible = v.isolatie;
|
||||
dakVisible = v.dak;
|
||||
lampenVisible = v.lampen;
|
||||
refresh({ keepProps: true });
|
||||
@@ -725,6 +737,8 @@ function mountHouseEditor(container, callbacks) {
|
||||
|
||||
function renderIwProps(iw, warn) {
|
||||
const p = parts.interior.find(x => x.id === iw.id);
|
||||
if (iw.seam) return renderSeamProps(iw, warn);
|
||||
if (!p) { selection = null; return renderProps(); }
|
||||
propsEl.innerHTML = warn + head('distribute-horizontal', p.element, `Binnenwand · ${p.place.width} mm`) +
|
||||
cols(
|
||||
section('Positie', 'crosshair', num('hi-x1', 'Begin X', iw.x1) + num('hi-z1', 'Begin Y', iw.z1) + num('hi-x2', 'Eind X', iw.x2) + num('hi-z2', 'Eind Y', iw.z2)),
|
||||
@@ -737,6 +751,25 @@ function mountHouseEditor(container, callbacks) {
|
||||
UI.onNum('hi-height', v => { if (v >= 500) iw.wall.wall.heightAll = iw.wall.wall.heightLeft = iw.wall.wall.heightRight = v; }, after);
|
||||
}
|
||||
|
||||
// Naadwand: twee delen (één per unit), één set openingen en maten.
|
||||
function renderSeamProps(iw, warn) {
|
||||
const leaves = parts.interior.filter(x => x.id === iw.id);
|
||||
const title = `Naadwand ${iw.seam.a} | ${iw.seam.b}`;
|
||||
propsEl.innerHTML = warn + head('layout-split', title, leaves.length ? `${leaves.length} delen` : 'vervalt') +
|
||||
(leaves.length ? '' : UI.warn(`Unit ${iw.seam.a} en ${iw.seam.b} staan niet (meer) tegen elkaar; deze naadwand wordt niet gebouwd.`)) +
|
||||
cols(
|
||||
section('Opbouw', 'layers',
|
||||
num('hi-thick', 'Dikte per deel', HouseModel.thicknessOf(iw.wall), { step: 5, hint: 'Regelwerk + beplating aan de kamerzijde; naadzijde zonder plaat' }) +
|
||||
num('hi-height', 'Hoogte', iw.wall.wall.heightAll)),
|
||||
UI.specCard('Delen', 'layout-split', leaves.map(l => [`${l.element} (unit ${l.seamUnit})`, l.place.width, 'mm']))) +
|
||||
info('Tussenwand op de naad, per unit een eigen deel dat tegen het andere aan staat. Openingen gelden voor beide delen (de deur loopt door).') +
|
||||
actions(
|
||||
button('Openingen bewerken', 'pencil-square', `data-go="iw:${iw.id}"`),
|
||||
button('Verwijderen', 'trash', `data-remove-iw="${iw.id}"`, 'ui-btn-danger'));
|
||||
UI.onNum('hi-thick', v => { if (v >= 40) HouseModel.setThickness(iw.wall, v); }, after);
|
||||
UI.onNum('hi-height', v => { if (v >= 500) iw.wall.wall.heightAll = iw.wall.wall.heightLeft = iw.wall.wall.heightRight = v; }, after);
|
||||
}
|
||||
|
||||
// Woning-instellingen (niets geselecteerd): alles wat voor de hele woning
|
||||
// geldt, in tabbladen.
|
||||
function renderHouseProps(warn) {
|
||||
@@ -857,7 +890,7 @@ function mountHouseEditor(container, callbacks) {
|
||||
|
||||
// --- Alles opnieuw doorrekenen ---
|
||||
function refresh(opts) {
|
||||
parts = HouseModel.computeParts(state, { wallMaterials, floorMaterials, roofMaterials, lightingMaterials, sandwichMaterials, beplatingVisible, isolatieVisible, lampenVisible });
|
||||
parts = HouseModel.computeParts(state, { wallMaterials, floorMaterials, roofMaterials, lightingMaterials, sandwichMaterials, beplatingVisible, lampenVisible });
|
||||
const totals = HouseModel.computeTotals(parts);
|
||||
|
||||
if (houseGroup) scene.remove(houseGroup);
|
||||
|
||||
Reference in New Issue
Block a user