88 lines
4.5 KiB
Markdown
88 lines
4.5 KiB
Markdown
# 路口主导的短路段整条置灰
|
||
|
||
父任务:`.trellis/tasks/08-26-direct-manipulation-road-editor`。约束模型与编辑所有权的权威定义在父任务 `design.md`。
|
||
|
||
## 问题
|
||
|
||
`src/compile/direct-edit-solver.js` 里 `editable: false` 的唯一来源是 `unavailable`:
|
||
|
||
```js
|
||
const start = Math.min(1, startReserve);
|
||
const end = Math.max(0, 1 - endReserve);
|
||
const unavailable = start >= end;
|
||
```
|
||
|
||
但 `junctionReserves()` 给每端保留区的比例有硬上限 `Math.min(0.45, cutback / length)`,
|
||
于是 `start ≤ 0.45`、`end ≥ 0.55`,`start >= end` 结构上永远为假。
|
||
**该分支是死代码,连带那句提示语「该道路全部位于路口保留区,请进入 JunctionTools 编辑。」永远不可能显示。**
|
||
|
||
实测 `test/fixtures/fengshu-er-road.osm`:126 个道路手柄,0 个 `editable: false`。
|
||
|
||
后果是短路段拿到了一条无意义的编辑带(`test/fixtures/fengshu-er-road.osm`,20 个有保留区的段):
|
||
|
||
| 路长(米) | 总宽(米) | 窗口 | 可编辑带(米) |
|
||
| --- | --- | --- | --- |
|
||
| 14.5 | 9.8 | [0.45,0.55] | 1.5 |
|
||
| 15.4 | 9.8 | [0.45,0.55] | 1.5 |
|
||
| 18.6 | 9.8 | [0.45,0.55] | 1.9 |
|
||
| 19.1 | 9.8 | [0.45,0.55] | 1.9 |
|
||
| 19.2 | 9.8 | [0.45,0.55] | 1.9 |
|
||
| 19.6 | 6.5 | [0.45,0.55] | 2.0 |
|
||
| 82.2 | 9.8 | [0.17,0.83] | 54.9 |
|
||
| 199.2 | 9.8 | [0.00,0.93] | 185.6 |
|
||
|
||
第一行那条路只有 14.5 米长、9.8 米宽,cutback 是 `max(宽度) × 1.4 ≈ 13.7` 米——
|
||
**每一端**的路口都要这条路的 94%,两端合计 188%,远超全长。上限把它压成各 45%,
|
||
凭空造出中间 10%(1.5 米)的「可编辑带」。
|
||
|
||
这违反两条已写明的约定:
|
||
|
||
- 父任务不变量「相邻 profile 之间必须有可计算的过渡」。约束默认 `transition: 'smoothstep'`
|
||
作用于区间两端回归基线,1.5 米的区间两侧紧贴保留区,没有任何余量做过渡。
|
||
- 父任务「编辑所有权」:主地图只编辑两个 junction reserve **之间**的道路内部 interval。
|
||
这种路的真实路口几何占满全长,根本不存在「之间」。
|
||
|
||
## 目标
|
||
|
||
让路口几何占满的短路段整条归 JunctionTools,恢复那个分支的可达性,
|
||
并使父任务 prd 的验收标准「落在 junction reserve 内的手柄不可拖动,并提示进入 JunctionTools」
|
||
从空真变成可演示。
|
||
|
||
## 判据
|
||
|
||
**可编辑带长度(米)< 道路总宽度(米)→ 该 segment 的所有道路手柄 `editable: false`。**
|
||
|
||
用物理长度而非归一化 station,理由是过渡段需要的是实际距离,与道路长短无关。
|
||
一条比自身宽度还短的编辑带装不下横断面的平滑变化。
|
||
|
||
在上表数据上分界干净,无边界模糊样本:1.5 < 9.8 置灰;54.9 > 9.8 保留。
|
||
恰好切出可编辑带 < 10 米的那 6 段。
|
||
|
||
判断必须在上限生效**之后**用实际窗口算,而不是拿未截断的 `cutback / length` 之和——
|
||
后者与「过渡段放不下」这件事没有直接关系。
|
||
|
||
## 验收标准
|
||
|
||
- [ ] 可编辑带短于道路宽度的 segment,其全部 `road-*` 手柄 `editable: false` 且带 `disabledReason`。
|
||
- [ ] `disabledReason` 复用既有文案,引导进入 JunctionTools。
|
||
- [ ] 可编辑带不短于道路宽度的 segment,行为与当前 main 完全一致(手柄数量、位置、`editable: true`)。
|
||
- [ ] 置灰不改变 `reserves` 本身,也不改变任何几何输出:`compileGeometry` 结果与置灰前逐字节一致。
|
||
- [ ] 置灰的 segment 仍然出现在 manifest 中(不是被删除),否则客户端无法解释为什么不能编辑。
|
||
- [ ] junction 手柄不受影响,仍然 `editable: true`。
|
||
- [ ] `test/direct-edit-solver.js` 覆盖:短路段全部置灰、正常路段不受影响、判据边界(带长 ≈ 宽度)。
|
||
- [ ] `npm run test`、`npm run test:client`、`npm run test:client:unit`、`npm run format:check`、`npm run build` 全绿。
|
||
- [ ] 客户端无需改动即可显示灰色手柄与原因(`08-26-direct-edit-map-editor` 已实现该路径)。
|
||
|
||
## 不做
|
||
|
||
- 不改 `junctionReserves()` 的 0.45 上限本身。上限保护的是 reserve 语义,改它会牵动 junction 侧几何。
|
||
- 不改 cutback 的推导公式。
|
||
- 不实现 JunctionTools 侧的编辑能力(属 `08-26-direct-edit-junction-tools`)。
|
||
- 不做客户端改动。
|
||
- 不把置灰的 segment 从 manifest 里移除。
|
||
|
||
## 顺序依赖
|
||
|
||
与 `08-26-direct-edit-map-editor` 的第 4、5 步无依赖,可并行或后置。
|
||
客户端置灰渲染路径已在该任务第 3 步交付并有单测覆盖,本任务只补上服务端的输入。
|