docs: a room junction is a side, not just a corner (#229 r2 M1)

The tolerance fix in r2 named the room's nearest polygon vertex as the point
of contact, which silently excluded the T-junction — a partition meeting the
middle of a room wall. That is a documented product case (141-wall-junctions
§13.1) and the code already measures distance to the edge, not the vertex
(distToSegment over roomEdges). Merging would have run straight through a
legitimate node.

AC2 now proves the room case with a T-junction into the middle of a long
side, and a mutant restores the vertex-only search.

Issue: #229
User-Visible: no
This commit is contained in:
Codex
2026-08-21 11:55:51 +03:00
parent 5c560df1a2
commit 1ecd267138
+15 -3
View File
@@ -116,8 +116,17 @@ run of one thickness», оптимизатор её вызывает (`plan-opti
проверяется совпадение концов самих перегородок (§8.3). Отдельного допуска для
ребра комнаты, колонны или черновика нет: иначе один и тот же зазор считался бы
стыком в одном случае и не считался в другом, а AC2 перестал бы быть однозначным.
Точка стыка берётся у ребра комнаты — ближайшая вершина полигона, у колонны —
её центр, у черновика — конец сохранённого контура.
Точка стыка берётся у ребра комнаты — **ближайшая точка на любой стороне
полигона**, а не только его вершина; у колонны — её центр, у черновика — конец
сохранённого контура.
Именно сторона, а не вершина: T-стык перегородки к середине комнатной стены —
штатный случай продукта (`docs/specs/141-wall-junctions.md` §13.1 прямо называет
примыкание «к середине существующей wall/partition»), и такой узел обязан
пережить слияние. Примитив для этого в коде уже есть — `distToSegment` по
рёбрам комнаты (`plan-snap-overlay.ts:313`), считающий расстояние до отрезка.
Ревизия r3: прежняя редакция говорила «ближайшая вершина полигона» и пропускала
ровно этот случай (находка M1 ревью r2).
### 8.3. Допуски
@@ -219,7 +228,9 @@ plan-only export, merge и оптимизация сохраняли согла
с крайними точками цепочки. **Доказательство:** `unit` + `smoke`.
2. **AC2 — узел с причиной остаётся.** Слияния не происходит, если на общем конце
есть третья перегородка, ребро комнаты, колонна или конец черновика — четыре
отдельных случая. **Доказательство:** `unit`.
отдельных случая. Случай «ребро комнаты» проверяется **T-стыком к середине
стороны**, а не только к её углу: тест с примыканием в середину длинного ребра
красный, если реализация ищет лишь вершины полигона. **Доказательство:** `unit`.
3. **AC3 — проём не двигается, в обоих представлениях.** Перегородка с дверью
посередине сращивается с соседней; координаты центра, полученные через
`resolvePartitionOpening`, до и после совпадают, `host.id` указывает на
@@ -265,6 +276,7 @@ plan-only export, merge и оптимизация сохраняли согла
| `partition-merge-disabled` | не вызывать слияние в `_finishWallChain` | смок AC1 |
| `partition-merge-ignores-thickness` | сращивать при разном `cm` | юнит AC4 |
| `partition-merge-ignores-junction` | сращивать через примыкание третьей стены | юнит AC2 |
| `junction-checks-room-vertices-only` | искать примыкание комнаты только по вершинам полигона | юнит AC2 (T-стык) |
| `partition-merge-keeps-relative-t` | не пересчитывать `host.t` | юнит AC3 |
| `partition-merge-skips-materialization` | не обновлять `x/y/angle` проёма | юнит AC3 |
| `chain-merge-sweeps-whole-space` | сращивать все перегородки пространства, а не компоненту цепочки | юнит AC8 |