Tectum — configurator Van Emous Mantelzorgwoningen (intern)

Configurator voor mantelzorgwoningen: wand, vloer en woning (gekoppelde units) met 2D, 3D, specificaties en PDF-tekenbladen.

Copyright © 2026 Machiel Heinen. Alle rechten voorbehouden; gebruik uitsluitend met schriftelijke toestemming. Zie LICENTIE.md. Elk bronbestand begint met deze copyright-kop.

Draaien

./start.sh            # of: python3 -m http.server 8000

Open http://localhost:8000. Elke statische webserver volstaat; geen build-stap. Direct openen via file:// werkt niet (texturen/lucht).

Structuur

index.html          app-shell: bovenbalk (menu, documenten, opslaan), sneltoetsen, splashscreen
css/app.css         alle stijl
js/vendor/          three.js r128, eigen OrbitControls, jsPDF, qrcode-generator 1.4.4 (MIT, Kazuhiko Arase; QR in de light-PDF),
                    model-viewer 4.3.1 (Apache-2.0, Google; UMD-bundel met eigen three.js, AR in de light-versie)
js/core/            gedeelde helpers: geometrie, weergavelagen (lagenmenu), menubalk, eigenschappenpaneel
                    (inspector.js), UI-kit (werkbalk, weergave, popovers), PDF-bladen,
                    DXF-schrijver (dxf-writer.js), IFC-schrijver (ifc-writer.js), OBJ-schrijver
                    (obj-writer.js), GLB-schrijver (glb-writer.js), ZIP (zip-writer.js), labels, camerageheugen,
                    skybox, licentie, logo
js/wall/            WallModel (logica) + wand-PDF + wand-editor
js/floor/           FloorModel (logica) + vloer-PDF + vloer-editor
js/roof/            RoofModel: dak (plat/lessenaar/zadel) + dakrand (boeidelen/daktrim)
                    PostModel: palen onder een overkapping/veranda (dak per unit te verlengen), of een dichte
                    zijwand op een vrije hoek
js/house/chimney-model.js  ChimneyModel: schoorsteen tegen een buitenwand (hol, sparing in de wand zoals een raam,
                    ook over een naad, zonder hout erin; sparing in het dak met raveelwerk (stijlen, balken, kreupele
                    balken), de beplating eindigt op het kader; onderbreekt de dakrand; een nokbalk stopt ervoor;
                    buiten steenstrip/stuc, binnen als de wanden of eigen; in de plattegrond
                    te verslepen langs de buitengevel)
