core: shared pure plan-footprint math for spatial-grid and MCP - #600
core: shared pure plan-footprint math for spatial-grid and MCP#600ActArtech wants to merge 2 commits into
Conversation
Extract rotation-aware XZ footprint AABB/corners and expand-then-intersect gap overlap into packages/core/lib/plan-footprint. Spatial-grid and alignment-anchors delegate to it. Export via @pascal-app/core/plan-footprint and spatial-grid. Design note documents one source and gap call-site rules after pascalorg#569.
Aymericr
left a comment
There was a problem hiding this comment.
Thanks for picking up the note I left at the end of #569 — this is the right direction and I checked the math rather than assuming: planFootprintAABB's abs-cos/abs-sin extents are provably the same box as the rotated-corner loop it replaces in alignment-anchors.ts, planFootprintCorners preserves spatial-grid's rotation convention exactly (different corner order, nothing depends on order), the attachTo null-list matches the enum in item.ts, and it stays clear of the R3F guard in architecture.test.ts. The alignment-anchors.ts comment admitting it "mirrors the rotated-corner math the spatial-grid manager uses" was a real duplication and −58 lines is a real removal.
But as it stands the PR moves the number in the wrong direction, and that's what I want to fix before it lands.
The ask on #569 was that MCP stop being a third copy. With the rewire declared out of scope, aabbsOverlap in door-clearance.ts survives — and the new aabbsOverlapPlan is a line-for-line reimplementation of it. Post-merge there are three copies of expand-then-intersect instead of two, and MCP still uses its own. The extraction is the easy half; the consolidation was the point.
Three of the five exports have no callers. aabbsOverlapPlan and planFootprintAABBForItem exist for the deferred MCP work; planFootprintAABBFromCorners is called only by tests, which then assert it's identical to planFootprintAABB — so it's an identity helper proving itself. On #569 I asked you to delete aabbFromPlan and nodeItemAabb for exactly this, and AGENTS.md names dead code and speculative abstractions specifically.
Two paths, either fine by me:
- Finish it. Keep all five exports and rewire
door-clearance.ts/layout-clearance.ts/check-collisions.tsto import from@pascal-app/core/plan-footprint, deleting MCP'saabbsOverlapandPlanAabb. Heads-up on the trap that probably made you defer:@pascal-app/coreis only a devDependency ofpackages/mcpwhiledoor-clearance.tsalready runtime-importsgetScaledDimensionsfrom@pascal-app/core/schema— that's a latent packaging bug, and moving more runtime code across that edge means promoting it to a real dependency. Please also keep thegap: 0versus0.08distinction from #569 intact per call site; that's the bug I'd most want a test to hold. - Or narrow it. Ship only
planFootprintCornersandplanFootprintAABB, drop the other three exports and their tests, and leave the subpath export in as the seam for the follow-up.
On the wiki page: I'd rather it didn't say "Aymericr noted…" — the other wiki/architecture/ pages state the rule, not who asked for it, and 43 lines of page restating the header of a 133-line math module is more provenance than durable rule. Fold the gap-semantics table into the module header and skip the page, or cut it to the invariant plus the call-site table.
Useful side-finding worth carrying into the rewire: your aabbsOverlapPlan comment ("expand each box by gap") is right and MCP's existing one ("expand each box by gap/2") describes something the code doesn't do. Fix that comment while you're in there.
What does this PR do?
Extracts rotation-aware plan (XZ) footprint math into a pure, Node-safe core module so spatial-grid, alignment anchors, and (later) MCP layout clearance share one formula after #569.
packages/core/src/lib/plan-footprint.ts: corners, AABB, expand-then-intersect gap overlap, scaled item helper (null for wall/ceiling hosts)@pascal-app/core/plan-footprint(pure) and re-export from@pascal-app/core/spatial-gridwiki/architecture/plan-footprint.md(one source; packing gap ~0.08 vs check/verifygap: 0)Out of scope: rewiring MCP
furnish_room/verify_scene/ door keep-outs to call these helpers (follow-up).How to test
bun test packages/core/src/lib/plan-footprint.test.ts— expect all passbun test packages/core/src/services/alignment-anchors.test.ts— still greenbun run --cwd packages/core build—tsc --buildcleanbun run check packages/core/src/lib/plan-footprint.ts packages/core/src/lib/plan-footprint.test.ts packages/core/src/hooks/spatial-grid/spatial-grid-manager.ts packages/core/src/services/alignment-anchors.ts@pascal-app/core/plan-footprintand@pascal-app/core/spatial-gridand confirmplanFootprintAABBreturns the same boxScreenshots / screen recording
N/A — non-visual change (pure geometry helpers + tests + wiki note).
Checklist
bun test/bun run --cwd packages/core buildbun run checkon changed files)wiki/architecture/plan-footprint.md)mainbranchNote
Medium Risk
Unifies alignment and floor-collision footprint math (intentionally); wrong rotation convention would affect placement, snapping, and future MCP clearance, though tests and delegation to prior spatial-grid formulas mitigate that.
Overview
Introduces
packages/core/src/lib/plan-footprint.tsas the single pure XZ source for rotation-aware footprint corners, conservative AABBs, expand-then-intersect overlap with configurable gap, and a scaledplanFootprintAABBForItemhelper (null for wall/ceiling hosts).Spatial-grid and alignment-anchors stop inlining duplicate math and delegate to this module; the spatial-grid entry also re-exports the helpers. A new
@pascal-app/core/plan-footprintpackage export targets Node/MCP callers without pulling the grid manager.Adds unit tests for rotation, corner/AABB parity, gap semantics, and item scaling; documents the module in
wiki/architecture/plan-footprint.md. MCP furnish/verify rewires are explicitly out of scope.Reviewed by Cursor Bugbot for commit 6384a73. Bugbot is set up for automated code reviews on this repo. Configure here.