fix: preserve wall thickness transitions

Issue: #150
User-Visible: yes
This commit is contained in:
Sergey Matyunin
2026-08-18 17:36:54 +03:00
parent fd0b52f3a9
commit 6cbf9fbdf0
11 changed files with 372 additions and 12 deletions
+7
View File
@@ -365,6 +365,13 @@ physical interval when an acute child ring cannot be subtracted. Paper and
masonry paths are emitted by that same geometry pass. Computed independent
junction patches enter as extras only after room opening cuts, so an opening
cannot cut a coincident partition and room exterior authority remains intact.
Before the exterior offset is built, each saved atomic endpoint splits its
containing collinear union edge. Offset changes are explicit butt steps at that
endpoint, including nonzero-to-zero transitions. The topology tolerance starts
in render units and is divided by the current edge length before it is compared
with or used to de-duplicate normalized `t` fractions; this keeps the result
scale-independent and prevents one interval's depth from leaking into its
neighbour.
The full card retains the
pair in `_wallUnionCache`; static cards retain it in a weak server-snapshot
cache guarded by a structural geometry fingerprint. This is computed render
+5
View File
@@ -2,6 +2,11 @@
## Unreleased
- Collinear exterior walls now change thickness exactly at their saved
breakpoint. After splitting a room, a 10 cm wall therefore keeps its full
depth up to the divider without leaking onto an adjacent zero-thickness
facade; Plan, View, static, hidden isometric and light geometry share the
corrected outline ([#150](https://github.com/Matysh/houseplan-card/issues/150)).
- Home Assistant devices and individual entities manually assigned to a room
without an HA Area now stay in that exact room instead of returning to their
registry Area. Existing saved assignments recover automatically, and
+6
View File
@@ -8,6 +8,12 @@
## Unreleased
- Коллинеарные внешние стены теперь меняют толщину точно в сохранённой точке
перехода. После разделения комнаты стена 10 см сохраняет полную толщину до
перегородки и не продолжается по соседнему фасаду с нулевой толщиной; План,
View, статическая и скрытая изометрическая геометрия, а также свет используют
один исправленный контур
([#150](https://github.com/Matysh/houseplan-card/issues/150)).
- Устройства и отдельные сущности Home Assistant, вручную назначенные комнате
без HA-зоны, теперь остаются именно в ней, а не возвращаются в исходную зону
из реестра. Уже сохранённые назначения восстанавливаются автоматически, а
+6
View File
@@ -1981,6 +1981,12 @@ require hands on real hardware — they remain for the human pass.
path appears; room-card and tooltip m² both decrease to the same inner-
contour area
[auto: smoke_wall_thickness]
- [ ] **Exact thickness transition after Split**: split one zero-thickness room,
apply 10 cm to every wall of one child and keep the other child at zero.
Both halves of the 10 cm facade end at the divider endpoint; no hatch,
paper or light masonry continues along the zero side. Plan, View, static
and hidden Iso consume the same stepped geometry
[auto: smoke_wall_thickness_transition + test/wall-thickness.test.mjs]
- [ ] **Openings cut the slab**: a door/window/gate on a thick wall leaves a gap in
the body; the door swing is offset toward the inner face and gate leaves
toward the exterior face; with
+15 -2
View File
@@ -53,6 +53,15 @@ paper and masonry paths come from one cached structural pass in flat renderers;
live HA state ticks do not repeat the boolean topology. Saved room and wall data
is not migrated or rewritten.
Every endpoint of an exterior atomic interval is materialised on a collinear
boolean-union edge before offsetting. Unequal neighbouring half-depths form a
hard butt step at that exact endpoint on both the inner and outer faces; the
larger depth is never tapered or extended over the smaller/zero interval.
Geometry tolerances are render-space distances and are converted to a local
dimensionless edge fraction before breakpoint comparison or de-duplication.
This preserves the same `0 ↔ h` and `h1 ↔ h2` transition at normalized and
production (`coordScale = 1000`) scales.
## 3. Body render
Production body is the **ring** `outset(poly, half) − inset(poly, half)` per
@@ -153,7 +162,9 @@ room; nested-room tie; partially out-of-span legacy opening; overlapping
opening de-duplication; shared symbol/cut/tunnel rejection; thick-door tunnel
clipping and room-side colour ownership; whole and
atomic rekey after edge/scale; corner Split exterior equality across
0/1/15/100 cm, unequal arms, both windings and convex/concave endpoints.
0/1/15/100 cm, unequal arms, both windings and convex/concave endpoints;
production-scale `0 ↔ 10`, `10 ↔ 20` and `1 ↔ 100` collinear transitions at
their exact endpoint.
Browser: seamless frame; fill not in hatch; m² drops with thickness; a partial
virtual stretch, its solid thick remainders and Undo move as one real resize;
the virtual rubber band paints above the real body; sun starts at the room-side
@@ -162,7 +173,9 @@ solid-only in both full and static cards while a 20 cm body keeps its hatch;
door/window/gate tunnels repeat outer/shared room fills without an axis seam
(`demo/smoke_opening_tunnel_fill.mjs`); corner Split keeps the same facade in
Plan/View/kiosk/static/isometric surfaces and the light barrier
(`demo/smoke_split_corner_wall.mjs`).
(`demo/smoke_split_corner_wall.mjs`); a Split followed by all-room thickness
keeps the neighbouring zero facade clear across Plan, View, static, hidden Iso
and light masonry (`demo/smoke_wall_thickness_transition.mjs`).
## 9. Independent partitions, drafts and columns