v0.6.0: ruimtes (verfemmer: functie, netto m², vloerafwerking, FIBO-wandpanelen, eigen verfkleur, vals plafond, ruimtestaat op de PDF), inrichting (sanitair, keuken, kookeiland, kasten, bed, zithoek, boiler; slepen met snappen op het wandvlak, draaien, kosten), kozijnen met deurrichting, glasdeur en schuifdeuren (inbouw/opbouw, deuren open in de loopmodus) plus dagkanten, gevel stucwerk en wandstukken splitsen met eigen gevel, dak over de hele woning met overkapping, geschilderd plafond, model Amstel als nieuw ontwerp, kosten en prijzen uit kosten/intern.csv en kosten/leveranciers.csv (CostCsv); easter egg verwijderd; overbodige comments opgeschoond (alleen copyright, uitzonderingen en valkuilen blijven)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
b5510d56c7
commit
ceda0b554d
+3
-40
@@ -4,18 +4,8 @@
|
||||
* Alle rechten voorbehouden. Gebruik uitsluitend met schriftelijke toestemming.
|
||||
* Zie LICENTIE.md.
|
||||
*/
|
||||
// ============================================================
|
||||
// wall/wall-pdf.js — ENIGE bron van het wand-tekenblad (A3 liggend):
|
||||
// frame-materiaallijst, plaatmateriaal, vooraanzicht met posnums en
|
||||
// maatketens, bovenaanzicht (doorsnede regelwerk + beplating), zijaanzicht
|
||||
// (laagopbouw) en titelblok. Gebruikt door de losse wand-editor (1 blad) en
|
||||
// door de unit (1 blad per wand in de gezamenlijke PDF).
|
||||
// Plain script, geladen na wall-model.js en core/pdf-sheet.js.
|
||||
// ============================================================
|
||||
|
||||
window.WallPdf = (() => {
|
||||
// Tekent één volledig wandblad op de HUIDIGE pagina van `doc`.
|
||||
// opts: { buitenMateriaal, cladding, trasraam, skinExt, project, titel, element, blad, lamps: [{ u, y }] }
|
||||
function drawSheet(doc, CONFIG, calcData, opts) {
|
||||
const buitenMateriaal = opts.buitenMateriaal || 'vochtdoek';
|
||||
const pieces = WallModel.computeBOM(CONFIG, calcData);
|
||||
@@ -26,7 +16,6 @@ window.WallPdf = (() => {
|
||||
const { RED, BLUE, BLACK, GREY } = PdfSheet.COLORS;
|
||||
doc.setFont('helvetica', 'normal');
|
||||
|
||||
// --- Frame materiaal-tabel (linksboven) ---
|
||||
const tblX = [8, 26, 42, 58, 76, 92];
|
||||
let ty = 14;
|
||||
doc.setTextColor(...BLACK);
|
||||
@@ -41,13 +30,12 @@ window.WallPdf = (() => {
|
||||
doc.line(tblX[0], ty, tblX[4] + 12, ty);
|
||||
ty += 4;
|
||||
groups.forEach(g => {
|
||||
if (ty > 232) return; // laat ruimte vrij voor materiaaltabellen eronder
|
||||
if (ty > 232) return;
|
||||
[String(g.posnum), String(g.width), String(g.depth), String(g.length), String(g.count)]
|
||||
.forEach((v, i) => doc.text(v, tblX[i], ty));
|
||||
ty += 4.3;
|
||||
});
|
||||
|
||||
// --- Inkoop balken (handelslengtes, zaagplan uit WallModel) ---
|
||||
const purchase = WallModel.planPurchase(pieces);
|
||||
ty += 3;
|
||||
doc.setFontSize(9);
|
||||
@@ -65,7 +53,6 @@ window.WallPdf = (() => {
|
||||
});
|
||||
});
|
||||
|
||||
// --- Materiaal binnen/buiten + isolatie ---
|
||||
let my = 240;
|
||||
const midH = Math.round(WallModel.topLine(CONFIG).maxY);
|
||||
doc.setFontSize(8.5);
|
||||
@@ -79,7 +66,6 @@ window.WallPdf = (() => {
|
||||
doc.text(`${CONFIG.wallWidth} x ${CONFIG.sheathingThick} x ${midH} ${buitenNaam} 1`, tblX[0], my); my += 6;
|
||||
doc.text('Isolatie: glaswol (spouwvullend)', tblX[0], my);
|
||||
if (buitenMateriaal === 'vochtdoek') {
|
||||
// Kruislat op het vochtdoek (zelfde berekening als de 3D: WallModel.computeBattens).
|
||||
const bat = WallModel.computeBattens(CONFIG, opts.cladding || 'horizontaal', opts.trasraam, opts.skinExt, opts.facade, opts.skinFrom);
|
||||
const B = WallModel.BATTEN;
|
||||
my += 4.5;
|
||||
@@ -95,12 +81,8 @@ window.WallPdf = (() => {
|
||||
}
|
||||
}
|
||||
|
||||
// --- Titelblok (rechtsonder) ---
|
||||
PdfSheet.titleBlock(doc, opts.project, { titel: opts.titel, element: opts.element, blad: opts.blad });
|
||||
|
||||
// --- Hoofdaanzicht ---
|
||||
// drawX1/marginBottom laten ruimte vrij voor het zijaanzicht (rechts)
|
||||
// en het bovenaanzicht (onder de maatketens).
|
||||
const drawX0 = 95, drawX1 = 380, drawY0 = 15, drawY1 = 225;
|
||||
const marginSides = 25, marginTop = 15, marginBottom = 68;
|
||||
const availW = (drawX1 - drawX0) - marginSides * 2;
|
||||
@@ -126,14 +108,9 @@ window.WallPdf = (() => {
|
||||
doc.setLineWidth(0.3);
|
||||
pieces.forEach(p => {
|
||||
if (p.outline) {
|
||||
// Werkelijke omtrek: schuine kop (volgt de daklijn, evt. met knik
|
||||
// onder de nok) resp. bovenregel in verstek.
|
||||
const c = p.outline.map(q => [px(q.x), py(q.y)]);
|
||||
c.forEach((q, i) => { const n = c[(i + 1) % c.length]; doc.line(q[0], q[1], n[0], n[1]); });
|
||||
} else if (p.kind === 'verticale balk' || p.kind === 'kreupele stijl') {
|
||||
// Viervlak i.p.v. rechthoek: de bovenkant loopt schuin mee met de
|
||||
// daklijn (yTopLeft/yTopRight kunnen verschillen), zodat zowel de
|
||||
// hoogste als de laagste kant van de balk op de juiste plek komt.
|
||||
const wx0 = p.x - p.width / 2, wx1 = p.x + p.width / 2;
|
||||
const corners = [
|
||||
[px(wx0), py(p.yBottomLeft)], [px(wx1), py(p.yBottomRight)],
|
||||
@@ -154,16 +131,13 @@ window.WallPdf = (() => {
|
||||
doc.setLineWidth(0.2);
|
||||
CONFIG.openings.forEach(op => {
|
||||
const opXWorld = -wallWidth / 2 + op.x;
|
||||
// Schuine bovenzijde: y0 = bovenkant links, y0r = rechts.
|
||||
const x0 = px(opXWorld), y0 = py(op.y + op.h), y0r = py(op.y + op.hR), x1 = px(opXWorld + op.w), y1 = py(op.y);
|
||||
[[x0, y1, x1, y1], [x1, y1, x1, y0r], [x1, y0r, x0, y0], [x0, y0, x0, y1]].forEach(l => doc.line(...l));
|
||||
doc.line(x0, y0, x1, y1);
|
||||
doc.line(x0, y1, x1, y0r);
|
||||
doc.setTextColor(...BLACK);
|
||||
doc.setFontSize(6);
|
||||
// Dagmaat-label BINNEN de opening zetten (net onder de bovenkant),
|
||||
// i.p.v. erboven — daar overlapte het met de maatketen/omtrek
|
||||
// erboven.
|
||||
// Label binnen de opening: erboven overlapte het met de maatketen.
|
||||
doc.text(op.hR !== op.h ? `${op.w}x${op.h}/${op.hR}` : `${op.w}x${op.h}`, (x0 + x1) / 2, Math.max(y0, y0r) + 5, { align: 'center' });
|
||||
});
|
||||
|
||||
@@ -180,8 +154,6 @@ window.WallPdf = (() => {
|
||||
doc.text(String(Math.round(hLeft)), px(-wallWidth / 2) - 9, (py(0) + py(hLeft)) / 2, { align: 'center', angle: 90 });
|
||||
drawDimLine(px(wallWidth / 2) + 7, py(0), px(wallWidth / 2) + 7, py(hRight));
|
||||
doc.text(String(Math.round(hRight)), px(wallWidth / 2) + 11, (py(0) + py(hRight)) / 2, { align: 'center', angle: 90 });
|
||||
// Tussenpunten van de daklijn: stippellijn van vloer tot nok/knik
|
||||
// (nok = het enige hoogste punt; mansarde-/wolfsgevel: knikken).
|
||||
const inner = tl.pts.slice(1, -1);
|
||||
inner.forEach(q => {
|
||||
const isNok = inner.filter(o => o.y >= q.y - 0.5).length === 1;
|
||||
@@ -219,7 +191,6 @@ window.WallPdf = (() => {
|
||||
doc.text(String(Math.round(openingPoints[i + 1] - openingPoints[i])), px(mid - wallWidth / 2), openY, { align: 'center' });
|
||||
}
|
||||
|
||||
// --- Gevellampen (woning): rechthoekje met "L" op lamphoogte ---
|
||||
(opts.lamps || []).forEach(l => {
|
||||
const lx = px(-wallWidth / 2 + l.u), ly = py(l.y);
|
||||
doc.setDrawColor(...BLACK);
|
||||
@@ -231,13 +202,9 @@ window.WallPdf = (() => {
|
||||
doc.text('L', lx + 2, ly + 1);
|
||||
});
|
||||
|
||||
// --- Extra laag van de aanroeper (bijv. elektra, ElektraPdf):
|
||||
// overlay(doc, pu, py), pu = wand-x (0..breedte) -> blad-mm.
|
||||
if (opts.overlay) opts.overlay(doc, (u) => px(-wallWidth / 2 + u), py);
|
||||
|
||||
// --- Bovenaanzicht (doorsnede op stijlhoogte, zoals de voorbeeld-
|
||||
// tekeningen): binnenzijde boven, buitenzijde onder (= de kant van
|
||||
// waaruit het vooraanzicht bekeken wordt). Zelfde horizontale schaal.
|
||||
// Binnenzijde boven, buitenzijde onder (de kant van het vooraanzicht).
|
||||
const sT = CONFIG.sheathingThick;
|
||||
const frameD = Math.max(CONFIG.studDepth, CONFIG.plateDepth);
|
||||
const tvY0 = floorY + 34;
|
||||
@@ -246,7 +213,6 @@ window.WallPdf = (() => {
|
||||
const tvY1 = tvFrame1 + sT * scale;
|
||||
const halfW = wallWidth / 2;
|
||||
|
||||
// Beplating, onderbroken ter plaatse van de openingen.
|
||||
const skinCuts = CONFIG.openings.map(op => [op.x, op.x + op.w]).sort((a, b) => a[0] - b[0]);
|
||||
const skinSegments = [];
|
||||
let skinCursor = 0;
|
||||
@@ -259,7 +225,6 @@ window.WallPdf = (() => {
|
||||
doc.rect(px(a - halfW), tvFrame1, (b - a) * scale, sT * scale, 'S');
|
||||
});
|
||||
|
||||
// Stijlen (vol + kreupel) als doorsneden: rechthoek met kruis.
|
||||
doc.setDrawColor(...RED);
|
||||
doc.setLineWidth(0.2);
|
||||
const studXs = [...new Set(calcData.studs.map(st => st.x))];
|
||||
@@ -288,8 +253,6 @@ window.WallPdf = (() => {
|
||||
doc.setFontSize(7);
|
||||
doc.text(String(Math.round(wallWidth)), px(0), tvDimY + 3.5, { align: 'center' });
|
||||
|
||||
// --- Zijaanzicht (rechterkopse kant): laagopbouw binnen | regelwerk |
|
||||
// buiten, met onder- en bovenregel, op dezelfde schaal.
|
||||
const svX0 = 392;
|
||||
const svFrame0 = svX0 + sT * scale;
|
||||
const svFrame1 = svFrame0 + frameD * scale;
|
||||
|
||||
Reference in New Issue
Block a user