v0.4.8: gevellampen tellen vanaf de zichtbare afgewerkte hoek
- bedekte gevelstukken (wandstuk in de naad, binnenhoek L) afgetrokken via voetafdruk - uiteinden verlengd met afwerking (+ skinExt bij tussenpassende wanden) - groupFacadeRuns accepteert overlap Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
448c2b1289
commit
f163f4deb1
@@ -173,6 +173,13 @@ assets/ logo (preloader) + bestemmingsmap voor toekomstige
|
|||||||
unitrand bij een naad); spots te dicht bij een binnenwand vervallen.
|
unitrand bij een naad); spots te dicht bij een binnenwand vervallen.
|
||||||
Woning-instellingen › Verlichting › Binnenspots. In 3D (filter Lampen),
|
Woning-instellingen › Verlichting › Binnenspots. In 3D (filter Lampen),
|
||||||
plattegrond (open cirkeltje), render en totalen.
|
plattegrond (open cirkeltje), render en totalen.
|
||||||
|
- **Startpunt gevellampen (v0.4.8).** Een gevel telt vanaf de zichtbare,
|
||||||
|
afgewerkte hoek: elk uiteinde + afwerking van de haakse wand (52 mm bij
|
||||||
|
vochtdoek), plus de bedekte kopse kant (skinExt) bij tussenpassende wanden.
|
||||||
|
Delen van een gevel achter een andere wand (bijv. een wandstuk dat de naad
|
||||||
|
in loopt om een binnenhoek te sluiten, zoals A-W2 bij een L) worden
|
||||||
|
afgetrokken via de voetafdruk van die wand; de gevel begint dan bij diens
|
||||||
|
afgewerkte buitenkant.
|
||||||
- **Lichtbronnen (v0.4.7).** Geen echte schaduw per lamp (één schaduwkaart
|
- **Lichtbronnen (v0.4.7).** Geen echte schaduw per lamp (één schaduwkaart
|
||||||
per lamp overschrijdt de browserlimiet); licht door muren wordt geometrisch
|
per lamp overschrijdt de browserlimiet); licht door muren wordt geometrisch
|
||||||
voorkomen: buitenlampen en boeideel-spots zijn half hun bundelhoek naar
|
voorkomen: buitenlampen en boeideel-spots zijn half hun bundelhoek naar
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
* Alle rechten voorbehouden. Gebruik uitsluitend met schriftelijke toestemming.
|
* Alle rechten voorbehouden. Gebruik uitsluitend met schriftelijke toestemming.
|
||||||
* Zie LICENTIE.md.
|
* Zie LICENTIE.md.
|
||||||
*/
|
*/
|
||||||
const APP_VERSION = '0.4.7';
|
const APP_VERSION = '0.4.8';
|
||||||
// 0.0.X per kleine iteratie, 0.X.0 per mijlpaal, X.0.0 bij live-gang.
|
// 0.0.X per kleine iteratie, 0.X.0 per mijlpaal, X.0.0 bij live-gang.
|
||||||
|
|
||||||
let tabs = [];
|
let tabs = [];
|
||||||
|
|||||||
+2
-2
@@ -329,7 +329,7 @@ function offsetRectilinearLoop(pts, d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Gevels: groepeert lijnstukken in de plattegrond tot doorlopende gevels
|
// Gevels: groepeert lijnstukken in de plattegrond tot doorlopende gevels
|
||||||
// (zelfde as + normaal + gevelvlak, aansluitend). segs: [{ axis ('x'|'z'),
|
// (zelfde as + normaal + gevelvlak, aansluitend of overlappend). segs: [{ axis ('x'|'z'),
|
||||||
// normal {x, z}, line (positie op de andere as), s0, s1 (s0 < s1) }, ...].
|
// normal {x, z}, line (positie op de andere as), s0, s1 (s0 < s1) }, ...].
|
||||||
// Geeft [{ axis, normal, line, s0, s1, segs (op s0 gesorteerd) }].
|
// Geeft [{ axis, normal, line, s0, s1, segs (op s0 gesorteerd) }].
|
||||||
// Gebruikt door de woning (latwerk/doek-patroon) en de buitenverlichting.
|
// Gebruikt door de woning (latwerk/doek-patroon) en de buitenverlichting.
|
||||||
@@ -338,7 +338,7 @@ function groupFacadeRuns(segs, opts) {
|
|||||||
const runs = [];
|
const runs = [];
|
||||||
segs.slice().sort((a, b) => a.s0 - b.s0).forEach(sg => {
|
segs.slice().sort((a, b) => a.s0 - b.s0).forEach(sg => {
|
||||||
const run = runs.find(r => r.axis === sg.axis && Math.abs(r.normal.x - sg.normal.x) < 1e-6 && Math.abs(r.normal.z - sg.normal.z) < 1e-6 &&
|
const run = runs.find(r => r.axis === sg.axis && Math.abs(r.normal.x - sg.normal.x) < 1e-6 && Math.abs(r.normal.z - sg.normal.z) < 1e-6 &&
|
||||||
Math.abs(r.line - sg.line) < lineTol && Math.abs(r.s1 - sg.s0) < gapTol);
|
Math.abs(r.line - sg.line) < lineTol && sg.s0 <= r.s1 + gapTol); // aansluitend of overlappend
|
||||||
if (run) { run.segs.push(sg); run.s1 = Math.max(run.s1, sg.s1); }
|
if (run) { run.segs.push(sg); run.s1 = Math.max(run.s1, sg.s1); }
|
||||||
else runs.push(Object.assign({}, sg, { s0: sg.s0, s1: sg.s1, segs: [sg] }));
|
else runs.push(Object.assign({}, sg, { s0: sg.s0, s1: sg.s1, segs: [sg] }));
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -126,9 +126,23 @@ window.LightingModel = (() => {
|
|||||||
const axis = Math.abs(normal.z) > 0.5 ? 'x' : 'z';
|
const axis = Math.abs(normal.z) > 0.5 ? 'x' : 'z';
|
||||||
const perp = axis === 'x' ? 'z' : 'x';
|
const perp = axis === 'x' ? 'z' : 'x';
|
||||||
const q0 = UnitModel.localToWorld(p.place, -W / 2, T / 2), q1 = UnitModel.localToWorld(p.place, W / 2, T / 2);
|
const q0 = UnitModel.localToWorld(p.place, -W / 2, T / 2), q1 = UnitModel.localToWorld(p.place, W / 2, T / 2);
|
||||||
|
// Gevel loopt tot de afgewerkte hoek, zodat endOffset altijd vanaf de
|
||||||
|
// zichtbare hoek telt: elk uiteinde + afwerking (latwerk + bekleding van
|
||||||
|
// de haakse wand die eroverheen loopt), en waar dit stuk de kopse kant
|
||||||
|
// van een doorlopende wand bedekt (skinExt) ook nog die wanddikte.
|
||||||
|
// Binnenhoeken en naden: zie de voetafdrukken in 3 en de overlap in 2.
|
||||||
|
const c = WallModel.claddingOffset(p.buitenMateriaal), e = p.skinExt || {};
|
||||||
|
const extL = (e.left > 0 ? e.left : 0) + c, extR = (e.right > 0 ? e.right : 0) + c;
|
||||||
|
const up = q1[axis] >= q0[axis];
|
||||||
|
// Voetafdruk van dit stuk incl. afwerking (om bedekte delen van andere
|
||||||
|
// gevels af te trekken, zie 3).
|
||||||
|
const corners = [[-W / 2, -p.place.thickness / 2], [W / 2, -p.place.thickness / 2], [-W / 2, T / 2], [W / 2, T / 2]]
|
||||||
|
.map(([lx, lz]) => UnitModel.localToWorld(p.place, lx, lz));
|
||||||
segs.push({
|
segs.push({
|
||||||
piece: p, normal, axis, perp, line: q0[perp],
|
piece: p, normal, axis, perp, line: q0[perp],
|
||||||
sAt0: q0[axis], sAtW: q1[axis], s0: Math.min(q0[axis], q1[axis]), s1: Math.max(q0[axis], q1[axis]),
|
sAt0: q0[axis], sAtW: q1[axis],
|
||||||
|
s0: up ? q0[axis] - extL : q1[axis] - extR, s1: up ? q1[axis] + extR : q0[axis] + extL,
|
||||||
|
foot: { x0: Math.min(...corners.map(q => q.x)), x1: Math.max(...corners.map(q => q.x)), z0: Math.min(...corners.map(q => q.z)), z1: Math.max(...corners.map(q => q.z)) },
|
||||||
override: overrides[u.id][w.side] || 'auto'
|
override: overrides[u.id][w.side] || 'auto'
|
||||||
});
|
});
|
||||||
})));
|
})));
|
||||||
@@ -153,6 +167,16 @@ window.LightingModel = (() => {
|
|||||||
runs.forEach(run => {
|
runs.forEach(run => {
|
||||||
const blocked = [];
|
const blocked = [];
|
||||||
const pos = []; // lampposities langs deze gevel (wereld-mm)
|
const pos = []; // lampposities langs deze gevel (wereld-mm)
|
||||||
|
// Delen van deze gevel die achter een andere wand liggen (bijv. het
|
||||||
|
// stuk van een wand dat de naad in loopt om een binnenhoek te sluiten)
|
||||||
|
// zijn geen zichtbare gevel: de gevel begint pas bij de afgewerkte
|
||||||
|
// buitenkant van die andere wand.
|
||||||
|
segs.filter(o => !run.segs.includes(o)).forEach(o => {
|
||||||
|
const f = o.foot;
|
||||||
|
const pMin = run.axis === 'x' ? f.z0 : f.x0, pMax = run.axis === 'x' ? f.z1 : f.x1;
|
||||||
|
const aMin = run.axis === 'x' ? f.x0 : f.z0, aMax = run.axis === 'x' ? f.x1 : f.z1;
|
||||||
|
if (run.line > pMin + 1 && run.line < pMax - 1 && aMax > run.s0 && aMin < run.s1) blocked.push([Math.max(run.s0, aMin), Math.min(run.s1, aMax)]);
|
||||||
|
});
|
||||||
run.segs.forEach(sg => {
|
run.segs.forEach(sg => {
|
||||||
const cfg = sg.piece.config, sW = cfg.studWidth;
|
const cfg = sg.piece.config, sW = cfg.studWidth;
|
||||||
const low = Math.min(cfg.wallHeightLeft, cfg.wallHeightRight) < H + 100;
|
const low = Math.min(cfg.wallHeightLeft, cfg.wallHeightRight) < H + 100;
|
||||||
|
|||||||
Reference in New Issue
Block a user