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
+30
-27
@@ -114,8 +114,12 @@ window.FloorModel = (() => {
|
||||
// ----------------------------------------------------------
|
||||
// Balkverdeling: zelfde algoritme (calculateSegmentPositions) als de wand.
|
||||
// params = state.floor (of de ruwe invoerwaarden uit de editor).
|
||||
// rims (optioneel): { front, back } — kopbalk langs de voor-/achterrand
|
||||
// (haaks op de balken), bijv. op een naad tussen twee units waar de
|
||||
// modules weer aan elkaar gemonteerd worden. De langsbalken worden daar
|
||||
// met één balkbreedte ingekort. Langs de zijranden ligt altijd al een balk.
|
||||
// ----------------------------------------------------------
|
||||
function computeFrame(params) {
|
||||
function computeFrame(params, rims) {
|
||||
const width = params.width || 2000;
|
||||
const depth = params.depth || 2000;
|
||||
const joistW = params.joistWidth || 70;
|
||||
@@ -131,7 +135,9 @@ window.FloorModel = (() => {
|
||||
calculateSegmentPositions(width - joistW, minSp, maxSp).forEach(p => joists.push(leftJoistX + p));
|
||||
joists = [...new Set(joists.map(x => Math.round(x)))].sort((a, b) => a - b);
|
||||
|
||||
return { joists, width, depth, joistW, joistH, underlayThick };
|
||||
const r = { front: !!(rims && rims.front), back: !!(rims && rims.back) };
|
||||
const joistLen = depth - (r.front ? joistW : 0) - (r.back ? joistW : 0);
|
||||
return { joists, width, depth, joistW, joistH, underlayThick, rims: r, joistLen };
|
||||
}
|
||||
|
||||
// Bovenkant vloer (mm) = waar de wanden van een unit op staan.
|
||||
@@ -151,8 +157,10 @@ window.FloorModel = (() => {
|
||||
const { width, depth, joists, joistW, joistH, underlayThick } = calcData;
|
||||
const widthM = width * toM, depthM = depth * toM;
|
||||
const joistWM = joistW * toM, joistHM = joistH * toM, underlayM = underlayThick * toM;
|
||||
const rimCount = calcData.rims ? (calcData.rims.front ? 1 : 0) + (calcData.rims.back ? 1 : 0) : 0;
|
||||
const joistLenM = (calcData.joistLen || depth) * toM;
|
||||
|
||||
const joistWoodM3 = joists.length * joistWM * joistHM * depthM;
|
||||
const joistWoodM3 = joists.length * joistWM * joistHM * joistLenM + rimCount * joistWM * joistHM * widthM;
|
||||
const joistWoodKg = joistWoodM3 * DENSITY_WOOD_KGM3;
|
||||
|
||||
const grossAreaM2 = widthM * depthM;
|
||||
@@ -197,8 +205,9 @@ window.FloorModel = (() => {
|
||||
}
|
||||
|
||||
// Alles in één keer vanuit een vloer-state (handig voor de unit).
|
||||
function computeFromState(state) {
|
||||
const calcData = computeFrame(state.floor);
|
||||
// rims: zie computeFrame.
|
||||
function computeFromState(state, rims) {
|
||||
const calcData = computeFrame(state.floor, rims);
|
||||
const resolvedOpenings = resolveFloorOpenings(state.openings || [], calcData.width, calcData.depth, calcData.joists, calcData.joistW);
|
||||
const chassisData = computeChassisWheels(state.chassis, calcData.width, calcData.depth);
|
||||
return { calcData, resolvedOpenings, chassisData };
|
||||
@@ -208,9 +217,6 @@ window.FloorModel = (() => {
|
||||
return {
|
||||
woodMaterial: new THREE.MeshStandardMaterial({ color: 0xc29b62, roughness: 0.6 }),
|
||||
osbMaterial: new THREE.MeshStandardMaterial({ color: 0xcda86a, roughness: 0.75, side: THREE.DoubleSide }),
|
||||
isolatieMaterial: new THREE.MeshStandardMaterial({
|
||||
color: 0xffe08c, roughness: 0.9, transparent: true, opacity: 0.5, side: THREE.DoubleSide
|
||||
}),
|
||||
wheelMaterial: new THREE.MeshStandardMaterial({ color: 0x151515, roughness: 0.5 })
|
||||
};
|
||||
}
|
||||
@@ -220,12 +226,11 @@ window.FloorModel = (() => {
|
||||
// Z = -diepte/2), Y = dikte (balkhoogte + OSB). Balken en isolatie zijn
|
||||
// simpele dozen; de OSB-onderlaag is een geëxtrudeerd Shape met ronde
|
||||
// uitsparingen voor de doorvoeren.
|
||||
// opts: { materials, osbVisible, isolatieVisible }
|
||||
// opts: { materials, osbVisible }
|
||||
// ----------------------------------------------------------
|
||||
function build3D(calcData, resolvedOpenings, chassisData, opts) {
|
||||
const { woodMaterial, osbMaterial, isolatieMaterial, wheelMaterial } = opts.materials;
|
||||
const { woodMaterial, osbMaterial, wheelMaterial } = opts.materials;
|
||||
const osbVisible = opts.osbVisible !== false;
|
||||
const isolatieVisible = opts.isolatieVisible !== false;
|
||||
const floorGroup3D = new THREE.Group();
|
||||
|
||||
const toM = 0.001;
|
||||
@@ -233,28 +238,26 @@ window.FloorModel = (() => {
|
||||
const widthM = width * toM, depthM = depth * toM;
|
||||
const joistWM = joistW * toM, joistHM = joistH * toM, underlayM = underlayThick * toM;
|
||||
|
||||
// A. VLOERBALKEN — dozen, lopen over de volle diepte door.
|
||||
// A. VLOERBALKEN — dozen over de diepte (ingekort bij een kopbalk), plus
|
||||
// de kopbalken (rims) over de volle breedte.
|
||||
const rims = calcData.rims || {};
|
||||
const joistLenM = (calcData.joistLen || depth) * toM;
|
||||
const joistZ = ((rims.front ? joistW : 0) - (rims.back ? joistW : 0)) / 2 * toM;
|
||||
joists.forEach(xMM => {
|
||||
const geo = new THREE.BoxGeometry(joistWM, joistHM, depthM);
|
||||
const geo = new THREE.BoxGeometry(joistWM, joistHM, joistLenM);
|
||||
const mesh = new THREE.Mesh(geo, woodMaterial);
|
||||
mesh.position.set(xMM * toM, joistHM / 2, 0);
|
||||
mesh.position.set(xMM * toM, joistHM / 2, joistZ);
|
||||
mesh.castShadow = true;
|
||||
floorGroup3D.add(mesh);
|
||||
});
|
||||
[['front', -1], ['back', 1]].filter(([k]) => rims[k]).forEach(([, sign]) => {
|
||||
const mesh = new THREE.Mesh(new THREE.BoxGeometry(widthM, joistHM, joistWM), woodMaterial);
|
||||
mesh.position.set(0, joistHM / 2, sign * (depthM - joistWM) / 2);
|
||||
mesh.castShadow = true;
|
||||
floorGroup3D.add(mesh);
|
||||
});
|
||||
|
||||
// B. ISOLATIE — vult elk balkvak (tussen twee opeenvolgende balken) over
|
||||
// de volle balkhoogte/diepte. Zelfde "leegte tussen het regelwerk"-
|
||||
// gedachte als bij wall.js, hier ook echt gevisualiseerd als laag.
|
||||
const bays = computeBays(joists, joistW);
|
||||
bays.forEach(bay => {
|
||||
const bayWidthM = (bay.right - bay.left) * toM;
|
||||
if (bayWidthM <= 0) return;
|
||||
const geo = new THREE.BoxGeometry(bayWidthM, joistHM, depthM);
|
||||
const mesh = new THREE.Mesh(geo, isolatieMaterial);
|
||||
mesh.position.set(((bay.left + bay.right) / 2) * toM, joistHM / 2, 0);
|
||||
mesh.visible = isolatieVisible;
|
||||
floorGroup3D.add(mesh);
|
||||
});
|
||||
// (Isolatie wordt niet getekend; de leegte-inhoud zit in computeSpecs.)
|
||||
|
||||
// C. OSB-ONDERLAAG — één geëxtrudeerd vlak over de volle vloer, met
|
||||
// ronde uitsparingen voor de doorvoeren. Shape wordt opgebouwd in
|
||||
|
||||
Reference in New Issue
Block a user