feat: junction nodes — detector, fans over the approved chamfer, scene set (#302)
Вторая половина переработки узлов поверх ядра из прошлого коммита: - `junctionContractHoles` — объективный инвариант «тело ⊇ полосы ∪ веера в фасадной границе» как экспортная чистая функция; самопроверка на заведомо дырявой фикстуре входит в юниты. Первая формулировка детектора из ТЗ («окружено кладкой с ≥5 из 8 сторон») уточнена в §8.4 по факту измерения: она ложно флагует легитимный пол комнаты в острых внутренних углах. - `junctionNodeBound` — «гладкая» фасадная граница (конверт с обычными углами) экспортирована: ею клиппуются куски узла и ею же пользуются тесты. - юниты #302: веера/рефлекс/короткий толстый саппорт/детектор/репро end-to-end; хелпер тестов старого контракта переведён на strip-safe семантику по саппортам и фасадной границе. - смок `smoke_junction_holes`: контрактные пробы считаются в node из той же фикстуры и проверяются в браузере по реальному `d`-пути карточки. - сет из 16 golden-сцен стыков крупным планом (звёзды лучей: T/X/Y/острые/ почти коллинеарные/виртуальные/колонна/черновик) + сцена-репро владельца; билдер сцен и `zoomCenter` в harness. Контракт сцены `multiwall-junction-bevel-view-dark` инвертирован по решению владельца: проба в перекрытии полос обязана быть ЗАПОЛНЕНА (strip-safe), а не пустой. - семь мутантов §14, включая слепоту детектора и невозврат саппортов. - фикстура #197: площадь кладки выросла на 0.2 юнита² — слайвер вееров вдоль хорд фаски; константа обновлена с комментарием. Эталоны новых сцен идут отдельным коммитом с положенными трейлерами. Issue: #302 User-Visible: yes
@@ -2,6 +2,13 @@
|
||||
|
||||
## Unreleased
|
||||
|
||||
- Wall junctions no longer leave white wedges and notches. A node where three
|
||||
or more walls meet is now completed with sector fans and the exact strips of
|
||||
its rays on top of the existing chamfer: an acute junction is solid masonry,
|
||||
and the chamfer cut survives only where it does not touch the walls
|
||||
themselves. The no-holes invariant is checked automatically on a set of 16
|
||||
close-up junction scenes and on the plan from the original report
|
||||
([#302](https://github.com/Matysh/houseplan-card/issues/302)).
|
||||
- Every Plan editor tool now shows the same complete set of wall axes and
|
||||
structural endpoints. Switching from Walls to Thickness no longer hides room
|
||||
axes, while each tool keeps its own hints and live preview
|
||||
|
||||
@@ -8,6 +8,13 @@
|
||||
|
||||
## Не выпущено
|
||||
|
||||
- Стыки стен больше не оставляют белых клиньев и зазубрин. Узел, где сходятся
|
||||
три и больше стен, теперь достраивается угловыми веерами и точными полосами
|
||||
своих лучей поверх прежней фаски: острый стык — сплошная кладка, срез фаски
|
||||
остаётся только там, где он не задевает сами стены. Инвариант «дыр нет»
|
||||
проверяется автоматически на сете из 16 крупноплановых сцен стыков и на
|
||||
плане из исходного сообщения
|
||||
([#302](https://github.com/Matysh/houseplan-card/issues/302)).
|
||||
- Во всех инструментах редактора Плана теперь отображается один и тот же полный
|
||||
набор осевых линий и узлов стен. При переходе из «Стены» в «Толщина» оси
|
||||
комнат больше не исчезают, а подсказки и предпросмотр активного инструмента
|
||||
|
||||
@@ -185,6 +185,21 @@ excluded from this shared `roomGeom`, so a door does not change the room fill
|
||||
and a detached body cannot punch it. Full and Static render paths reuse the same
|
||||
structural cache instead of rebuilding wall booleans once per room.
|
||||
|
||||
**Junction nodes (#302).** A degree-3+ node keeps the approved #249 chamfer
|
||||
(`bevelMultiWallBody`, bounded by the node's join limit
|
||||
`MULTI_WALL_JOIN_LIMIT × halfDepth`), and AFTER it the node additively gets
|
||||
back what a chamfer must never eat: the exact support quads of its rays (each
|
||||
bounded by its own finite length, so a trimmed lateral phantom — #271 — cannot
|
||||
come back) and one sector fan per pair of angularly adjacent rays
|
||||
(`junctionNodeGeometry`): mitre up to the node limit, bevel chord past it,
|
||||
reflex sectors skipped. The pieces are clipped by the plain-corner facade
|
||||
bound (`junctionNodeBound`), so a node can never grow new facade at a concave
|
||||
vertex. The result is strip-safe: an acute junction is solid masonry, and the
|
||||
objective invariant «body ⊇ support strips ∪ fans, inside the facade bound» is
|
||||
machine-checked by `junctionContractHoles` in tests and the
|
||||
`smoke_junction_holes` wiring probe. Degenerate zero-area rings left by
|
||||
coincident chords are dropped.
|
||||
|
||||
**Hatch density is physical (#230).** The pattern step is a distance on the
|
||||
plan, not a count of coordinate units: `wallHatchStepUnits(cellCm)` returns
|
||||
`8 × (5 / cell_cm)`, which is 9.6 cm at every grid scale and exactly the
|
||||
|
||||
|
Before Width: | Height: | Size: 199 KiB After Width: | Height: | Size: 198 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 350 KiB After Width: | Height: | Size: 349 KiB |
|
Before Width: | Height: | Size: 338 KiB After Width: | Height: | Size: 336 KiB |
|
Before Width: | Height: | Size: 320 KiB After Width: | Height: | Size: 319 KiB |
|
Before Width: | Height: | Size: 319 KiB After Width: | Height: | Size: 317 KiB |
|
Before Width: | Height: | Size: 297 KiB After Width: | Height: | Size: 296 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 141 KiB |
@@ -2,7 +2,7 @@
|
||||
"version": 1,
|
||||
"fixture": "synthetic-only",
|
||||
"chromium": "151.0.7922.34",
|
||||
"sourceFingerprint": "03f814f86bf3582d85993d03efe835babf6f5e2d2c6401124588e4eb0a7b9278",
|
||||
"sourceFingerprint": "4869370390a8aaa4066ea720457ccafc421b87da1879eda2e6273935a3a0f4d9",
|
||||
"captureScriptSha256": "ce2e9542fed9dade3085be87d16f69adb2ac8262893ad78ad966b1b9673f2983",
|
||||
"command": "npm run build && node demo/docs/capture.mjs",
|
||||
"scenarios": {
|
||||
@@ -14,8 +14,8 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "03f814f86bf3582d85993d03efe835babf6f5e2d2c6401124588e4eb0a7b9278",
|
||||
"imageSha256": "c9e2203fe2df5c2627c861f92e9c4dfad585efb101df19e4b6388a6fbc27d01a"
|
||||
"sourceSha256": "4869370390a8aaa4066ea720457ccafc421b87da1879eda2e6273935a3a0f4d9",
|
||||
"imageSha256": "51551aa5237090b67ff4c48802b0f2518e884b48cb1b0319e782fced239953ea"
|
||||
},
|
||||
"view-touch": {
|
||||
"file": "02-view-touch.png",
|
||||
@@ -25,8 +25,8 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "03f814f86bf3582d85993d03efe835babf6f5e2d2c6401124588e4eb0a7b9278",
|
||||
"imageSha256": "a544bd821460e5b9b7a83b1636ce6b6a3fc50be68fe4f74779d23ec9e12abe6a"
|
||||
"sourceSha256": "4869370390a8aaa4066ea720457ccafc421b87da1879eda2e6273935a3a0f4d9",
|
||||
"imageSha256": "e52f419772f86480b336a0ab63d0c781207101b262fdf73f5fd581527e47dce4"
|
||||
},
|
||||
"space-create": {
|
||||
"file": "03-space-create.png",
|
||||
@@ -36,8 +36,8 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "03f814f86bf3582d85993d03efe835babf6f5e2d2c6401124588e4eb0a7b9278",
|
||||
"imageSha256": "6df7753f00b7d87cd35fd18fb8fbac0a2a7fa2e549902b3afee38f38c93a2ac0"
|
||||
"sourceSha256": "4869370390a8aaa4066ea720457ccafc421b87da1879eda2e6273935a3a0f4d9",
|
||||
"imageSha256": "329750c81a7a958c4fd105b2c80f85dce55ed87df9ddf0ea08084e4428e85f04"
|
||||
},
|
||||
"room-contour-close": {
|
||||
"file": "04-room-contour-close.png",
|
||||
@@ -47,8 +47,8 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "03f814f86bf3582d85993d03efe835babf6f5e2d2c6401124588e4eb0a7b9278",
|
||||
"imageSha256": "0129b6a5f1f97fa5d29db0a30bfd899bcfe53308a8ba3872d2a794132fccc9cc"
|
||||
"sourceSha256": "4869370390a8aaa4066ea720457ccafc421b87da1879eda2e6273935a3a0f4d9",
|
||||
"imageSha256": "e9a847d17b9bd02ad9fa39a6e7194f980144e90538eb94413f770f9539ceb7bc"
|
||||
},
|
||||
"plan-context-tray": {
|
||||
"file": "05-plan-context-tray.png",
|
||||
@@ -58,8 +58,8 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "03f814f86bf3582d85993d03efe835babf6f5e2d2c6401124588e4eb0a7b9278",
|
||||
"imageSha256": "7f243f578d2d286ae7911363571762e3910fe2117abc5253292d9ef2d578c8dc"
|
||||
"sourceSha256": "4869370390a8aaa4066ea720457ccafc421b87da1879eda2e6273935a3a0f4d9",
|
||||
"imageSha256": "7fd57bfc022211c5d37bd7c4a1a72b34ed7651fd577ada1d2314b64ae5061c21"
|
||||
},
|
||||
"device-editor": {
|
||||
"file": "06-device-editor.png",
|
||||
@@ -69,8 +69,8 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "03f814f86bf3582d85993d03efe835babf6f5e2d2c6401124588e4eb0a7b9278",
|
||||
"imageSha256": "24710a46be38418a09c4bdb3db8750611affea593d80c91cfe74c105ef8ed201"
|
||||
"sourceSha256": "4869370390a8aaa4066ea720457ccafc421b87da1879eda2e6273935a3a0f4d9",
|
||||
"imageSha256": "0ef6798b79ff0b78e1947b1dba547b92cbdf11b79b6335cffb8a415158c09b5d"
|
||||
},
|
||||
"device-display-preview": {
|
||||
"file": "06-device-display-preview.png",
|
||||
@@ -80,8 +80,8 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "03f814f86bf3582d85993d03efe835babf6f5e2d2c6401124588e4eb0a7b9278",
|
||||
"imageSha256": "1eaedd95180175f3db2c2e052bad70db63f6c70b296ec19c3d152ccbb81520ed"
|
||||
"sourceSha256": "4869370390a8aaa4066ea720457ccafc421b87da1879eda2e6273935a3a0f4d9",
|
||||
"imageSha256": "3842b3306d4e73a5b1d3475a96b4c1fd433c5c4334054a34d52f7cc0a20ae931"
|
||||
},
|
||||
"background-editor": {
|
||||
"file": "07-background-editor.png",
|
||||
@@ -91,8 +91,8 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "03f814f86bf3582d85993d03efe835babf6f5e2d2c6401124588e4eb0a7b9278",
|
||||
"imageSha256": "460f098f7761a41c6b30e42940cb5c9d6f96966ba34e4df04ea273575c293e93"
|
||||
"sourceSha256": "4869370390a8aaa4066ea720457ccafc421b87da1879eda2e6273935a3a0f4d9",
|
||||
"imageSha256": "f91c9575404abc64c5f03bb7dc9283b80231ada6bfd88774cfdf7d53fb46e0b2"
|
||||
},
|
||||
"room-card": {
|
||||
"file": "08-room-card.png",
|
||||
@@ -102,8 +102,8 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "03f814f86bf3582d85993d03efe835babf6f5e2d2c6401124588e4eb0a7b9278",
|
||||
"imageSha256": "66d8b0a509909822ff6b891a483bad9d2c72b20f08e287355883aa5205c6cee0"
|
||||
"sourceSha256": "4869370390a8aaa4066ea720457ccafc421b87da1879eda2e6273935a3a0f4d9",
|
||||
"imageSha256": "48a5685039a5e0de2a28190d857b193c86e2e63606e3c7a8c40fc9d2b190da4e"
|
||||
},
|
||||
"device-info": {
|
||||
"file": "09-device-info.png",
|
||||
@@ -113,8 +113,8 @@
|
||||
},
|
||||
"theme": "dark",
|
||||
"language": "en",
|
||||
"sourceSha256": "03f814f86bf3582d85993d03efe835babf6f5e2d2c6401124588e4eb0a7b9278",
|
||||
"imageSha256": "29b23ec03b320c35b3b6d725b3e69dd7a2cfcd1607cfbbe01dceb37c316964c3"
|
||||
"sourceSha256": "4869370390a8aaa4066ea720457ccafc421b87da1879eda2e6273935a3a0f4d9",
|
||||
"imageSha256": "83debe3fc2853406f8bc37df55d162a0b0dadc8c4e997dda4db83c07ca25caab"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||