v0.4.10: wandhoogtes gekoppeld, middenpunt (nok), binnenspots langs naadwanden
- WallModel: optioneel middenpunt (heightMid, topLine), bovenregels in verstek; stijlen, openingen, beplating, doek, latwerk, BOM, 2D en PDF volgen de knik - wand-editor: schakelaar "Middenpunt (nok)" + nokhoogte, links/rechts = goothoogte - UnitModel.syncWallHeights: tegenoverliggende wand gespiegeld, haakse wanden vlak op de hoekhoogtes; wallPieces met nok per stuk - LightingModel.computeIndoor: raster vanaf binnenzijde eigen naadwanddeel Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
9bd7faeaa6
commit
9126588df7
+44
-3
@@ -174,7 +174,12 @@ window.UnitModel = (() => {
|
||||
const fullConfig = WallModel.configFromState(wallState);
|
||||
const W = wallLayout.width;
|
||||
const hL = wallState.wall.heightLeft, hR = wallState.wall.heightRight;
|
||||
const heightAt = (u) => hL + (u / W) * (hR - hL);
|
||||
// Middenpunt (nok) midden op de wand; een stuk krijgt de nok alleen als
|
||||
// die erin valt, anders de daklijn ter plaatse als gewone helling.
|
||||
const hM = wallState.wall.heightMid > 0 ? Math.max(wallState.wall.heightMid, hL, hR) : null;
|
||||
const pU = W / 2;
|
||||
const heightAt = (u) => hM === null ? hL + (u / W) * (hR - hL)
|
||||
: u <= pU ? hL + (u / pU) * (hM - hL) : hM + ((u - pU) / (W - pU)) * (hR - hM);
|
||||
const multi = wallLayout.pieces.length > 1;
|
||||
const used = new Set();
|
||||
|
||||
@@ -182,8 +187,10 @@ window.UnitModel = (() => {
|
||||
const openings = fullConfig.openings
|
||||
.filter(op => op.x >= a - EPS && op.x + op.w <= b + EPS)
|
||||
.map(op => { used.add(op.id); return { id: op.id, type: op.type, w: op.w, h: op.h, y: op.y, anchor: 'left', offset: op.x - a }; });
|
||||
const hasPeak = hM !== null && a < pU - 1 && b > pU + 1;
|
||||
const params = Object.assign({}, wallState.wall, {
|
||||
width: b - a, heightLeft: Math.round(heightAt(a)), heightRight: Math.round(heightAt(b))
|
||||
width: b - a, heightLeft: Math.round(heightAt(a)), heightRight: Math.round(heightAt(b)),
|
||||
heightMid: hasPeak ? hM : null, peakX: hasPeak ? pU - a : undefined
|
||||
});
|
||||
const config = WallModel.buildConfig(params, openings);
|
||||
return {
|
||||
@@ -197,6 +204,40 @@ window.UnitModel = (() => {
|
||||
return { pieces, dropped, fullConfig };
|
||||
}
|
||||
|
||||
// Wandhoogtes koppelen, zodat er altijd een logisch dak op past. De
|
||||
// bewerkte wand (side) bepaalt de dakvorm:
|
||||
// - de tegenoverliggende wand krijgt dezelfde hoogtes gespiegeld (van
|
||||
// buitenaf gezien wisselen links en rechts), incl. middenpunt (nok);
|
||||
// - de twee haakse wanden worden vlak op de hoogte van de hoek waar ze
|
||||
// op aansluiten (goothoogte bij een lessenaar- of zadeldak).
|
||||
// Voorbeeld: west zuid hoger dan noord -> oost ook, noordwand vlak op de
|
||||
// lage, zuidwand vlak op de hoge hoogte. Muteert state.
|
||||
// Welke haakse wand zit aan de linker/rechterkant (van buitenaf gezien).
|
||||
const WALL_ENDS = {
|
||||
voor: { left: 'rechts', right: 'links' },
|
||||
achter: { left: 'links', right: 'rechts' },
|
||||
links: { left: 'voor', right: 'achter' },
|
||||
rechts: { left: 'achter', right: 'voor' }
|
||||
};
|
||||
const OPPOSITE = { voor: 'achter', achter: 'voor', links: 'rechts', rechts: 'links' };
|
||||
function syncWallHeights(state, side) {
|
||||
const w = state.walls[side].wall;
|
||||
const mid = w.heightMid > 0 ? w.heightMid : null;
|
||||
const set = (key, hL, hR, hM) => {
|
||||
const t = state.walls[key].wall;
|
||||
t.heightLeft = hL; t.heightRight = hR; t.heightMid = hM;
|
||||
t.heightAll = hM === null && hL === hR ? hL : w.heightAll;
|
||||
};
|
||||
set(OPPOSITE[side], w.heightRight, w.heightLeft, mid);
|
||||
set(WALL_ENDS[side].left, w.heightLeft, w.heightLeft, null);
|
||||
set(WALL_ENDS[side].right, w.heightRight, w.heightRight, null);
|
||||
}
|
||||
// Hoogste punt van een wand (incl. nok).
|
||||
function wallTopOf(wallState) {
|
||||
const w = wallState.wall;
|
||||
return Math.max(w.heightLeft, w.heightRight, w.heightMid > 0 ? w.heightMid : 0);
|
||||
}
|
||||
|
||||
function validateState(design) {
|
||||
if (!design.floor) throw new Error('veld "floor" ontbreekt');
|
||||
try { FloorModel.validateState(design.floor); } catch (err) { throw new Error('vloer: ' + err.message); }
|
||||
@@ -210,5 +251,5 @@ window.UnitModel = (() => {
|
||||
}
|
||||
}
|
||||
|
||||
return { WALL_SIDES, CORNER_MODES, clone, createDefaultState, localToWorld, computeLayout, wallPieces, validateState };
|
||||
return { WALL_SIDES, CORNER_MODES, clone, createDefaultState, localToWorld, computeLayout, wallPieces, syncWallHeights, wallTopOf, validateState };
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user