Skip to content

feat: add production measurement tools#505

Merged
Aymericr merged 9 commits into
mainfrom
feat/measurement-tools
Jul 17, 2026
Merged

feat: add production measurement tools#505
Aymericr merged 9 commits into
mainfrom
feat/measurement-tools

Conversation

@Aymericr

@Aymericr Aymericr commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add persistent associative distance, angle, perimeter, area, and volume measurements across 2D and 3D
  • add smart magnetic snapping, axis feedback, direct editing, zone quantity reports, and measurement visibility controls
  • prefer floor surfaces near wall corners for polygon measurements while preserving deliberate wall/tabletop picks and Alt raw selection
  • make Escape finish valid area drafts with three or more points, preserving invalid drafts for correction
  • integrate with current polygon editing, room boundary, plugin, autosave, and undo behavior

Verification

  • bun run check-types
  • bun run check
  • bun test (2311 pass, 1 intentional skip)
  • bun run build
  • focused measurement, room detection, slab edge, polygon editing, and wall history suites

Note

High Risk
Large cross-cutting change to core schema, scene sync, clone graphs, and editor pointer handling; incorrect measurement or zone sync could corrupt saved scenes or misreport quantities.

Overview
Introduces a first-class measurement scene node (distance, angle, area, perimeter, volume) with planar validation, optional semantic feature anchors that survive clone/paste via reference remapping, and geometry helpers exported from core.

Extends the node registry with measurement contributions (features, match, quickMeasure) and richer floorplan labels; sceneRegistry now exposes a revision counter when 3D object membership changes.

Ships substantial 2D floorplan tooling: draft/commit flows with magnetic axis guides, registry-geometry snapping, vertex/midpoint editing, extrusion UI for volume, and a separate smart quick-measure HUD layer. Viewer Display menu gains a Measurements visibility toggle; dev react-scan / Agentation load only when PASCAL_DEV_DIAGNOSTICS=1.

Zones can autoFromWalls with boundaryWallIds; space-detection sync plans polygon updates from detected rooms, and deriveZoneQuantityReport computes footprint vs enclosed-room quantities from matching walls/slabs/ceilings.

Reviewed by Cursor Bugbot for commit 64dc1e5. Bugbot is set up for automated code reviews on this repo. Configure here.

Aymericr and others added 9 commits July 14, 2026 00:09
- Smart measurement lens: registry-owned wall/slab/zone hover reports with a
  single top-center HUD, click-to-pin, latest-event back pressure, and no
  scene writes
- Conservative derived zone quantities (footprint, perimeter, proven
  enclosure, gross wall/floor surface, flat-room volume) with the
  selected-zone blueprint panel
- Direct editing of committed measurements via selected-only 2D/3D vertex
  affordances with midpoint insertion, cancellation, and one-write history
- Shared measurement surface-query session; 2D tracing joins the
  slab/ceiling magnetic pipeline with registered-corner snapping
- Angle arcs on the smaller angle, indigo active/black resting hierarchy,
  screen-sized normal-aligned contact rings

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Measurement drafting and committed-edit paths gated wall, semantic, and
axis magnetism on isMagneticSnapActive(), which is only true in the
'lines' snapping mode — in the default 'grid' mode corners and wall
intersections barely attracted (3D association fell to the 0.012 m
verify tolerance, 2D wall radii to the 0.05 m connect stick).

Measurement is an analysis tool whose anchors exist to bind real
geometry, so its snapping no longer consults the construction
snapping-mode chip: 2D/3D drafting and committed vertex edits are always
magnetic, Alt is the temporary bypass in both views (releasing the axis
pull, wall magnetism, and the 2D projected-geometry pull, and shrinking
association to contact tolerance). A discrete 2D wall snap (endpoint /
midpoint / crossing) now outranks the locked axis pull, and committed 2D
edits route the fallback through the raw pointer so free drags no longer
quantize to the construction grid. Volume extrusion height keeps its
mode-driven grid quantize.

Codex adversarial review confirmed the diagnosis and plumbing; its 2D
Alt-depth and grid-quantize findings are applied. New
surface-plan-snap tests pin the magnetic override seam.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts:
#	apps/editor/app/globals.css
#	packages/core/src/lib/space-detection.test.ts
#	packages/core/src/lib/space-detection.ts
#	packages/editor/src/components/editor-2d/renderers/floorplan-registry-layer.tsx
#	packages/editor/src/hooks/use-auto-save.ts
#	packages/editor/src/hooks/use-keyboard.ts
#	packages/editor/src/lib/plugin-panels.ts
#	packages/nodes/src/shared/polygon-vertex-affordance.ts
#	packages/nodes/src/slab/floorplan-affordances.ts
#	packages/plugin-trees/src/index.ts
#	packages/plugin-trees/src/instanced.tsx
@Aymericr
Aymericr merged commit ae87ca5 into main Jul 17, 2026
3 checks passed
@Aymericr
Aymericr deleted the feat/measurement-tools branch July 17, 2026 17:01

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 64dc1e5. Configure here.

snapshots.set(
levelId,
`${levelWallSnapshot(walls)}##${zones.map(zoneGeometrySignature).sort().join('||')}`,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Zone edits rerun slab sync

Medium Severity

The levelStructureSnapshots now includes zone geometry, causing runSpaceDetection to trigger when only zone data changes. This leads to unnecessary re-reconciliation of auto slabs and ceilings, potentially recreating auto slabs a user had manually removed, a feedback loop the previous implementation aimed to prevent.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 64dc1e5. Configure here.

zone.polygon,
polygon.map((point) => [point.x, point.y]),
),
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quantities ignore live zone polygon

Medium Severity

deriveZoneQuantityReport computes footprint, perimeter, and room matching from zone.polygon only. Procedural zones with autoFromWalls can have a stale stored polygon while resolveAutoZonePolygon already derives the live footprint from moved walls, so quantity reports can disagree with the scene.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 64dc1e5. Configure here.

if (Array.isArray(anchor)) return anchor
const nodeId = idMap.get(anchor.reference.nodeId)
return nodeId ? { ...anchor, reference: { ...anchor.reference, nodeId } } : anchor
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clone keeps old anchor ids

Medium Severity

When remapping measurement feature anchors during clone, if idMap has no entry for a referenced host, the anchor keeps the original nodeId. The cloned measurement can keep pointing at nodes outside the clone (or the wrong instance in the target scene) instead of falling back to free anchors.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 64dc1e5. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant