v0.7.3: elektraleidingen nooit meer door een raam of deur (makeOpeningTest): een stijgleiding boven/onder een opening (wcd onder een raam) gaat eerst op dezelfde hoogte opzij tot naast de opening, langs dezelfde wand met een deur of raam ertussen via het plafond, gevellampen om verspringende gevelhoeken heen en het uit elkaar schuiven van buizen eindigt nooit in een opening (alle modellen 0 kruisingen); felsplaten als gevelafwerking (zink/antraciet/zwart, per woning, wand of wandstuk, opbouw als verticale rabat, kleuren gedeeld met het felsdak, in 3D, PDF en kosten); felsplaat op dak én gevel = geen boeideel, de dakplaat zet om over de rand zonder opstand, een boeideel ernaast stopt gelijk met zo'n rand (ook naast daktrim); zijwand bij een overkapping (Palen overkapping › Zijwand) in plaats van een hoekpaal, gestuukt, met de bekleding van de gevel in hetzelfde vlak aan de buitenkant (in 3D, plattegrond, PDF, DXF en kosten); model Reest (12,9 × 7,85 m, lessenaarsdak hoog aan de noordgevel over twee units in één vlak, overkapping bij de voordeur met witte zijwand, aanbouw met plat dak en daktrim, zuidgevel en dak in antraciet felsplaten, verder verticale rabat)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
89cadbebf7
commit
51921650e3
+59
-5
@@ -72,6 +72,50 @@ window.WallModel = (() => {
|
||||
return mat;
|
||||
}
|
||||
|
||||
// Felsplaten (staande naad) op de gevel: zelfde opbouw als verticale rabat (doek, latten, bekleding), alleen het
|
||||
// materiaal verschilt. Kleuren ook voor het dak (RoofModel.FELS). In 3D de naden als textuur over het blok.
|
||||
const FELS = {
|
||||
SEAM_MM: 500, TILE_SEAMS: 6,
|
||||
COLORS: {
|
||||
zink: { label: 'Zink', hex: '#8e9497' },
|
||||
antraciet: { label: 'Antraciet', hex: '#3d4146' },
|
||||
zwart: { label: 'Zwart', hex: '#1f2022' }
|
||||
}
|
||||
};
|
||||
const isFelsColor = (key) => !!FELS.COLORS[key];
|
||||
const felsHex = (key) => (FELS.COLORS[key] || FELS.COLORS.antraciet).hex;
|
||||
const felsMaterials = {};
|
||||
function felsMaterial(key) {
|
||||
const k = isFelsColor(key) ? key : 'antraciet';
|
||||
if (felsMaterials[k]) return felsMaterials[k];
|
||||
let mat;
|
||||
const canvas = typeof document !== 'undefined' && document.createElement('canvas');
|
||||
const ctx = canvas && canvas.getContext && canvas.getContext('2d');
|
||||
if (!ctx) mat = new THREE.MeshStandardMaterial({ color: felsHex(k), roughness: 0.4, metalness: 0.55 });
|
||||
else {
|
||||
const B = 100, N = FELS.TILE_SEAMS; // 5 mm/px
|
||||
canvas.width = B * N;
|
||||
canvas.height = 16;
|
||||
const base = new THREE.Color(felsHex(k));
|
||||
const shade = (f) => '#' + base.clone().multiplyScalar(f).getHexString();
|
||||
const col = (a, b, color) => { ctx.fillStyle = color; ctx.fillRect(a, 0, b - a, canvas.height); };
|
||||
for (let i = 0; i < N; i++) {
|
||||
const a = i * B, f = 0.97 + ((i * 29) % 7) / 100; // per baan net iets anders
|
||||
col(a, a + B, shade(f));
|
||||
col(a + 6, a + 14, shade(f * 1.04)); // lichte zetting naast de naad
|
||||
col(a, a + 2, shade(f * 0.6)); // schaduw van de naad
|
||||
col(a + 2, a + 5, shade(f * 1.35)); // staande naad (licht)
|
||||
}
|
||||
const tex = new THREE.CanvasTexture(canvas);
|
||||
tex.wrapS = tex.wrapT = THREE.RepeatWrapping;
|
||||
tex.repeat.set(1000 / (FELS.SEAM_MM * N), 1);
|
||||
tex.anisotropy = 8;
|
||||
mat = new THREE.MeshStandardMaterial({ color: 0xffffff, map: tex, roughness: 0.4, metalness: 0.55 });
|
||||
}
|
||||
felsMaterials[k] = mat;
|
||||
return mat;
|
||||
}
|
||||
|
||||
function claddingOffset(buitenMateriaal, stone, stuc) {
|
||||
if (buitenMateriaal === 'vochtdoek') return 2 * BATTEN.thick + CLADDING_THICK_MM;
|
||||
if (buitenMateriaal !== 'cementplaat') return 0;
|
||||
@@ -121,6 +165,14 @@ window.WallModel = (() => {
|
||||
return mat;
|
||||
}
|
||||
|
||||
// Materiaal van een gevelbekleding (UV in meters): felsplaten, steen, stuc of rabat; null = kale plaat.
|
||||
function claddingMaterial(f) {
|
||||
if (isFelsColor(f.fels)) return felsMaterial(f.fels);
|
||||
if (isStoneFinish(f.stone)) return stoneMaterial(f.stone);
|
||||
if (isStucColor(f.stuc)) return stucMaterial(f.stuc);
|
||||
return f.rabatColor ? rabatMaterial(f.rabatColor, f.cladding) : null;
|
||||
}
|
||||
|
||||
// Hoogte vanaf het loopvlak (= onderkant van de wand).
|
||||
const TRASRAAM_DEFAULT_MM = 350;
|
||||
function trasraamFor(heightMM, finish) {
|
||||
@@ -763,6 +815,7 @@ window.WallModel = (() => {
|
||||
const skinFrom = opts.skinFrom > 0 ? opts.skinFrom : 0;
|
||||
const painted = !!opts.painted;
|
||||
const stone = buitenMateriaal === 'cementplaat' && isStoneFinish(opts.stone) ? opts.stone : null;
|
||||
const felsKey = buitenMateriaal === 'vochtdoek' && isFelsColor(opts.fels) ? opts.fels : null;
|
||||
// spaanplaatBelow: naadwand geheel in één unit; onder het dak van de andere unit is het een binnenwand.
|
||||
const spaanplaatBelow = !!opts.spaanplaatBelow && skinFrom > 0 && buitenMateriaal === 'vochtdoek';
|
||||
const rabatOn = buitenMateriaal === 'vochtdoek' && buitenVisible && show('gevel');
|
||||
@@ -792,7 +845,7 @@ window.WallModel = (() => {
|
||||
let spaanplaatBuitenAreaM2 = 0;
|
||||
let spaanplaatBuitenVolumeM3 = 0;
|
||||
let battenLengthM = 0, battenVolumeM3 = 0, battenCount = 0, battenPieces = 0;
|
||||
let rabatAreaM2 = 0;
|
||||
let rabatAreaM2 = 0, felsAreaM2 = 0;
|
||||
let trasraamAreaM2 = 0, trasraamVolumeM3 = 0;
|
||||
let stoneAreaM2 = 0, stoneIsolatieM3 = 0;
|
||||
let stucAreaM2 = 0;
|
||||
@@ -1294,6 +1347,7 @@ window.WallModel = (() => {
|
||||
return shape;
|
||||
}) : [];
|
||||
rabatAreaM2 = rabatShapes.reduce((sum, shape) => sum + shapeAreaWithHoles(shape), 0);
|
||||
if (felsKey) { felsAreaM2 = rabatAreaM2; rabatAreaM2 = 0; }
|
||||
if (rabatOn && rabatShapes.length) {
|
||||
const geo = new THREE.ExtrudeGeometry(rabatShapes, { steps: 1, depth: rabatDepthMM * toM, bevelEnabled: false });
|
||||
const gridM = (facade && facade.gridY0 !== undefined ? facade.gridY0 : skinStartY(trasraam)) * toM;
|
||||
@@ -1303,7 +1357,7 @@ window.WallModel = (() => {
|
||||
if (Math.abs(nrm.getX(k)) > 0.5) uv.setXY(k, z, y); else if (Math.abs(nrm.getY(k)) > 0.5) uv.setXY(k, x, z); else uv.setXY(k, x, y);
|
||||
}
|
||||
uv.needsUpdate = true;
|
||||
const mesh = new THREE.Mesh(geo, rabatMaterial(opts.rabatColor, cladding));
|
||||
const mesh = new THREE.Mesh(geo, felsKey ? felsMaterial(felsKey) : rabatMaterial(opts.rabatColor, cladding));
|
||||
mesh.position.set(0, 0, zDoek);
|
||||
mesh.castShadow = true;
|
||||
mesh.receiveShadow = true;
|
||||
@@ -1391,7 +1445,7 @@ window.WallModel = (() => {
|
||||
stats: {
|
||||
woodVolumeM3, spaanplaatVolumeM3, spaanplaatAreaM2, cementplaatVolumeM3, cementplaatAreaM2, doekAreaM2,
|
||||
spaanplaatBuitenAreaM2, spaanplaatBuitenVolumeM3, horizBeamCount,
|
||||
battenLengthM, battenVolumeM3, battenCount, battenPieces, rabatAreaM2, trasraamAreaM2, trasraamVolumeM3, trasraamStoneAreaM2, trasraamIsolatieM3, stoneAreaM2, stoneIsolatieM3, stucAreaM2
|
||||
battenLengthM, battenVolumeM3, battenCount, battenPieces, rabatAreaM2, felsAreaM2, trasraamAreaM2, trasraamVolumeM3, trasraamStoneAreaM2, trasraamIsolatieM3, stoneAreaM2, stoneIsolatieM3, stucAreaM2
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1620,8 +1674,8 @@ window.WallModel = (() => {
|
||||
}
|
||||
|
||||
return {
|
||||
STANDARD_BEAM, STOCK_LENGTHS_MM, CORNER_STUDS, EXTERIOR_MATERIALS, OPENING_TYPES, BATTEN, CLADDING_DIRECTIONS, CLADDING_THICK_MM, RABAT, RABAT_COLORS, rabatHex, STUC, STUC_COLORS, isStucColor, stucHex, claddingOffset, cornerExt, TRASRAAM_DEFAULT_MM, STONE, STONE_COLORS, TRASRAAM_STONES, isStoneFinish, stoneThumbUrl, trasraamFor, skinStartY, computeBattens, planPurchase, purchaseText,
|
||||
stoneMaterial, stucMaterial, sheathingHoles, skinSegmentsAtY, topLine, skinConfig, wallTopPoints, topPlateOutlines, openingTopAt, openingTopMax, openingArea, openingSpanAtY,
|
||||
STANDARD_BEAM, STOCK_LENGTHS_MM, CORNER_STUDS, EXTERIOR_MATERIALS, OPENING_TYPES, BATTEN, CLADDING_DIRECTIONS, CLADDING_THICK_MM, RABAT, RABAT_COLORS, rabatHex, FELS, isFelsColor, felsHex, STUC, STUC_COLORS, isStucColor, stucHex, claddingOffset, cornerExt, TRASRAAM_DEFAULT_MM, STONE, STONE_COLORS, TRASRAAM_STONES, isStoneFinish, stoneThumbUrl, trasraamFor, skinStartY, computeBattens, planPurchase, purchaseText,
|
||||
stoneMaterial, stucMaterial, felsMaterial, claddingMaterial, sheathingHoles, skinSegmentsAtY, topLine, skinConfig, wallTopPoints, topPlateOutlines, openingTopAt, openingTopMax, openingArea, openingSpanAtY,
|
||||
validateState, resolveOpenings, computeBOM, groupBOM, buildConfig, configFromState, thicknessOf, computeFrame,
|
||||
createMaterials, build3D, computeSpecs
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user