Files
road-compiler/workbench/client/probe/ol-ext-transform/README.md
que01 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

69 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ol-ext Transform 限时探针
对应 `.trellis/tasks/08-26-direct-edit-map-editor/implement.md` 第 1 步。
这个探针只回答一个问题:**能否复用 ol-ext 通用 handle 的命中、pointer 生命周期与视觉反馈。**
它不回答“道路语义怎么建模”——那部分由 `src/edit/``EditSession` / `projection` 负责,且已经独立单测通过。
## 怎么跑
```bash
npm install ol-ext --no-save # 门禁通过前不进依赖清单
npm run dev
```
然后打开 <http://localhost:5173/probe/ol-ext-transform/>。
不需要导入 OSM也不需要后端页面用 `fixture.ts` 里的合成道路。
## 你要做的事
拖动地图上那个**蓝色圆点手柄**,来回拖几次,快慢都试,然后看右侧面板。
## 三条门禁(必须同时成立)
| # | 门禁 | 面板怎么读 |
|---|---|---|
| 1 | OL `Map` 未被重建 | “实例 #N,累计构造 N 次”两个数字必须相等。再点几次“强制 React 重渲染”,数字仍要相等。 |
| 2 | 基线 source 未被写入 | “写入 0 次,几何未改变”。拖拽过程中这行**任何变化都算失败**。 |
| 3 | proxy 拖拽稳定且事件能转成 draft 值 | 看**「原始位移」**那行跟手连续变化、松手不跳;手柄不粘滞、不丢命中。 |
门禁 3 要看的是「原始位移」,不是「约束值」。约束值带生产钳位 `±5.4 米`
而 5.4 米在 zoom 20 只有约 47 像素,稍微拖远就会顶到边界显示成常量——那是正常的,不代表跟踪有问题。
「原始位移」不钳位,所以它才反映跟手质量。
两个数都是用生产代码算的(`signedMetersAlongAxis()` / `projectHandleValue()`
所以门禁 3 同时验证了“事件 → 约束值”这条链路。
另外面板会显示收到了多少个 `translating` 事件。这个数字和 React 渲染次数的比例是个有用的信号:
探针已经把逐帧读数用 `requestAnimationFrame` 合并了,生产实现还要更进一步——
ghost 直接写自己的 OL source绝不为每次指针移动重渲染 React 树。
注意:**卸载/重新挂载地图会构造新的 Map这是预期行为**,不算门禁 1 失败。门禁 1 针对的是拖拽与重渲染。
## 请回报给我
1. 三条门禁分别通过/未通过。
2. 未通过的,面板上的具体数字或现象。
3. 主观手感:拖拽是否顺滑,手柄命中是否可靠。
## 已知的、探针之外的结论
这些我已经查过,不用你验证,但会计入最终取舍:
- ol-ext 4.0.38BSD-3-Clause`peerDependencies: ol >= 5.3.0`,无运行时依赖。
- **不带 TypeScript 类型,也没有 `@types/ol-ext`。** 本目录的 `ol-ext.d.ts` 是我为探针手写的最小声明;
真要把 ol-ext 提为正式依赖,就要长期自己维护一份声明文件。
- `Transform``translate` 分支直接对传入 feature 调 `geometry.translate()`
所以它只能绑一次性 proxy绝不能绑编译产物图层——这也是门禁 2 存在的原因。
- 它的手柄模型是 bounding box 的 scale/rotate/stretch跟道路法线偏移、区间范围、路口 cutback 不是一回事。
即使门禁全过,它最多承担“通用手柄的命中与拖拽生命周期”,语义投影仍然是我们自己的 `projection.ts`
## 如果门禁没过
`design.md` 的回退优先级,删掉本目录,改用回退方案 1
原生 OL `Snap` + 小型 `PointerInteraction` adapter。
`HandleManifest → RoadEditOperation → RoadConstraint → preview solver` 的数据合约不变,
所以这一步失败只换输入层,第 2 步已交付的 `EditSession` / `projection` / `meters` 全部保留。