mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-30 19:58:50 +00:00
fix: close both code-review mediums and drop the dead paper layer (#302 r1 M1,M2)
**M1.** `docs/WALL-THICKNESS.md` §3 «Junction nodes» переписан под решение №5: полный mitre, фаска #249 в отставке, `bevelMultiWallBody` — только адресный латеральный трим. Прежний абзац описывал отменённое утреннее решение. **M2.** Guard мутанта `junction-fans-disabled` собирает `test-build` и бандл перед смоком: `smoke_junction_holes` — единственный смок, импортирующий из `test-build`, и в чистом worktree он падал `ERR_MODULE_NOT_FOUND` до применения мутации. Ревью прав: после переякорения guard'а на смок я не перегнал его штатным харнесом — только ручной test-build-патч, который worktree не видит. **Low + следствие.** `bevelMultiWallPaper` удалена как мёртвый код; следом измерено (фикстура #197 и репро владельца — байт в байт с веерами и без), что и `paperWithNodeCorners` бумаге ничего не даёт: footprint ∪ shell уже покрывает каждый узел. Слой удалён целиком, бумага возвращена к rawPaper. Осиротевший мутант `multi-wall-paper-full-origin-cut` (#261, «белый клин от вычитающего разреза бумаги») снят с обоснованием: в бумаге не осталось ни одного вычитания — этот класс регресса невозможен по построению. `npm test` 1303/1303; `golden:verify` 126/126; контракт-проба репро — 0. Issue: #302 User-Visible: no
This commit is contained in:
+7
-74
@@ -2952,40 +2952,6 @@ function bevelMultiWallBody(
|
||||
return current;
|
||||
}
|
||||
|
||||
function bevelMultiWallPaper(
|
||||
paper: any,
|
||||
centre: any,
|
||||
map: MultiWallNodeMap,
|
||||
): any {
|
||||
let beveled = paper;
|
||||
let protectedStrips: any = null;
|
||||
try {
|
||||
protectedStrips = multiWallProtectedMapGeometry(map);
|
||||
} catch {
|
||||
return paper;
|
||||
}
|
||||
for (const node of map.nodes) {
|
||||
try {
|
||||
const cuts = multiWallEffectiveCutGeometry(
|
||||
node, map, true, true, protectedStrips,
|
||||
);
|
||||
if (cuts) beveled = difference(beveled, cuts);
|
||||
} catch {
|
||||
// Isolate a failed optional node cut; retain the last valid paper.
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (protectedStrips) {
|
||||
const protectedPaper = intersection(protectedStrips, paper);
|
||||
beveled = union(beveled, protectedPaper);
|
||||
}
|
||||
// Paper is the complete room footprint. Interior bevel cuts expose floor,
|
||||
// not the scene background, so the centre union must always remain solid.
|
||||
return union(centre, beveled);
|
||||
} catch {
|
||||
return paper;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collapse arithmetic noise on computed junction vertices before polyclip sees
|
||||
@@ -3191,15 +3157,7 @@ export function floorFootprintGeometry(
|
||||
const paper = exterior.shell?.length
|
||||
? union(exterior.centre, exterior.shell)
|
||||
: exterior.centre;
|
||||
return multiWallNodes.nodes.length
|
||||
? paperWithNodeCorners(
|
||||
paper, multiWallNodes,
|
||||
junctionNodeBound(
|
||||
rooms, walls, openCuts, pitch, cellCm, gridPitch, coordScale,
|
||||
multiWallNodes,
|
||||
),
|
||||
)
|
||||
: paper;
|
||||
return paper;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
@@ -3260,19 +3218,6 @@ export function junctionNodeBound(
|
||||
}
|
||||
}
|
||||
|
||||
/** Paper under the node corner: the same additive supports and fans (#302). */
|
||||
function paperWithNodeCorners(paper: any, map: MultiWallNodeMap, bound?: any): any {
|
||||
const corners = junctionNodeGeometry(map);
|
||||
let out = paper;
|
||||
for (const piece of [...corners.supports, ...corners.fans]) {
|
||||
try {
|
||||
let ring: any = [closedRing(piece)];
|
||||
if (bound) ring = intersection(ring, bound);
|
||||
if (ring?.length) out = union(out, ring);
|
||||
} catch { /* keep paper */ }
|
||||
}
|
||||
return dropDegenerateRings(out, Math.max(map.epsilon, 1e-9) ** 2);
|
||||
}
|
||||
|
||||
export function polyclipToPathD(geom: any): string {
|
||||
if (!geom) return '';
|
||||
@@ -3520,15 +3465,11 @@ export function wallBodiesGeometry(
|
||||
: [];
|
||||
// Paper: the approved chamfer first, then the same additive fans that
|
||||
// complete the masonry corner complete the paper beneath it (#302).
|
||||
const paperGeom = multiWallNodes.nodes.length
|
||||
? paperWithNodeCorners(
|
||||
rawPaperGeom, multiWallNodes,
|
||||
junctionNodeBound(
|
||||
rooms, walls, openCuts, pitch, cellCm, gridPitch, coordScale,
|
||||
multiWallNodes,
|
||||
),
|
||||
)
|
||||
: rawPaperGeom;
|
||||
// Paper needs no node pieces: the footprint-plus-shell union already
|
||||
// covers every junction (measured on #197 and the owner repro — byte-equal
|
||||
// with and without them), and with the subtractive paper bevel gone the
|
||||
// #261 white-wedge class is impossible by construction.
|
||||
const paperGeom = rawPaperGeom;
|
||||
const bodyOf = (ring: typeof roomRings[number]): any => {
|
||||
const outset: any = closedRing(ring.outset);
|
||||
return ring.inset ? difference(outset, closedRing(ring.inset) as any) : outset;
|
||||
@@ -3972,15 +3913,7 @@ export function paperRoomShapesWithWalls(
|
||||
const multiWallNodes = multiWallNodesForGeometry(
|
||||
rooms, walls, openCuts, pitch, cellCm, gridPitch, coordScale,
|
||||
);
|
||||
const paper = multiWallNodes.nodes.length
|
||||
? paperWithNodeCorners(
|
||||
rawPaper, multiWallNodes,
|
||||
junctionNodeBound(
|
||||
rooms, walls, openCuts, pitch, cellCm, gridPitch, coordScale,
|
||||
multiWallNodes,
|
||||
),
|
||||
)
|
||||
: rawPaper;
|
||||
const paper = rawPaper;
|
||||
const path = polyclipToPathD(paper);
|
||||
if (path) return [{ path }];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user