Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
432e0f494a | ||
|
|
decbbb4b72 | ||
|
|
51921650e3 | ||
|
|
89cadbebf7 | ||
|
|
ab0dca9bb5 | ||
|
|
adb3c74f85 | ||
|
|
86fcd57b96 | ||
|
|
b137a458d4 | ||
|
|
bd084e4a96 | ||
|
|
ceda0b554d | ||
|
|
b5510d56c7 | ||
|
|
e1a688728c | ||
|
|
8cdfa21f46 | ||
|
|
23bfe153a2 | ||
|
|
12c2579471 | ||
|
|
7d91416004 | ||
|
|
94a5215f82 | ||
|
|
373c2c2fb7 | ||
|
|
001206a108 | ||
|
|
9126588df7 | ||
|
|
9bd7faeaa6 | ||
|
|
f163f4deb1 | ||
|
|
448c2b1289 | ||
|
|
5ecf3e0c2a | ||
|
|
7ae76fe390 | ||
|
|
9ed9cee2e0 | ||
|
|
f8da490640 | ||
|
|
3a4b9608c0 | ||
|
|
3591fad220 |
@@ -1,237 +1,507 @@
|
|||||||
# Tectum — configurator Van Emous Mantelzorgwoningen (intern)
|
# Tectum — configurator Van Emous Mantelzorgwoningen (intern)
|
||||||
|
|
||||||
Losse, meerdere-bestanden-opzet van de eerdere single-file wand-tool, nu met
|
Configurator voor mantelzorgwoningen: wand, vloer en woning (gekoppelde units)
|
||||||
een menubalk om tussen objecttypen (muur/vloer) te schakelen.
|
met 2D, 3D, specificaties en PDF-tekenbladen.
|
||||||
|
|
||||||
Copyright © 2026 Machiel Heinen. Alle rechten
|
Copyright © 2026 Machiel Heinen. Alle rechten voorbehouden; gebruik
|
||||||
voorbehouden; gebruik uitsluitend met schriftelijke toestemming. Zie
|
uitsluitend met schriftelijke toestemming. Zie [LICENTIE.md](LICENTIE.md).
|
||||||
[LICENTIE.md](LICENTIE.md). Elk bronbestand begint met deze copyright-kop.
|
Elk bronbestand begint met deze copyright-kop.
|
||||||
|
|
||||||
## Draaien
|
## Draaien
|
||||||
|
|
||||||
**Optie 1 — direct openen (geen server nodig):**
|
|
||||||
Dubbelklik `index.html`. Alles werkt met gewone `<script src="...">`-tags
|
|
||||||
(geen ES-modules), dus dit werkt ook via `file://`.
|
|
||||||
|
|
||||||
**Optie 2 — lokale server (optioneel):**
|
|
||||||
```
|
```
|
||||||
cd project
|
./start.sh # of: python3 -m http.server 8000
|
||||||
python3 -m http.server 8000
|
|
||||||
```
|
```
|
||||||
en open `http://localhost:8000`.
|
Open `http://localhost:8000`. Elke statische webserver volstaat; geen
|
||||||
|
build-stap. Direct openen via `file://` werkt niet (texturen/lucht).
|
||||||
|
|
||||||
## Structuur
|
## Structuur
|
||||||
|
|
||||||
```
|
```
|
||||||
index.html app-shell: menubalk, splashscreen, over-deze-software
|
index.html app-shell: bovenbalk (menu, documenten, opslaan), sneltoetsen, splashscreen
|
||||||
css/
|
css/app.css alle stijl
|
||||||
app.css alle stijl, in één bestand
|
js/vendor/ three.js r128, eigen OrbitControls, jsPDF, qrcode-generator 1.4.4 (MIT, Kazuhiko Arase; QR in de light-PDF),
|
||||||
js/
|
model-viewer 4.3.1 (Apache-2.0, Google; UMD-bundel met eigen three.js, AR in de light-versie)
|
||||||
vendor/
|
js/core/ gedeelde helpers: geometrie, weergavelagen (lagenmenu), menubalk, eigenschappenpaneel
|
||||||
three.min.js three.js r128, lokaal gevendord (geen CDN meer)
|
(inspector.js), UI-kit (werkbalk, weergave, popovers), PDF-bladen,
|
||||||
OrbitControls.js eigen, compacte OrbitControls-vervanging (zie
|
DXF-schrijver (dxf-writer.js), IFC-schrijver (ifc-writer.js), OBJ-schrijver
|
||||||
"Bewuste keuzes" hieronder) — leunt op three.min.js
|
(obj-writer.js), GLB-schrijver (glb-writer.js), ZIP (zip-writer.js), labels, camerageheugen,
|
||||||
core/
|
skybox, licentie, logo
|
||||||
geometry.js gedeelde, pure functies (regelwerk-verdeling,
|
js/wall/ WallModel (logica) + wand-PDF + wand-editor
|
||||||
polygon-oppervlaktes, clip-functies) — gebruikt
|
js/floor/ FloorModel (logica) + vloer-PDF + vloer-editor
|
||||||
door zowel wall.js als floor.js, niet gedupliceerd
|
js/roof/ RoofModel: dak (plat/lessenaar/zadel) + dakrand (boeidelen/daktrim)
|
||||||
canvas-labels.js gedeelde stijl voor maatlabels ("X: 6000mm") in de
|
PostModel: palen onder een overkapping/veranda (dak per unit te verlengen), of een dichte
|
||||||
2D-canvassen van wand, vloer en unit
|
zijwand op een vrije hoek
|
||||||
pdf-sheet.js gedeelde PDF-bouwstenen: titelblok, maatlijn, tabel
|
js/house/chimney-model.js ChimneyModel: schoorsteen tegen een buitenwand (hol, sparing in de wand zoals een raam,
|
||||||
camera-memory.js onthoudt de 3D-camerastand per tabblad + onderdeel
|
ook over een naad, zonder hout erin; sparing in het dak met raveelwerk (stijlen, balken, kreupele
|
||||||
view-filter.js "Weergave"-dropdown met vinkjes voor de 3D-weergaven
|
balken), de beplating eindigt op het kader; onderbreekt de dakrand; een nokbalk stopt ervoor;
|
||||||
license.js licentietekst voor "Over deze software" (kopie van
|
buiten steenstrip/stuc, binnen als de wanden of eigen; in de plattegrond
|
||||||
LICENTIE.md, dat bestand is leidend)
|
te verslepen langs de buitengevel)
|
||||||
logo-data.js logo als PNG-data voor de PDF-titelblokken
|
js/lighting/ LightingModel: gevellampen, boeideel-spots, binnenspots
|
||||||
(opnieuw genereren uit assets/logo.svg, zie kop)
|
js/elektra/ ElektraModel + ElektraPdf: meterkast, schakelaars (letters), wcd, groepen, leidingen
|
||||||
wall/
|
js/sandwich/ SandwichModel: sandwichpanelen rondom
|
||||||
wall-model.js WallModel: ENIGE bron van de wand-logica (anker-
|
js/room/ RoomModel: ruimtes (verfemmer), functie, netto m², afwerking, vals plafond
|
||||||
resolutie openingen, regelwerk, 3D-opbouw, specs,
|
js/interior/ FixtureModel: inrichting (sanitair, keuken, kasten, meubels, boiler)
|
||||||
validatie) — geen DOM
|
js/unit/ UnitModel: 1 vloer + 4 wanden, naden, wandstukken
|
||||||
wall-pdf.js WallPdf: het wand-tekenblad (aanzicht, boven- en
|
js/house/ HouseModel (woning) + woning-PDF + CAD-export (house-dxf.js) + BIM-export (house-ifc.js) + woning-editor
|
||||||
zijaanzicht, materiaallijst) — losse wand én unit
|
js/cost/ CostModel (kostenberekening), posten + noodwaarden, CostCsv (CSV's), venster Kosten & tijden
|
||||||
wall.js wand-editor (UI: invoer, 2D, interactie, JSON/PDF)
|
js/app.js menubalk, versienummer, actieve editor
|
||||||
floor/
|
light.html light-versie (modelpagina's), los te openen: light.html?model=amstel
|
||||||
floor-model.js FloorModel: ENIGE bron van de vloer-logica (balken,
|
js/light/ LightModel (keuzes op een model toepassen, indelingscontrole, kerncijfers), LightPdf (klant-PDF) + light-UI
|
||||||
doorvoeren, chassis, 3D-opbouw, specs, validatie)
|
css/light.css stijl light-versie, alles onder .tectum-light
|
||||||
floor-pdf.js FloorPdf: het vloer-tekenblad — losse vloer én unit
|
json/defaults/ referentie-JSON's (niet runtime ingeladen)
|
||||||
floor.js vloer-editor (UI, uitsluitend cirkelvormige
|
kosten/ intern.csv (eigen waarden) + leveranciers.csv (live prijzen), bij het starten ingeladen
|
||||||
openingen/doorvoeren)
|
assets/ logo, texturen, skybox
|
||||||
roof/
|
|
||||||
roof-model.js RoofModel: plat dak = vloer (FloorModel) 180°
|
|
||||||
gespiegeld + dakleer; dakrand (boeidelen met spots
|
|
||||||
of daktrim) als één doorlopende rand om de woning
|
|
||||||
lighting/
|
|
||||||
lighting-model.js LightingModel: buitenverlichting per unit (geen /
|
|
||||||
boeideel-spots / gevellampen), gevellampen per
|
|
||||||
wandstuk met terugval naar spots, override per wand
|
|
||||||
unit/
|
|
||||||
unit-model.js UnitModel: 1 vloer + 4 wanden, hoekaansluiting,
|
|
||||||
naden (wand vervalt deels/geheel) en wandstukken
|
|
||||||
house/
|
|
||||||
house-model.js HouseModel: woning = gekoppelde units + binnenwanden;
|
|
||||||
posities (koppelen aan zijde + uitlijning), naden,
|
|
||||||
totalen
|
|
||||||
house-pdf.js HousePdf: samenhangende PDF (plattegrond, per unit
|
|
||||||
vloer + wandstukken, binnenwanden, totalen)
|
|
||||||
house.js woning-editor (UI): navigatieboom, plattegrond met
|
|
||||||
selecteren/binnenwand tekenen, eigenschappen, 3D;
|
|
||||||
mount de echte wand-/vloer-editor per onderdeel
|
|
||||||
app.js menubalk-logica, versienummer, mount/unmount van
|
|
||||||
de actieve editor
|
|
||||||
json/
|
|
||||||
defaults/ referentie-JSON's die tonen wat "Nieuw" oplevert
|
|
||||||
(worden NIET ingeladen via fetch(), zie hieronder)
|
|
||||||
premade/ bestemmingsmap voor opgeslagen/geëxporteerde designs
|
|
||||||
assets/ logo (preloader) + bestemmingsmap voor toekomstige
|
|
||||||
GLB's/texturen
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Bewuste keuzes / bekende beperkingen
|
## Uitgangspunten
|
||||||
|
|
||||||
- **Volledig CDN-vrij.** three.js (r128) staat lokaal in `js/vendor/three.min.js`.
|
- **Eén bron per logica.** Rekenwerk en 3D-opbouw zitten alleen in de
|
||||||
OrbitControls is een eigen, compacte implementatie (`js/vendor/OrbitControls.js`)
|
`*Model`/`*Pdf`-modules; editors en woning hergebruiken die.
|
||||||
— het originele addon-bestand was niet beschikbaar om te vendoren, dus is de
|
- **Geen ES-modules, geen CDN.** Gewone `<script>`-tags in vaste volgorde
|
||||||
gebruikte subset (roteren via slepen, zoomen via scrollwiel, pannen via
|
(zie `index.html`), alle libraries lokaal.
|
||||||
rechts-slepen, `target`/`update()`) opnieuw geschreven en losstaand getest
|
- **Assen/zijden.** Bovenaanzicht boven = noord: voor = noord, achter = zuid,
|
||||||
(rotatie/zoom-richting/grenzen/pannen/dispose). Functioneel gelijkwaardig
|
links = west, rechts = oost (interne sleutels blijven voor/achter/…).
|
||||||
voor wat deze tool nodig heeft, maar geen 1-op-1 kopie van alle opties van
|
- **Hoogtes** gelden vanaf bovenkant vloer (loopvlak).
|
||||||
de officiële addon (bijv. geen damping/inertia).
|
- **Weergavelagen** (`ViewLayers`): regelwerk, elektra, beplating, vochtdoek,
|
||||||
- **Geen ES-modules.** Alle JS-bestanden zijn gewone `<script>`-tags, geladen
|
latwerk, gevelbekleding, kozijnen, dakbedekking, afwerking, verlichting,
|
||||||
in een vaste volgorde (`geometry.js` → `canvas-labels.js` → jsPDF →
|
inrichting, ruimtes, dak en maten, elk los aan/uit; de snelkeuze Fase zet
|
||||||
`pdf-sheet.js` → `wall-model.js` → `wall-pdf.js` → `floor-model.js` →
|
alles tot en met een bouwfase aan (de volgorde in de hal). Lagen die aan
|
||||||
`floor-pdf.js` → `roof-model.js` → `lighting-model.js` → `wall.js` → `floor.js` → `unit-model.js` → `house-model.js`
|
beide zijden zijn ingesloten worden niet
|
||||||
→ `house-pdf.js` → `house.js` → `app.js`).
|
gebouwd (stijlen tussen spaanplaat en doek, latten en doek achter de rabat,
|
||||||
Reden: ES-module-imports (`import ... from`) breken bij rechtstreeks openen
|
sporen tussen plafond en dakbedekking). Specificaties en totalen rekenen
|
||||||
via `file://` door browser-CORS-beleid. Dit was expliciet een vereiste
|
altijd met alle lagen.
|
||||||
("gewoon via een index file"), dus is hier bewust voor gekozen.
|
- **Invoer volgt de logica:** de dakvorm is een eigenschap van de unit
|
||||||
- **`json/defaults/*.json` worden niet gefetcht.** Om dezelfde reden (fetch()
|
(plat/lessenaar/zadel, richting, goot- en nokhoogte of helling); de
|
||||||
van lokale bestanden werkt ook niet betrouwbaar via `file://`): de
|
wanden volgen.
|
||||||
standaardwaarden van "Nieuw" staan hardcoded in `wall.js`/`floor.js` zelf,
|
|
||||||
en komen overeen met deze JSON-bestanden. De JSON's zijn dus referentie/
|
## Functionaliteit
|
||||||
documentatie, en (voor wanden) een bestand dat je via "Importeer JSON" kan
|
|
||||||
inladen — geen runtime-configuratiebron.
|
- **Wand:** openingen (raam/deur/voordeur) met ankers, ook boven elkaar
|
||||||
- **Alleen wall.js heeft Exporteer/Importeer JSON.** floor.js nog niet.
|
(raam boven een deur; stijlen ertussen van dorpel tot dorpel), regelwerk
|
||||||
- **Floor.js heeft nu dezelfde soorten logica als wall.js.** 2D-bovenaanzicht
|
38x235 met dubbele hoekstijlen en een dubbele stijl naast deuren, zaagplan
|
||||||
+ doorsnede, regelwerk (vloerbalken), cirkelvormige doorvoeren, een
|
op handelslengtes, spaanplaat binnen, vochtdoek (met kruislat en trasraam)
|
||||||
onderlaag van OSB-plaat (standaard 22mm, dikte + oppervlak + volume +
|
of cementplaat buiten.
|
||||||
gewicht), een isolatielaag (leegte tussen de balken, analytisch bepaald —
|
- **Elektra** (`elektra/`): meterkast (3×25 A) bij de voordeur, schakelaars
|
||||||
net als bij de wand krijgt isolatie zelf bewust geen dichtheid/gewicht),
|
met letter (A binnen, B buiten, per unit een eigen; dezelfde letter bij de
|
||||||
een volwaardig 3D-perspectief (balken/isolatie/OSB met doorvoer-gaten/
|
lampen erop), dubbele wcd's per unit, apparaten met eigen groep (kookgroep
|
||||||
chassis-wielen, met aan/uit-toggles voor OSB en isolatie, plus fullscreen-
|
perilex, wasmachine, droger, warmtepomp, optioneel oven/vaatwasser).
|
||||||
2D/3D) en een specificaties-paneel met een gewichtstotaal. Losse,
|
Groepenverklaring met fasen en aardlekschakelaars, leidingen via stijlen
|
||||||
optionele chassis-laag (4 transportwielen in een "dobbelsteen 4"-indeling,
|
en plafond naar de meterkast (strekkende meters per type, draad, buis,
|
||||||
exact gecentreerd op de vloer — spoorbreedte/wielbasis/wieldiameter
|
steekverbinders op module-naden), materiaallijst en eigen PDF-blad.
|
||||||
instelbaar, geen interactie met de balkposities).
|
Buizen minstens 50 mm uit elkaar (gebundeld alleen het laatste stuk naar
|
||||||
- **Single point of truth wand/vloer/unit.** Alle reken- en 3D-logica zit in
|
de meterkast). Nooit door een raam of deur (`makeOpeningTest`): een
|
||||||
`WallModel`/`FloorModel`. De losse editors én de unit roepen die aan, dus
|
stijgleiding boven/onder een opening (wcd onder een raam) gaat eerst op
|
||||||
een wijziging in de wand- of vloerlogica geldt automatisch overal. De unit
|
dezelfde hoogte opzij tot naast de opening, langs dezelfde wand met een
|
||||||
bewaart per onderdeel een gewone wand-/vloer-state; wandbreedtes worden
|
deur of raam ertussen via het plafond, gevellampen om de gevelhoeken heen,
|
||||||
afgeleid uit vloermaat + wanddiktes + hoekaansluiting, openingen houden
|
en uit elkaar schuiven van buizen eindigt nooit in een opening. Vloer-wcd's met leiding door de vloer. Elektra ook op de
|
||||||
hun anker (links/midden/rechts). "Opslaan als" bij een unit geeft JSON +
|
PDF-bladen per wand, vloer en dakvlak (plafond). Alles verplaatsbaar door
|
||||||
één samenhangende PDF: bovenaanzicht unit (U-1), vloer (V-1), elke wand
|
te slepen in de plattegrond. Kosten (groep Elektra): buis + draad per
|
||||||
(W-1…W-4, via WallPdf/FloorPdf) en een totalenblad (balken, zaaglijst,
|
meter, boorgaten (geteld op stijlen, regels en balken), dozen,
|
||||||
glaswol, plaatwerk, gewichten). Projectgegevens van de unit staan in
|
afmonteren, groepenkast en keuring.
|
||||||
`state.project` en gelden voor alle bladen.
|
- **Kozijnen** (`wall/kozijn-model.js`): per opening een vulling (geen, raam
|
||||||
- **Standaarden (WallModel).** Muurbalk 38 x 235 mm (stijlen én regels),
|
met vast glas en optioneel ventilatierooster, of deur met dorpel en
|
||||||
ingekocht in 3600/4200/4800/5400 mm; een zaagplan (`planStockCutting` in
|
optionele glasstrook of als glasdeur; zij- en bovenlicht vullen de rest van een grote
|
||||||
geometry.js) kiest per staaf de lengte met het minste snijverlies — bij een
|
opening), kleur buiten en binnen (wit, grijs, antraciet, zwart). Volgt de
|
||||||
unit over alle wanden samen. Stukken langer dan 5400 worden opgeknipt.
|
maat van de opening, ook een schuine bovenzijde. Deur: kant van het blad,
|
||||||
Elke wandkop heeft een dubbele hoekstijl (2 x 38 mm). De app start met een
|
scharnierzijde en draairichting (naar binnen/buiten); openslaande deuren
|
||||||
unit.
|
met zijlichten = twee deuren naast elkaar. Koppelen: een opening die tegen
|
||||||
- **Woning (v0.2).** Bestand → Nieuw → Woning (1 unit) of Woning L-vorm. Een
|
zijn buur aan staat (zelfde onderkant en hoogte, samen max. 2850 mm) vormt
|
||||||
unit koppel je aan een zijde van een andere unit (uitlijning start/midden/
|
daarmee één sparing zonder stijlen, dagkanten, latten of kozijnstijlen
|
||||||
eind + verschuiving). Op de naad vervalt de wand van beide units over het
|
ertussen; twee draaideuren worden stolp (bladen tegen elkaar), anders één
|
||||||
gedeelde stuk; een wand kan daardoor in meerdere stukken uiteenvallen
|
gedeelde tussenstijl. Schuifdeur: 1 of 2 bladen
|
||||||
(bijv. A-W2a/b), haakse wanden lopen dan door tot de vloerrand. Binnen-
|
(uit elkaar), in de wand of op de wand aan een rail (binnen- of
|
||||||
wanden teken je in de plattegrond (standaard 100 mm, spaanplaat beide
|
buitenzijde), glazen of dicht blad. In de plattegrond (app en PDF) een
|
||||||
zijden) en bewerk je met de gewone wand-editor. Een wandstuk dat aan een
|
draaicirkel per deur en de schuifrichting per schuifdeur; in de loopmodus
|
||||||
naad eindigt loopt de naad in door met de dikte van de haakse buurwand,
|
gaan deuren open (dubbele schuifdeur samen). Dagkanten (afgewerkte
|
||||||
zodat binnenhoeken (L-vorm) dicht zijn. Zijden heten naar windrichting
|
fase): binnen een geschilderde omranding, dagkantplaten tot het kozijn en
|
||||||
t.o.v. het bovenaanzicht (boven = noord): voor = noord, achter = zuid,
|
een vensterbank onder ramen; buiten een omranding in de kozijnkleur en
|
||||||
links = west, rechts = oost (intern blijven de oude sleutels). Oude unit-JSON's kunnen in
|
een waterslag onder ramen (`WallModel.build3D`).
|
||||||
een woning worden geïmporteerd. Units kunnen (nog) niet gedraaid worden.
|
- **Plafond:** in de afgewerkte fase is de onderkant van het dak
|
||||||
- **Mijlpaal v0.4 — gevelopbouw.** Samenvatting van de v0.3.11–0.3.19-iteraties:
|
geschilderd in de plafondkleur (Binnen › Wanden › Plafond), zolang
|
||||||
kruislat-latwerk op vochtdoek (richting gevelbekleding globaal), lampen op de
|
"Geschilderd" aan staat; anders kale OSB.
|
||||||
afgewerkte gevel (+52 mm), logo-watermerk op het doek, trasraam (cement-
|
- **Dakvorm/wandhoogte:** per unit een dakvorm (Unit › Dakvorm: plat,
|
||||||
gebonden plaat, 350 mm vanaf het loopvlak), sandwichpanelen rondom (600 mm de
|
lessenaar, zadel of wolfsdak, met schuiven en hellingshoek).
|
||||||
grond in), hoekdoorloop van de buitenlagen over de hoekstijlen, en latwerk/
|
Daaruit volgen de wanden: de kopgevels krijgen de daklijn (bij een
|
||||||
doek per doorlopende gevel over unit-naden heen. Details per onderdeel hieronder.
|
wolfsdak afgeknot op het wolfseind, met
|
||||||
- **Plat dak (v0.3).** Elke unit heeft een dak (tweede laag) dat standaard
|
daarboven driehoekige wolfseinden met de dakhelling tot de nok, met een
|
||||||
de vloermaat volgt, maar een eigen maat/verschuiving mag krijgen. Opbouw =
|
rechte nok ertussen), de haakse wanden staan vlak op de goothoogte. Het
|
||||||
vloer 180° gespiegeld (OSB als plafond onder, balken, dakleer bovenop); het
|
bovenste deel van een wolfsdak is gewoon houtwerk: sporen, hoekkepers,
|
||||||
dak wordt bewerkt met de vloer-editor in dakmodus. De dakrand is woning-
|
nokbalk en kopbalken (ook in zaaglijst, specificaties en kosten).
|
||||||
breed: boeidelen (overstek 200–400 mm vanaf de dakrand = standaard de
|
Een dubbel lessenaardak (twee units, elk hoog aan hun gezamenlijke naad,
|
||||||
gevel, 300 mm hoog, spots op 40% van de overstek, op elke (unit-)hoek en
|
op de mm gelijke goot, nok en hoogte op de naad: samen een zadeldak)
|
||||||
daartussen verdeeld met min/max h.o.h.) of een daktrim van 80 mm. De rand
|
krijgt net als een zadeldak een stalen nokbalk onder de naad; één
|
||||||
loopt als één geheel over de naden tussen units. Het dak ligt op de hoogste
|
lessenaar of twee die zo niet aansluiten niet. Staat er een schoorsteen
|
||||||
wandbovenkant van de unit; bij units met verschillende hoogtes ligt de
|
op de nok, dan stopt elke nokbalk vóór de schoorsteen.
|
||||||
dakrand op het hoogste dak.
|
Goot en nok gelden over de volle vloermaat (goot boven de buitenkant van
|
||||||
- **Dakrand & buitenverlichting (v0.3.3).** Boeidelen aan/uit per unit
|
de gevel); staat de kopgevel tussen de haakse wanden, dan loopt zijn
|
||||||
(anders daktrim); de rand wordt per ribbe opgebouwd (in verstek, geen
|
daklijn daar precies op aan. Het wolfseind schaalt mee met goot en
|
||||||
zichtbare naad). Verlichting is woning-breed: type (geen / boeideel-spots /
|
nok (verhouding). De PDF heeft voor een wolfsdak een eigen blad met het
|
||||||
gevellampen), lichtrichting en alle afstanden. Gevellampen worden per
|
bovenste deel (bovenaanzicht houtwerk + stuklijst).
|
||||||
GEVEL verdeeld (aansluitende wandstukken in hetzelfde vlak, ook over een
|
Grenzen (`UnitModel.LIMITS`): nok max 5 m, goot / plat dak max 3 m (vanaf
|
||||||
naad tussen units), niet per wand: op lamphoogte (standaard 1950) alleen op
|
bovenkant vloer tot onderkant dak), unit max 4,7 x 14 m. Platte daken van verschillende hoogte krijgen elk hun eigen
|
||||||
vrije stukken >= 2000 mm (openingen incl. raamwerk eraf), eerste/laatste
|
boeideel (versprongen, het lage loopt door tot onder het hoge). Wijzig je een
|
||||||
300 mm van hoek/opening, daartussen min/max h.o.h.; smallere stukken krijgen
|
wandhoogte in de wand-editor, dan geldt dezelfde regel vanuit die wand.
|
||||||
geen lampen. Gevellampen en boeideel-spots sluiten elkaar uit. De min.
|
De daklijn van een wand hoort bij de wand zonder naden: loopt een wand
|
||||||
h.o.h. geldt over alle lampen van een gevel samen (ook bij afstand hoek/
|
door een naad langer door (bijv. de kopgevel naast een gekoppelde unit),
|
||||||
opening en overrides): te dicht bij elkaar = samengevoegd tot één lamp in
|
dan blijven nok en knikken op hun plaats (`UnitModel.topLineOn`).
|
||||||
het midden. Per wandzijde blijft een override: automatisch / 500 mm
|
- **Dakaansluiting (L/T):** staat een unit met nokdak (zadel of
|
||||||
naast elke opening / geen. Standaard unithoogte 2600 mm.
|
wolfsdak) met zijn nok haaks op de langszijde van een buur met nokdak
|
||||||
- **3D-weergave (v0.3.5).** Filters als dropdown met vinkjes. Woning:
|
(vleugel tegen hoofdvolume), dan loopt de vleugel het hoofddak in tot
|
||||||
Beplating (wandplaten, vloer- en plafondplaten, dakleer, boeideel/daktrim),
|
zijn nok, met kilkepers in de binnenhoeken (bij gelijke goot, nok en
|
||||||
Isolatie, Dak, Lampen. "Volle render": avondscène met maaiveld, elke
|
overspanning onder 45°); het
|
||||||
gevellamp (per lichtrichting) en boeideel-spot is een echte SpotLight
|
wolfseind van de vleugel aan de naad vervalt. Ligt de vleugel gelijk met
|
||||||
(zonder schaduwen, om het licht te houden); de nep-lichtkegels zijn dan
|
een kop van het hoofdvolume, dan wordt die kop een schild in de vlakken
|
||||||
verborgen.
|
van de vleugel (hoekkeper, de goot loopt door; de kopgevel staat dan op
|
||||||
- **Latwerk gevelbekleding (v0.3.11).** Bij vochtdoek komt er een kruislat
|
goothoogte, een wolfseind daar vervalt). Een vleugel die in een wolfseind
|
||||||
op (WallModel.computeBattens): latten 20x30 mm, handelslengte 4000, 400 mm
|
van het hoofdvolume zou steken sluit niet aan. Elke unit houdt zijn eigen
|
||||||
h.o.h. in beide richtingen, uitgespaard rond openingen en afgekapt op de
|
dakdeel (sporen, kreupele sporen, kepers, knik- en nokbalken; stalen
|
||||||
(schuine) bovenrand. De bovenste laag staat haaks op de gevelbekleding
|
nokbalk alleen over de eigen nok) met een eigen PDF-blad
|
||||||
(WEO/Novalit, 12 mm; richting per losse wand, in een woning voorlopig
|
(`HouseModel.roofJoins`, `RoofModel.computeJoinedRoof`). Niet bij dak
|
||||||
globaal als woning-instelling). Gevellampen hangen op de afgewerkte gevel:
|
over de hele woning; dakramen in zo'n dakdeel doen nog niet mee.
|
||||||
wandvlak + kruislat (40) + bekleding (12) = 52 mm naar buiten. Cement-gebonden
|
- **Overkapping:** bij een dak over de hele woning met `cover` loopt het
|
||||||
platen (steenstrips) krijgen geen latwerk. Latten tellen mee in gewicht,
|
dak door tot de omhullende rechthoek waar geen unit staat (bijv. een
|
||||||
specificaties, wand-PDF en woningtotalen; zichtbaar met "Beplating".
|
terras naast een kortere module), met een afgewerkte onderplaat in de
|
||||||
- **Vochtdoek-bedrukking (v0.3.13).** Net als op de echte doeken staat het logo
|
kleur van het boeideel (`HouseModel.coverExtensions`). Palen
|
||||||
als medium-grijs watermerk (geen kleur) onder 45° op het vochtdoek, 1,5 m
|
(Woning › Dak › Palen overkapping) komen onder de vrije dakrand; met
|
||||||
breed, herhaald per tegel van 2 m (WallModel.createMaterials, CanvasTexture).
|
"Zijwand" krijgt een vrije hoek geen paal maar een gestuukte wand van
|
||||||
- **Trasraam (v0.3.14).** Woning-instelling (aan/uit + hoogte, standaard 350 mm
|
200 mm van de dakhoek terug tot de gevel, langs de zijkant van de
|
||||||
vanaf Y=0 van de vloer = het beloopbare vlak / bovenkant vloer). Onderaan
|
overkapping (bij een hoek tussen twee vrije randen de kant met de kortste
|
||||||
elke vochtdoek-gevel komt een strook cement-gebonden plaat (montage-
|
weg naar de gevel); in 3D, plattegrond, PDF, DXF en kosten
|
||||||
achterkant), vóór het doek; het doek loopt er ongewijzigd achter door en
|
(`PostModel`, `dak.zijwandM2`/`dak.zijwandMontage`). Ligt de buitenkant
|
||||||
het latwerk begint erboven. Zelfde plaat- en uitsparingslogica als de
|
in het vlak van een gevel, dan loopt die bekleding (felsplaten, rabat,
|
||||||
buitenplaten, dus openingen blijven gerespecteerd (WallModel.trasraamFor,
|
steen) erover door, gelijk met de gevel en tot onder de dakrand.
|
||||||
build3D opts.trasraam, computeBattens). Telt mee in gewicht, wand-PDF en de
|
- **Dak over de hele woning:** eigenschappen Woning › Dak › "Over hele woning": één
|
||||||
woningtotalen ("Cementplaat (trasraam)").
|
dakvorm (zelfde invoer als per unit) over de omhullende rechthoek van alle
|
||||||
- **Hoekdoorloop buitenlagen (v0.3.18).** Een wand die tussen twee doorlopende
|
units; een wolfsdak alleen bij een rechthoek (bij een L-/T-vorm zouden
|
||||||
wanden past, bedekt met zijn buitenlagen ook de kopse kant (hoekstijlen) van
|
de wolfseinden kilkepers vragen, dan wordt het een zadeldak), bijv. een
|
||||||
die wanden: UnitModel geeft per wand(stuk) skinExt { left, right } (= dikte
|
grote wolfskap over twee units naast elkaar. Elke unit
|
||||||
van de doorlopende wand, 0 bij naden/vrije einden), WallModel.cornerExt telt
|
houdt zijn eigen dakdeel (dekken, bovenste deel van het wolfsdak geknipt
|
||||||
per laag de eigen diepte erbij. Latwerk en trasraam lopen door; vochtdoek
|
op de unit, PDF-bladen, kosten); de wanden van alle units volgen het
|
||||||
en cementplaat (liggen in de beplatingsruimte) krijgen een strook net vóór
|
woningdak. De daken per unit blijven bewaard (`roof.unitWalls`) en komen
|
||||||
het wandvlak.
|
terug als je het weer uitzet.
|
||||||
- **Latwerk en doek per gevel (v0.3.19).** HouseModel.assignFacades groepeert
|
- **Vloer:** balken, cirkelvormige doorvoeren, OSB, optioneel chassis;
|
||||||
collineaire, aansluitende buitenwandstukken over alle units tot gevels
|
in de woning een vloerafwerking (textuur, bijv. visgraat).
|
||||||
(groupFacadeRuns in core/geometry.js, ook gebruikt door de buitenverlichting)
|
- **Woning:** units koppelen aan een zijde (uitlijning + verschuiving); op
|
||||||
en geeft elk stuk p.facade { u0, extStart, isEnd }. Het verticale
|
naden vervallen de buitenwanden en komt een naadwand met deur: midden op
|
||||||
latten-raster (400 h.o.h.) en het watermerk op het doek lopen daardoor over
|
de naad in twee delen (één per unit), of als één binnenwand geheel in unit
|
||||||
unit-naden door; een eindlat komt alleen aan het einde van de gevel.
|
A of B. De hoogte volgt per deel de daklijn van zijn unit. Staat een unit
|
||||||
- **Sandwichpanelen (v0.3.16).** Woning-instelling aan/uit. SandwichModel
|
met een hogere daklijn tegen een lager dak, dan krijgt zijn buitenwand aan
|
||||||
(js/sandwich/sandwich-model.js) legt één doorlopende rand (in verstek) om de
|
de naadzijde een opbouw vanaf de bovenkant van het lage dak (ramen daar
|
||||||
vereniging van alle unit-vloeren: 40 mm dik, van het loopvlak (bovenkant
|
teken je op die buitenwand) en stopt de naadwand op die hoogte. Loopt het
|
||||||
vloer) 600 mm naar beneden, de grond in. Plaat 495 x 1000 x 40 (9 kg),
|
lage dak langs de naad schuin, dan loopt de naadwand door en krijgt het
|
||||||
verticaal: één plaat per 495 mm gevel, 1000 afgezaagd op 600. Naden per
|
uitstekende stuk buitenafwerking (vochtdoek + latwerk).
|
||||||
495 mm; zichtbaar met "Beplating"; m2, aantal platen en gewicht (hele
|
Binnenwanden teken je in de plattegrond.
|
||||||
platen) in de woningtotalen.
|
- **Dak:** per unit opgebouwd als gespiegelde vloer + dakleer, in de vorm
|
||||||
- **Openingtypes.** Raam (500x1900), deur (900x2150) en voordeur (1150x2150);
|
die de wanden aangeven: plat, lessenaar (schuine kopgevels) of zadel
|
||||||
type kiezen zet de standaardmaat, daarna vrij aan te passen. De app start
|
(nok). Elk dakvlak is een eigen dek met de balken als sporen en een eigen
|
||||||
met een L-woning met een voordeur (noord, unit A) en 3 ramen (zuid, unit B).
|
PDF-blad; doorvoeren gaan naar het vlak waarin ze vallen. Opbouw:
|
||||||
- **Woning-instellingen.** Regelwerk-h.o.h. (min/max) geldt globaal voor alle
|
plafondplaat (OSB) binnen, sporen, dakbeschot (OSB 18 mm) bovenop en
|
||||||
buitenwanden resp. alle binnenwanden; in de wand-editor zijn die velden
|
daarop de bedekking per unit: dakleer, of bij een hellend dak riet
|
||||||
binnen een woning vergrendeld.
|
(180 mm, 3,8 kg/m²) of felsplaten (staande naad, zink/antraciet/zwart);
|
||||||
- **Versienummer** staat als enkele constante (`APP_VERSION`) in `app.js`.
|
de dakrand schuift dan mee omhoog. De dakrand
|
||||||
Conventie: laatste cijfer per kleine iteratie, middelste per mijlpaal
|
(boeidelen/daktrim, spots) loopt als één rand door en volgt de helling.
|
||||||
(aangegeven in chat), eerste bij live-gang.
|
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).
|
||||||
|
- **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. 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), binnenspots aan/uit en het type buitenverlichting. Wolfsdak over de hele
|
||||||
|
woning alleen als de units samen een rechthoek vormen (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. 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.
|
||||||
|
|||||||
@@ -1,2 +1,9 @@
|
|||||||
Bestemmingsmap voor toekomstige assets: GLB-modellen (ramen/deuren),
|
Assets voor de 3D-weergave en de PDF:
|
||||||
texturen/bumpmaps, e.d. Nog leeg.
|
- logo.svg / logo-animated.svg logo (splash, about); PDF-logo staat als data in js/core/logo-data.js
|
||||||
|
- skybox.webp equirectangulair panorama dag (4096x2048), "Lucht: Dag" (core/skybox.js)
|
||||||
|
- skybox-night.webp equirectangulair panorama nacht (4096x2048), "Lucht: Nacht"
|
||||||
|
- tiles.jpg tegeltextuur (1024x1024) voor de ronde vloer onder het object
|
||||||
|
- textures/buitenmuur/ steen voor het trasraam: "<code> - Witte voeg.jpg" (2062x1125, 2 mm/px,
|
||||||
|
naadloos), voorvertoning in thumb/32|64|128/*.png (WallModel.TRASRAAM_STONES)
|
||||||
|
- textures/vloer/ vloerafwerking (FloorModel.FINISHES), bijv. visgraat_001.jpg (1500x1500, tegel 3 m); thumb/32|64|128/*.png
|
||||||
|
- textures/dak/ dakbedekking: riet_<nr>.jpg (1024x1024, tegel 1 m); nummers in RoofModel RIET.nrs; thumb/32|64|128/*.png
|
||||||
|
|||||||
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 3.1 MiB |
|
After Width: | Height: | Size: 523 KiB |
|
After Width: | Height: | Size: 715 KiB |
|
After Width: | Height: | Size: 698 KiB |
|
After Width: | Height: | Size: 753 KiB |
|
After Width: | Height: | Size: 598 KiB |
|
After Width: | Height: | Size: 909 KiB |
|
After Width: | Height: | Size: 711 KiB |
|
After Width: | Height: | Size: 786 KiB |
|
After Width: | Height: | Size: 936 KiB |
|
After Width: | Height: | Size: 656 KiB |
|
After Width: | Height: | Size: 723 KiB |
|
After Width: | Height: | Size: 743 KiB |
|
After Width: | Height: | Size: 813 KiB |
|
After Width: | Height: | Size: 749 KiB |
|
After Width: | Height: | Size: 837 KiB |
|
After Width: | Height: | Size: 981 KiB |
|
After Width: | Height: | Size: 709 KiB |
|
After Width: | Height: | Size: 708 KiB |
|
After Width: | Height: | Size: 798 KiB |
|
After Width: | Height: | Size: 831 KiB |
|
After Width: | Height: | Size: 636 KiB |
|
After Width: | Height: | Size: 548 KiB |
|
After Width: | Height: | Size: 762 KiB |
|
After Width: | Height: | Size: 452 KiB |
|
After Width: | Height: | Size: 887 KiB |
|
After Width: | Height: | Size: 759 KiB |
|
After Width: | Height: | Size: 470 KiB |
|
After Width: | Height: | Size: 645 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 904 KiB |
|
After Width: | Height: | Size: 462 KiB |
|
After Width: | Height: | Size: 813 KiB |
|
After Width: | Height: | Size: 925 KiB |
|
After Width: | Height: | Size: 860 KiB |
|
After Width: | Height: | Size: 865 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 924 KiB |
|
After Width: | Height: | Size: 582 KiB |
|
After Width: | Height: | Size: 835 KiB |
|
After Width: | Height: | Size: 905 KiB |
|
After Width: | Height: | Size: 981 KiB |
|
After Width: | Height: | Size: 787 KiB |
|
After Width: | Height: | Size: 556 KiB |
|
After Width: | Height: | Size: 576 KiB |
|
After Width: | Height: | Size: 505 KiB |
|
After Width: | Height: | Size: 494 KiB |
|
After Width: | Height: | Size: 523 KiB |
|
After Width: | Height: | Size: 538 KiB |
|
After Width: | Height: | Size: 598 KiB |
|
After Width: | Height: | Size: 537 KiB |
|
After Width: | Height: | Size: 772 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 957 KiB |
|
After Width: | Height: | Size: 736 KiB |
|
After Width: | Height: | Size: 459 KiB |
|
After Width: | Height: | Size: 528 KiB |
|
After Width: | Height: | Size: 534 KiB |
|
After Width: | Height: | Size: 846 KiB |
|
After Width: | Height: | Size: 853 KiB |
|
After Width: | Height: | Size: 536 KiB |
|
After Width: | Height: | Size: 562 KiB |
|
After Width: | Height: | Size: 642 KiB |
|
After Width: | Height: | Size: 637 KiB |
|
After Width: | Height: | Size: 941 KiB |
|
After Width: | Height: | Size: 767 KiB |
|
After Width: | Height: | Size: 801 KiB |
|
After Width: | Height: | Size: 924 KiB |
|
After Width: | Height: | Size: 616 KiB |
|
After Width: | Height: | Size: 591 KiB |
|
After Width: | Height: | Size: 647 KiB |
|
After Width: | Height: | Size: 761 KiB |
|
After Width: | Height: | Size: 666 KiB |
|
After Width: | Height: | Size: 630 KiB |
|
After Width: | Height: | Size: 633 KiB |
|
After Width: | Height: | Size: 644 KiB |
|
After Width: | Height: | Size: 570 KiB |
|
After Width: | Height: | Size: 601 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 896 KiB |
|
After Width: | Height: | Size: 746 KiB |
|
After Width: | Height: | Size: 871 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 830 KiB |
|
After Width: | Height: | Size: 883 KiB |
|
After Width: | Height: | Size: 914 KiB |
|
After Width: | Height: | Size: 958 KiB |
|
After Width: | Height: | Size: 809 KiB |
|
After Width: | Height: | Size: 976 KiB |
|
After Width: | Height: | Size: 905 KiB |
|
After Width: | Height: | Size: 979 KiB |
|
After Width: | Height: | Size: 907 KiB |
|
After Width: | Height: | Size: 990 KiB |
|
After Width: | Height: | Size: 935 KiB |
|
After Width: | Height: | Size: 920 KiB |
|
After Width: | Height: | Size: 771 KiB |
|
After Width: | Height: | Size: 960 KiB |