Commit Graph

13 Commits

Author SHA1 Message Date
bc4b9a9717 feat: add direct edit handles behind directEdit flag
Steps 1-3 of the main map road interval editor.

EditSession keeps the command stack, undo/redo and previewSeq arbitration as
pure logic with no OpenLayers reference, so all of it is unit-tested in node.
Pointer displacement converts to meters through EPSG:4326 and spherical
distance: treating a 3857 delta as meters desyncs the geometry from the cursor
by 1/cos(latitude). Handle drags project onto the axis the manifest declares
and clamp to its range, so the client never writes a coordinate into a road
polygon.

All of it sits behind a directEdit flag that defaults to off. With the flag off
the workbench requests no manifest, creates no extra source and registers no
interaction, so behaviour matches main.

The ol-ext probe passed its three gates but is not adopted for road handles.
Transform translates by the raw pointer delta, so a handle detaches from its
clamped constraint value: a drag reading -24.1 m produced a draft of -5.4 m.
Production needs the handle position derived from the constraint instead, which
means owning the position update, so native OL PointerInteraction will carry
the drag. ol-ext stays out of package.json; the probe is kept as a manual
harness. Reserve handles are unreachable with the current solver, recorded in
research/ rather than worked around.

Also names the dead backend when an API response is empty, instead of
surfacing "Unexpected end of JSON input" from response.json().

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-27 14:59:11 +08:00
f3f763f94c feat: persist direct edits with revision rebase 2026-08-27 12:52:40 +08:00
41c314fc61 feat: add direct edit preview APIs 2026-08-27 12:48:29 +08:00
3297d0c97a feat: insert direct edit constraint solver stage
Adds resolveDirectEditConstraints between compileRoadModel and
compileGeometry, per the parent design's data flow. The stage is an
identity transform until the individual constraint kinds land: it
returns empty road profiles, junction plans and handle manifest, so
compileGeometry's geometry code is untouched and output stays
byte-identical.

Constraint planning is separated from solving up front. Only `exact`
and `recheck` constraints may reach the solver; `disabled`,
`pending`, `conflicted` and `stale` are reported as unapplied with a
reason. SOLVED_KINDS starts empty and grows one entry per kind, so a
partially delivered solver reports what it skipped instead of
publishing half-solved geometry.

diagnostic() moves to src/compile/diagnostics.js so the solver can
share the compiler's diagnostic shape without depending on fs, which
would break the pure-function boundary that lets preview, the full
compile and the CLI export share one implementation.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-27 10:29:45 +08:00
ba8eaba9d9 feat: compile revisions from area config snapshots 2026-08-26 18:08:55 +08:00
c0c8a16dd4 feat: add immutable road revision storage 2026-08-26 17:54:38 +08:00
02c3a4d3e4 fix: avoid map refresh on road selection 2026-08-26 15:39:17 +08:00
3c5f39ed73 fix: refine workbench map layers 2026-08-26 15:26:41 +08:00
4133a5244a fix: restore scene preview styles 2026-08-26 15:09:27 +08:00
3ddb33e321 feat: migrate workbench to React 2026-08-26 15:01:07 +08:00
181e575e1e feat: add web OSM import workflow 2026-08-26 14:05:26 +08:00
81e02c670d feat: export portable native road packages 2026-08-26 11:59:48 +08:00
a2a1fe216a refactor: move road workbench into compiler package 2026-08-25 17:18:49 +08:00