js/lighting/        LightingModel: gevellampen, boeideel-spots, binnenspots
js/elektra/         ElektraModel + ElektraPdf: meterkast, schakelaars (letters), wcd, groepen, leidingen
js/sandwich/        SandwichModel: sandwichpanelen rondom
js/room/            RoomModel: ruimtes (verfemmer), functie, netto m², afwerking, vals plafond
js/interior/        FixtureModel: inrichting (sanitair, keuken, kasten, meubels, boiler)
js/unit/            UnitModel: 1 vloer + 4 wanden, naden, wandstukken
js/house/           HouseModel (woning) + woning-PDF + CAD-export (house-dxf.js) + BIM-export (house-ifc.js) + woning-editor
js/cost/            CostModel (kostenberekening), posten + noodwaarden, CostCsv (CSV's), venster Kosten & tijden
js/app.js           menubalk, versienummer, actieve editor
light.html          light-versie (modelpagina's), los te openen: light.html?model=amstel
js/light/           LightModel (keuzes op een model toepassen, indelingscontrole, kerncijfers), LightPdf (klant-PDF) + light-UI
css/light.css       stijl light-versie, alles onder .tectum-light
json/defaults/      referentie-JSON's (niet runtime ingeladen)
kosten/             intern.csv (eigen waarden) + leveranciers.csv (live prijzen), bij het starten ingeladen
assets/             logo, texturen, skybox

Uitgangspunten

  • Eén bron per logica. Rekenwerk en 3D-opbouw zitten alleen in de *Model/*Pdf-modules; editors en woning hergebruiken die.
  • Geen ES-modules, geen CDN. Gewone <script>-tags in vaste volgorde (zie index.html), alle libraries lokaal.
  • Assen/zijden. Bovenaanzicht boven = noord: voor = noord, achter = zuid, links = west, rechts = oost (interne sleutels blijven voor/achter/…).
  • Hoogtes gelden vanaf bovenkant vloer (loopvlak).
  • Weergavelagen (ViewLayers): regelwerk, elektra, beplating, vochtdoek, latwerk, gevelbekleding, kozijnen, dakbedekking, afwerking, verlichting, inrichting, ruimtes, dak en maten, elk los aan/uit; de snelkeuze Fase zet alles tot en met een bouwfase aan (de volgorde in de hal). Lagen die aan beide zijden zijn ingesloten worden niet gebouwd (stijlen tussen spaanplaat en doek, latten en doek achter de rabat, sporen tussen plafond en dakbedekking). Specificaties en totalen rekenen altijd met alle lagen.
  • Invoer volgt de logica: de dakvorm is een eigenschap van de unit (plat/lessenaar/zadel, richting, goot- en nokhoogte of helling); de wanden volgen.

Functionaliteit

  • Wand: openingen (raam/deur/voordeur) met ankers, ook boven elkaar (raam boven een deur; stijlen ertussen van dorpel tot dorpel), regelwerk 38x235 met dubbele hoekstijlen en een dubbele stijl naast deuren, zaagplan op handelslengtes, spaanplaat binnen, vochtdoek (met kruislat en trasraam) of cementplaat buiten.
  • Elektra (elektra/): meterkast (3×25 A) bij de voordeur, schakelaars met letter (A binnen, B buiten, per unit een eigen; dezelfde letter bij de lampen erop), dubbele wcd's per unit, apparaten met eigen groep (kookgroep perilex, wasmachine, droger, warmtepomp, optioneel oven/vaatwasser). Groepenverklaring met fasen en aardlekschakelaars, leidingen via stijlen en plafond naar de meterkast (strekkende meters per type, draad, buis, steekverbinders op module-naden), materiaallijst en eigen PDF-blad. Buizen minstens 50 mm uit elkaar (gebundeld alleen het laatste stuk naar de meterkast). Nooit 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 de gevelhoeken heen, en uit elkaar schuiven van buizen eindigt nooit in een opening. Vloer-wcd's met leiding door de vloer. Elektra ook op de PDF-bladen per wand, vloer en dakvlak (plafond). Alles verplaatsbaar door te slepen in de plattegrond. Kosten (groep Elektra): buis + draad per meter, boorgaten (geteld op stijlen, regels en balken), dozen, afmonteren, groepenkast en keuring.
  • Kozijnen (wall/kozijn-model.js): per opening een vulling (geen, raam met vast glas en optioneel ventilatierooster, of deur met dorpel en optionele glasstrook of als glasdeur; zij- en bovenlicht vullen de rest van een grote opening), kleur buiten en binnen (wit, grijs, antraciet, zwart). Volgt de maat van de opening, ook een schuine bovenzijde. Deur: kant van het blad, scharnierzijde en draairichting (naar binnen/buiten); openslaande deuren met zijlichten = twee deuren naast elkaar. Koppelen: een opening die tegen zijn buur aan staat (zelfde onderkant en hoogte, samen max. 2850 mm) vormt daarmee één sparing zonder stijlen, dagkanten, latten of kozijnstijlen ertussen; twee draaideuren worden stolp (bladen tegen elkaar), anders één gedeelde tussenstijl. Schuifdeur: 1 of 2 bladen (uit elkaar), in de wand of op de wand aan een rail (binnen- of buitenzijde), glazen of dicht blad. In de plattegrond (app en PDF) een draaicirkel per deur en de schuifrichting per schuifdeur; in de loopmodus gaan deuren open (dubbele schuifdeur samen). Dagkanten (afgewerkte fase): binnen een geschilderde omranding, dagkantplaten tot het kozijn en een vensterbank onder ramen; buiten een omranding in de kozijnkleur en een waterslag onder ramen (WallModel.build3D).
  • Plafond: in de afgewerkte fase is de onderkant van het dak geschilderd in de plafondkleur (Binnen › Wanden › Plafond), zolang "Geschilderd" aan staat; anders kale OSB.
  • Dakvorm/wandhoogte: per unit een dakvorm (Unit › Dakvorm: plat, lessenaar, zadel of wolfsdak, met schuiven en hellingshoek). Daaruit volgen de wanden: de kopgevels krijgen de daklijn (bij een wolfsdak afgeknot op het wolfseind, met daarboven driehoekige wolfseinden met de dakhelling tot de nok, met een rechte nok ertussen), de haakse wanden staan vlak op de goothoogte. Het bovenste deel van een wolfsdak is gewoon houtwerk: sporen, hoekkepers, nokbalk en kopbalken (ook in zaaglijst, specificaties en kosten). Een dubbel lessenaardak (twee units, elk hoog aan hun gezamenlijke naad, op de mm gelijke goot, nok en hoogte op de naad: samen een zadeldak) krijgt net als een zadeldak een stalen nokbalk onder de naad; één lessenaar of twee die zo niet aansluiten niet. Staat er een schoorsteen op de nok, dan stopt elke nokbalk vóór de schoorsteen. Goot en nok gelden over de volle vloermaat (goot boven de buitenkant van de gevel); staat de kopgevel tussen de haakse wanden, dan loopt zijn daklijn daar precies op aan. Het wolfseind schaalt mee met goot en nok (verhouding). De PDF heeft voor een wolfsdak een eigen blad met het bovenste deel (bovenaanzicht houtwerk + stuklijst). Grenzen (UnitModel.LIMITS): nok max 5 m, goot / plat dak max 3 m (vanaf bovenkant vloer tot onderkant dak), unit max 4,7 x 14 m. Platte daken van verschillende hoogte krijgen elk hun eigen boeideel (versprongen, het lage loopt door tot onder het hoge). Wijzig je een wandhoogte in de wand-editor, dan geldt dezelfde regel vanuit die wand. De daklijn van een wand hoort bij de wand zonder naden: loopt een wand door een naad langer door (bijv. de kopgevel naast een gekoppelde unit), dan blijven nok en knikken op hun plaats (UnitModel.topLineOn).
  • Dakaansluiting (L/T): staat een unit met nokdak (zadel of wolfsdak) met zijn nok haaks op de langszijde van een buur met nokdak (vleugel tegen hoofdvolume), dan loopt de vleugel het hoofddak in tot zijn nok, met kilkepers in de binnenhoeken (bij gelijke goot, nok en overspanning onder 45°); het wolfseind van de vleugel aan de naad vervalt. Ligt de vleugel gelijk met een kop van het hoofdvolume, dan wordt die kop een schild in de vlakken van de vleugel (hoekkeper, de goot loopt door; de kopgevel staat dan op goothoogte, een wolfseind daar vervalt). Een vleugel die in een wolfseind van het hoofdvolume zou steken sluit niet aan. Elke unit houdt zijn eigen dakdeel (sporen, kreupele sporen, kepers, knik- en nokbalken; stalen nokbalk alleen over de eigen nok) met een eigen PDF-blad (HouseModel.roofJoins, RoofModel.computeJoinedRoof). Niet bij dak over de hele woning; dakramen in zo'n dakdeel doen nog niet mee.
  • Overkapping: bij een dak over de hele woning met cover loopt het dak door tot de omhullende rechthoek waar geen unit staat (bijv. een terras naast een kortere module), met een afgewerkte onderplaat in de kleur van het boeideel (HouseModel.coverExtensions). Palen (Woning › Dak › Palen overkapping) komen onder de vrije dakrand; met "Zijwand" krijgt een vrije hoek geen paal maar een gestuukte wand van 200 mm van de dakhoek terug tot de gevel, langs de zijkant van de overkapping (bij een hoek tussen twee vrije randen de kant met de kortste weg naar de gevel); in 3D, plattegrond, PDF, DXF en kosten (PostModel, dak.zijwandM2/dak.zijwandMontage). Ligt de buitenkant in het vlak van een gevel, dan loopt die bekleding (felsplaten, rabat, steen) erover door, gelijk met de gevel en tot onder de dakrand. Bij een overkapping (veranda, inpandig of uitpandig: het dak van een unit steekt buiten zijn vloer, HouseModel.hasCover) is er geen wolfsdak: de keuze verdwijnt en een bestaand wolfsdak wordt een zadeldak met dezelfde goot en nok.
  • Dak over de hele woning: eigenschappen Woning › Dak › "Over hele woning": één dakvorm (zelfde invoer als per unit) over de omhullende rechthoek van alle units; een wolfsdak alleen bij een rechthoek (bij een L-/T-vorm zouden de wolfseinden kilkepers vragen, dan wordt het een zadeldak), bijv. een grote wolfskap over twee units naast elkaar. Elke unit houdt zijn eigen dakdeel (dekken, bovenste deel van het wolfsdak geknipt op de unit, PDF-bladen, kosten); de wanden van alle units volgen het woningdak. De daken per unit blijven bewaard (roof.unitWalls) en komen terug als je het weer uitzet.
  • Vloer: balken, cirkelvormige doorvoeren, OSB, optioneel chassis; in de woning een vloerafwerking (textuur, bijv. visgraat).
  • Woning: units koppelen aan een zijde (uitlijning + verschuiving); op naden vervallen de buitenwanden en komt een naadwand met deur: midden op de naad in twee delen (één per unit), of als één binnenwand geheel in unit A of B. De hoogte volgt per deel de daklijn van zijn unit. Staat een unit met een hogere daklijn tegen een lager dak, dan krijgt zijn buitenwand aan de naadzijde een opbouw vanaf de bovenkant van het lage dak (ramen daar teken je op die buitenwand) en stopt de naadwand op die hoogte. Loopt het lage dak langs de naad schuin, dan loopt de naadwand door en krijgt het uitstekende stuk buitenafwerking (vochtdoek + latwerk). Binnenwanden teken je in de plattegrond.
  • Dak: per unit opgebouwd als gespiegelde vloer + dakleer, in de vorm die de wanden aangeven: plat, lessenaar (schuine kopgevels) of zadel (nok). Elk dakvlak is een eigen dek met de balken als sporen en een eigen PDF-blad; doorvoeren gaan naar het vlak waarin ze vallen. Opbouw: plafondplaat (OSB) binnen, sporen, dakbeschot (OSB 18 mm) bovenop en daarop de bedekking per unit: dakleer, of bij een hellend dak riet (180 mm, 3,8 kg/m²) of felsplaten (staande naad, zink/antraciet/zwart); de dakrand schuift dan mee omhoog. De dakrand (boeidelen/daktrim, spots) loopt als één rand door en volgt de helling. Is een dak langs de naad minstens een boeideelhoogte hoger dan het aangrenzende, dan krijgt het een eigen rand rondom (boven het lage dak zonder spots). De rand van het lage dak loopt dan door tot de gevel van het hoge, of langs een zijgevel tot de volle overstek (onder de hoge rand). Boeideel en daktrim steken 80 mm boven het dakleer uit. Hebben dak én gevel onder een rand felsplaten, dan komt er geen boeideel: de dakplaat zet om over de rand, net vóór de gevelbekleding en zonder opstand (RoofModel.FELS_EDGE, zetwerk zit in de prijs van de felsplaten); een boeideel ernaast stopt gelijk met de buitenkant van zo'n rand (ook naast daktrim). Onder de boeidelen zit op de gevel een ventilatierooster van 40 mm (direct onder de onderplaat, op de gevelbekleding; niet boven een veranda), zwart/antraciet/wit (RoofModel.VENT, Woning › Dak › Boeideel; kosten dak.ventRoosterM).
  • Gevel: gevelbekleding per woning, met override per wand en per wandstuk: rabat (vochtdoek + kruislat + rabat 12 mm, kleur per woning, getekend als plankentextuur die over naden doorloopt), steen (181 texturen), stucwerk (pleisterlaag 15 mm op cement-gebonden plaat, kleur per woning, WallModel.STUC) of felsplaten (staande naad, banen van 500 mm, zink/antraciet/zwart; opbouw als verticale rabat, kleuren gedeeld met de felsplaten op het dak, WallModel.FELS; kosten gevel.felsM2 en gevel.felsMontage). Een zijde kan gesplitst worden (wand › Wandstukken › Splitsen op, gemeten vanaf de linker vloerhoek van buitenaf): elk stuk wordt een eigen wand-element en kan een eigen gevel krijgen (bijv. stuc links, hout rechts). Steen is overal een steenstrip op een wit isolatieblok, samen 110 mm (WallModel.STONE). Het trasraam (cementplaat of een eigen steen) komt onder beide, dus twee stenen kan. Op een stenen trasraam onder rabat, felsplaten of stuc (minder ver uitstekend) komt een afdekker: zetwerk 5° aflopend met een neus van 25 mm over de steen, onderbroken bij openingen, zwart/antraciet/wit (WallModel.TRAS_CAP, TRIM_COLORS; kosten gevel.afdekkerM). Latwerk, doek en metselwerk lopen per gevel door over unit-naden. Sandwichpanelen rondom, 600 mm de grond in.
  • Ruimtes (room/room-model.js): elk door wanden afgesloten gebied is een ruimte, bepaald als een verfemmer: alles wat bereikbaar is zonder door een wand te gaan (deuren en ramen tellen als wand). Exact op het raster van de wandvlakken, dus de netto vloer tot op de mm; kiertjes tot 30 mm tussen wanden worden dichtgezet. Gereedschap Ruimte vullen (Start/Binnen): kies een functie (woonkamer, keuken, slaapkamer, badkamer, toilet, hal, ...) en klik in de plattegrond; of selecteer een gebied en kies daar de functie (nog eens klikken = de unit eronder). Per ruimte: naam, vloerafwerking (o.a. tegels), FIBO-wandpanelen (decor, tot een hoogte of tot het plafond), eigen verfkleur en een vals plafond op een vaste hoogte (alleen waar het dak hoger ligt; wandafwerking en binnenspots volgen). Laag in de plattegrond (Lagen › Ruimtes), label met netto m², in de structuur, het rapport, de kosten (vals plafond, FIBO) en op de PDF-plattegrond met een ruimtestaat. Het zaadpunt hoort bij een unit en schuift mee.
  • Inrichting (interior/fixture-model.js): zwevend toilet (wandcloset aan een voorzetwand), fontein, badmeubel met spiegel, inloopdouche (douchegoot, glaswand, regendouche), keukenblok (spoelbak, hoge kast met koelkast en oven, vaatwasser, bovenkasten), kookeiland met inductieplaat, kledingkast, bed, eettafel met stoelen, bank met chaise longue, fauteuil, salontafel, tv-meubel, boiler en wasmachine. Gereedschap Inrichting (I): kies een stuk in de werkbalk en klik in de plattegrond; slepen, bij een wand snapt de rug op het wandvlak (Alt = vrij), D = draaien, Del = verwijderen. Per stuk maten en opties (front, plek spoelbak, glaswand links/rechts, ...). In 2D, 3D (afgewerkte fase), de PDF-plattegrond, de structuur en de kosten (groep Inrichting; los meubilair telt niet mee). Het stuk hoort bij een unit en schuift mee.
  • Verlichting: boeideel-spots of gevellampen (per gevel verdeeld, override per wand) en binnenspots in een raster per unit.
  • Indeling (zelfde patroon als CAD/BIM-pakketten; elke functie op één plek): bovenbalk met menu Bestand (nieuw, openen, opslaan, exporteren, projectgegevens, kosten & tijden) · Beeld · Help, de geopende ontwerpen als tabs en de knop Opslaan; links de structuur (groepen in-/uitklapbaar en onthouden; de groep met de selectie klapt vanzelf open); in het midden een werkbalk met gereedschap (Selecteren V, Binnenwand W, Ruimte R, Inrichting I, met de opties van het actieve gereedschap ernaast; Unit toevoegen) en weergave (Lagen, Omgeving, Doorsnede X, Render, Lopen L, Rapport 4, 2D + 3D / 2D / 3D met 1/2/3); rechts het eigenschappenpaneel: de selectie (unit, wandstuk, binnenwand, ruimte, inrichting, elektra) met kruimelpad terug, of zonder selectie de woning (kerncijfers en inklapbare secties Gevel, Dak, Binnen, Verlichting, Elektra, Constructie); onderin een statusbalk met de hint van het gereedschap en meldingen. Wand- en vloer/dak-editor hebben dezelfde indeling (werkbalk boven, paneel met tabbladen en Resultaat rechts; binnen de woning met "← Woning" of Esc terug). Help › Sneltoetsen (?) toont alle toetsen. Rapport toont transport per unit, gewicht, afmetingen, kosten, hout en plaatwerk in plaats van de plattegrond, als masonry (kaart in de kortste kolom, leesvolgorde blijft).
  • 3D en plattegrond: één lagenmenu (Lagen in de werkbalk, met bouwfase als snelkeuze) voor 3D en plattegrond; plattegrond zoomt met het scrollwiel en de knoppen rechtsonder (F = passend), verschuiven met slepen; Doorsnede (wanden afgesneden op een instelbare hoogte, schuif in de werkbalk, snede wit afgedekt), binnenzijde in een verfkleur (afgewerkte fase), omgeving Ontwerp/Dag/Nacht, Render met lampen als echte lichtbronnen.
  • Transport: per unit buitenmaat (incl. gevelafwerking), hoogte en gewicht (vloer/wanden/dak) met een indicatieve breedteklasse.
  • Uitvoer: JSON opslaan/openen en een samenhangende PDF (aanzichten noord/oost/zuid/west als vlakke render met legenda afwerking, plattegrond, vloeren, wandstukken, binnenwanden, totalen).
  • CAD-export (DXF): Bestand › Exporteren › CAD (DXF); los van Opslaan/Ctrl+S. DXF R12 (AC1009), opent in elk CAD-pakket (AutoCAD, BricsCAD, DraftSight, LibreCAD, …); DWG maakt het CAD-pakket zelf met Opslaan als (echte DWG schrijven vergt een GPL- of commerciële bibliotheek). Modelruimte 1:1 in mm: plattegrond met noord boven en de zuidwesthoek van de units op 0,0, eronder de vier gevels in een 2×2-raster (maaiveld als basis). Plattegrond: wanden per stuk als gesloten polylijn, onderbroken bij sparingen die onder het snijvlak (1500 mm) beginnen (hogere gestreept), stijlzone en gevelbekleding als eigen lagen, kozijnen (raam: kader + glaslijn; deur: stijlen, blad en draaicirkel als boog; schuifdeur: bladen, pijlen, rail), ruimtegrenzen als gesloten polylijn met naam/m²/plafond, inrichting, dakrand, palen, schoorsteen, verlichting, elektra, naden en elementcodes. Gevels: dezelfde vlakken als de PDF-aanzichten (HousePdf.viewProjections) als lijntekening met verborgen lijnen weg, kozijnen met kader, blad, zij-/bovenlicht en glas (KozijnModel.viewLines). Maatvoering als echte DIMENSION (maatstijl TECTUM): ketting per buitenwandstuk langs de sparingen, totaal per stuk en van de woning, hoogtes maaiveld/peil/top per gevel. Lagen PL-* (plattegrond), AZ-* (aanzichten), MAATVOERING, TEKST; tekst, maatvoering en lijntypes afgestemd op 1:50 ($LTSCALE/DIMSCALE 50).
  • BIM-export (IFC): Bestand › Exporteren › BIM (IFC), ook in Woning › Uitvoer. IFC4 met alleen de bouwconstructie: hout (stijlen/regels als IfcMember, vloerbalken als IfcBeam, dakbalken als IfcMember), stalen nokbalk, palen, platen (spaanplaat, OSB, cementplaat als IfcPlate) en elektra (buis per leiding, inbouw-/lasdozen, meterkast); geen gevelafwerking, latwerk, isolatie, kozijnen, dakbedekking of inrichting. Geometrie uit de 3D-opbouw zelf (HouseIfc: fase elektra voor alle balken en leidingen, fase beplating voor de platen; herkend aan het materiaal), als driehoeksnet. Opbouw: unit › element (A-W1, A-V1, A-D) › onderdelen; binnenwanden en elektra los in de bouwlaag. Per onderdeel Pset_Tectum (element, onderdeel, afmeting, lengte, materiaal). Kleur per soort (op het vlak en het materiaal): stijl lichthout, regel oranje, vloerbalk bruin, dakbalk roodbruin, paal donkerbruin, stalen nokbalk staalblauw, spaanplaat groen, OSB geel, cementplaat grijs; elektra in de app-kleuren (HouseIfc COLORS). X = oost, Y = noord, Z = 0 op peil; zuidwesthoek van de units = 0,0 (zelfde als de DXF).
  • Render-export (OBJ): Bestand › Exporteren › Render (OBJ), ook in Woning › Uitvoer. Voor een sfeerimpressie: alleen wat in de afgewerkte woning te zien is (dak, dakrand, lampen, ruimtes, inrichting; los van de gekozen lagen, doorsnede en weergave-opties; zonder buizen en dozen, binnenste vloerbalken, latten en isolatie achter de gevel, lichtkegels, logobord, grond en lucht) als ZIP met .obj, .mtl, textures/*.png (rabat, steen, riet, tegels) en <naam>_lampen.py: in Blender uitvoeren importeert de OBJ en zet elke lamp (gevellamp, dakrandspot, binnenspot) als echte spotlight met dezelfde plek, richting en kegel als in de app (LightingModel.lightSources). Meters, Y omhoog (de standaard OBJ-import van Blender zet dat goed: noord = +Y), oorsprong op maaiveld onder het midden. Kleuren omgerekend van sRGB naar lineair (de app heeft geen kleurbeheer, Blender wel), PBR via Pr/Pm/d/Ke (ruwheid, metaal, doorzichtigheid glas, gloed lampen); textuurherhaling zit in de UV's (ObjWriter).

Light-versie (modelpagina's)

Beperkte configurator voor de websitepagina van één model (later in de HUGO-build; nu los via light.html?model=<sleutel uit HouseModel.MODELS>). Inbedden: de stylesheets en scripts uit light.html plus <div class="tectum-light" data-model="amstel"></div> (mount vanzelf), of TectumLight.mount(el, { model, frames, url, modelViewer }).

  • Rekent als de configurator (zelfde HouseModel.computeParts, totalen en CostModel), maar toont alleen: indicatieve prijs incl. btw (afgerond op € 100), buitenmaten, bouwhoogte, bruto/leefbaar m², inhoud en gewicht. Geen uren, zaaglijst, inkoop of kostenopbouw.
  • Weergave: 3D (afgewerkt, dag-omgeving), Doorsnede (wanden op een instelbare hoogte, standaard 1,5 m en hoogstens de laagste goot of de hoogte van een plat dak, afgesneden en wit afgedekt met HouseModel.sectionCaps, dezelfde als de configurator; dak, dakrand, palen en lampen weg) en een 2D-plattegrond (ruimtes met netto m², wanden, kozijnen met draairichting, inrichting, dakrand, buitenmaten).
  • Keuzes: per unit breedte, diepte, goothoogte en dakvorm met richting (lessenaar: hoge kant noord/zuid/ west/oost; zadel- en wolfsdak: nok noord–zuid of west–oost); bij een hellend dak de nokhoogte (lessenaar: hoge kant, met de helling eronder; de goot omhoog neemt de nok mee), bij een wolfsdak ook de hoogte van het wolfseind (bij een dak over de hele woning één keer), dakbedekking, gevelbekleding (hout met richting, felsplaten, stuc, steenstrips; kleur), het accent van het model (de afwijkende gevel; of geen), trasraam (geen of steen, met hoogte; een cementplaat-trasraam van het model wordt geen), boeidelen of daktrim (met kleur boeidelen; een model met beide houdt zijn indeling tot je kiest), zetwerk-kleur (afdekker trasraam en ventilatierooster), binnenspots aan/uit en het type buitenverlichting. Wolfsdak over de hele woning alleen als de units samen een rechthoek vormen en nooit bij een overkapping (zoals de configurator). Geen openingen, binnenwanden, inrichting of elektra; die volgen het model.
  • Keuzes op een schone kopie: LightModel.build past de keuzes elke keer toe op het model zelf; wat niet afwijkt blijft precies zoals in het model. Bij een andere maat schuiven binnenwanden mee met hun unit en schuift wat tegen de oost- of zuidgevel staat (binnenwand-eindpunt, inrichting) mee met die gevel (BAND). Bij een andere hoogte gaan de binnenwanden van die unit evenveel mee. Een andere dakvorm dan die van het model krijgt de helling uit LightModel.PITCH (lessenaar 10°, zadel 30°, wolfsdak 35°).
  • Kaders: standaard UnitModel.LIMITS (maat 2,4–14 m, max 4,7 m in één richting; hoogte 2,4–3 m), per model te beperken in LightModel.FRAMES of per pagina met frames (zelfde vorm; null = maat staat vast).
  • Indelingscontrole (LightModel.check): een keuze waarbij ramen of deuren niet meer passen (verschoven, ingeklemd, te hoog of over een naad), een binnenwand buiten de units valt, inrichting door een gevel steekt, ruimtes verdwijnen of units overlappen, wordt geweigerd; vergeleken met het model zelf. Bij een maat wordt de dichtstbijzijnde maat gezocht die nog past.
  • Indeling: paneel als accordeon (Afmetingen, Dak, Gevel, Verlichting; één open, de kop vat de keuze samen), kerncijfers en prijs met PDF-knop onderaan. Responsief op de breedte van de tool zelf (container queries; in de site in een Bootstrap col-12): vanaf 720 px naast elkaar, smaller 3D boven en de keuzes eronder met prijs en PDF vast onderin beeld. Stijl alles onder .tectum-light (Bootstrap-reboot geneutraliseerd); Bootstrap Icons nodig (css/vendor/bootstrap-icons.min.css). Het scrollwiel scrolt de pagina, tenzij je in de 3D hebt geklikt of Ctrl/⌘ ingedrukt houdt. Zijwaarts schuiven: rechts of middelste knop slepen, Shift/Ctrl/⌘ + slepen, of de pijltjestoetsen met de muis boven de 3D. Touch: één vinger draaien, twee vingers knijpen/schuiven (eigen OrbitControls, geldt ook voor de configurator).
  • Opslaan = PDF (LightPdf): voorblad "Uw woningontwerp" (beeld uit de 3D-weergave, kerncijfers, keuzes in woorden via LightModel.describe, indicatieve prijs, contactgegevens en een QR-code naar de modelpagina op de site, of data-url/url van de pagina), dan aanzichten en plattegrond (HousePdf.generate(state, { customer: true, doc }): zonder onderdelenlijst, elementcodes, elektra en kosten) en als laatste het stappenplan van de site ("Hoe verloopt het traject?") met een blok over maatwerk met de eigen software (keuken op maat, indeling, ramen en deuren). Contact en stappen staan in LightPdf.COMPANY en STEPS.
  • AR / schermvullend: knop rechtsboven in de weergave. Op een telefoon of tablet: het ontwerp als GLB (GlbWriter, afgewerkte woning zoals in 3D, één primitive per materiaal, texturen als JPEG/PNG tot 1024 px, lichtbundels weg; maaiveld onder het midden = oorsprong, HouseModel.groundOrigin) in model-viewer, over de hele pagina, met de knop "Bekijk in je tuin" (ware grootte; ar-modes="webxr scene-viewer quick-look", op iOS maakt model-viewer zelf de USDZ). model-viewer wordt pas bij de eerste keer geladen (js/vendor/model-viewer-umd.min.js naast js/light/, of modelViewer/data-model-viewer). AR vraagt https; Scene Viewer (Android zonder WebXR) heeft bovendien een publieke URL van de GLB nodig, een blob-URL werkt daar niet. Op de desktop: de weergave schermvullend (Fullscreen API; het scrollwiel zoomt dan direct). Per ontwerp wordt de GLB één keer gemaakt; el.tectumLight.glb() geeft { blob, url, stats } (op light.html de testknop GLB).

Kosten en prijzen (CSV)

Alle waarden van het kostenmodel staan in twee CSV-bestanden in kosten/, die de app bij het starten ophaalt. Elke waarde staat op één plek; de CSV's zijn leidend en de app bewaart niets in de browser.

  • kosten/intern.csv: eigen waarden: tijden, uurloon, bezetting, kosten per uur, opslagen, marge (alles behalve prijzen).
  • kosten/leveranciers.csv: alle inkoopprijzen (bijv. uit API-scripts van leveranciers), ook constructiehout per balkmaat.
  • js/cost/cost-defaults.js: welke posten er zijn (labels, eenheden, keuzes) en noodwaarden voor wat een CSV mist.
# intern.csv
code;omschrijving;eenheid;waarde
arbeid.uurloon;Uurloon productie (all-in);€/u;45
zagen.methode;Zaagmethode;;robot

# leveranciers.csv
code;omschrijving;eenheid;prijs;leverancier;artikelnummer;bijgewerkt
elektra.wcdEnkel;Wandcontactdoos enkel met randaarde;€/st.;6,00;Groothandel X;123456;2026-10-09
hout.balk.38x235;Constructiehout vuren C24 38×235;€/m;4,91;Houthandel Y;;2026-10-09
  • Verplicht: code en waarde (of prijs), excl. btw; 6,00, 6.00, 1.234,50 en € 6 mogen; bij een keuze de sleutel of de tekst. Scheidingsteken ;, , of tab; regels met # worden overgeslagen.
  • code = <groep>.<sleutel> uit cost-defaults.js, of hout.balk.<b>x<h> voor constructiehout per balkmaat in €/m (zonder balkmaat: m³-prijs × volume).
  • omschrijving is de naam van de post in de app (leeg = die uit cost-defaults.js).
  • eenheid is optioneel; ingevuld moet die gelijk zijn aan die van de post, anders wordt de regel geweigerd.
  • Een prijs in intern.csv of een tijd in leveranciers.csv wordt geweigerd ("hoort in …"). Meerdere regels met dezelfde code in leveranciers.csv (leveranciers): de laagste prijs telt.
  • Onbekende codes (bijv. onderdelen die de app nog niet rekent) en fouten staan bovenaan in Kosten & tijden.
  • Kosten & tijden: Toepassen geldt tot herladen (om te proberen); intern.csv downloaden om het bestand in kosten/ te vervangen. Prijsvelden staan vast. Bij Leveranciers: Sjabloon (alle prijscodes), Tijdelijk laden (tot herladen of Terug naar server).

Bekende beperkingen

  • DXF: geen arceringen en geen lijndiktes (R12); kleuren per laag (ACI), dus pendiktes via de plotstijl. Geen doorsnede en geen dakaanzicht. Eenheid staat niet in het bestand: in CAD op millimeters zetten (UNITS) als het pakket erom vraagt.

  • OBJ: lichtbronnen alleen via het meegeleverde Blender-script, geen reliëf-/normaalkaarten; glas als doorzichtig materiaal, in Blender eventueel op Glass BSDF zetten.

  • IFC: onderdelen zijn driehoeksnetten (niet parametrisch); geen verbindingsmiddelen, isolatie of bekabeling (alleen buizen).

  • Tijdelijk (verwijderen voor productie): zaagmachine-overzicht (zaagmeters bij 2400 m/u, zaagsneden, hoeken) in de app en op het totalenblad (SAW_M_PER_H).

  • Tijdelijk: een nieuwe woning is het voorbeeldontwerp "Vlinderwoning" (92 m², drie units, vlinderdak met riet + platte tuinkamer, ook als json/premade/vlinderwoning.json); uit te zetten met TEST_DEFAULT in js/house/house-model.js. Bij het starten opent model Amstel (HouseModel.createAmstel, naar examples/ontwerp_amstel.pdf): 11,24 × 7,2 m, twee modules onder één plat dak dat over het terras doorloopt, stucwerk wit met verticaal hout aan de slaapkamerkant, binnenwanden, dubbele schuifdeur tussen woonkamer en hal, en complete inrichting. Langer maken: beide units breder (alles is vanaf de westgevel gemaat). Model Wetering (HouseModel.createWetering, naar examples/ontwerp_wetering.pdf): 10,5 × 4,8 m, twee units van 2,6 en 2,2 m zonder naadwand (open woonkamer over de volle diepte), verticaal rabat grijs, plat dak met zwart boeideel, hoekkeuken met kookplaat, badkamer, slaapkamer met kledingkast. Model IJssel (HouseModel.createIJssel, naar examples/ontwerp_ijssel.pdf): L-vorm 14 × 4,6 m met een vleugel van 4,6 × 3 m, twee units met zadeldak en riet die met een kil en een hoekkeper op elkaar aansluiten, stucwerk wit, openslaande deuren in de westgevel. Model Waal (HouseModel.createWaal, naar examples/ontwerp_waal.pdf): 12,85 × 7 m, flauw zadeldak dat aan de oostkop 1,5 m doorloopt als veranda op eiken palen (Overkapping per unit). Model Maas (HouseModel.createMaas, naar examples/ontwerp_maas.pdf): vierkant 9,2 × 9,2 m, flauw zadeldak over de hele woning; de overkapping maakt van de noordwesthoek een inpandige veranda (2,5 × 4,6 m) op eiken palen. Model Rijn (HouseModel.createRijn, naar examples/ontwerp_rijn.pdf): L-vorm 13 × 10 m, hoofdvolume met flauw zadeldak (twee lessenaars die op de naad de nok vormen) en een vleugel met plat dak, steenstrips rondom met een schoorsteen (800 mm, hart op de naad) in de oostgevel, kookeiland, logeerkamer en apart toilet in de vleugel. Model Reest (HouseModel.createReest, naar examples/ontwerp_reest.pdf): 12,9 × 7,85 m, hoofdvolume 11,5 × 4,8 m onder één lessenaarsdak (hoog aan de noordgevel, twee units van 3,4 en 1,4 m met lessenaars in hetzelfde vlak) dat aan de westkop 1,4 m doorloopt als overkapping bij de voordeur, dicht met een witte zijwand; aanbouw met plat dak (toilet, berging, entree met open doorgang naar de woonkamer, daktrim i.p.v. boeidelen); zuidgevel en dak in antraciet felsplaten (zuidrand zonder boeideel, de felsplaten lopen over de zijwand door), verder verticale rabat. Model Vecht (HouseModel.createVecht): U-vorm 13 × 9,5 m, drie units (slaapvleugel west, tussenlid met entree, leefvleugel oost) met de holte open naar het noorden; de vleugels lessenaars die naar de holte aflopen, het tussenlid plat op dezelfde goot, de overkapping van het tussenlid dekt de holte (palen niet nodig); zwarte verticale rabat, wit stucwerk aan de holte. De standaardmodellen staan in HouseModel.MODELS; Bestand › Snel nieuw en het venster Nieuw worden daaruit opgebouwd (nieuw model = één regel plus een create-functie die modelKit gebruikt). De L-woning (8 × 3,6 m + 4,5 × 3,6 m) blijft beschikbaar als "Woning L-vorm".

  • Netto m² per ruimte telt de hele vloer, ook onder een laag schuin dak (geen NEN 2580-correctie voor hoogte < 1,5 m).

  • Units kunnen niet gedraaid worden.

  • Getekende binnenwanden volgen de dakvorm (nog) niet.

  • De dak-editor toont het dek in de plattegrond (niet per schuin dakvlak).

  • Geen schaduw per lamp in de render (browserlimiet).

  • Eigen OrbitControls: roteren/zoomen/pannen, geen damping.

Versie

APP_VERSION in js/app.js: laatste cijfer per iteratie, middelste per mijlpaal (met git-tag), eerste bij live-gang. De changelog staat in git.

S
Description
No description provided
Readme
181 MiB
Languages
JavaScript 94%
CSS 5.1%
HTML 0.9%