# 自动匹配 Cesium 巡航车道中心:技术设计 ## 设计目标 巡航路线以 osm2streets internal road topology 与已渲染的 Driving lane polygon 为几何事实源。道路区间直接使用 polygon 的中轴,不再对 OSM way 中心线施加固定米数偏移;OSM 只提供原始标签和转向语义,不再作为最终路口拓扑。 ## 数据流 ```text network.json ──▶ internal road/intersection directed graph OSM XML ──▶ turn:lanes semantics │ lane_polygons.geojson ──▶ validated Driving lane centerlines │ ▼ maneuver-aware lane selection │ ▼ internal road lane sections + surface-constrained junction curves │ ▼ vehicle-route.json + diagnostics ``` `scripts/build-area.js` 在 preview stage 调用 `buildVehicleRoute(osmPath, lanePolygonsPath)`。`lane_polygons.geojson` 同时写入 preview manifest inputs,`scripts/lib/area-diagnostics.js` 使用既有 SHA-256 freshness 检查自动识别过期路线。 ## 模块边界 ### `scripts/lib/lane-geometry.js` 新增纯几何共享模块,承载: - 校验 Driving `Polygon` ring; - 通过 polygon 两侧对应顶点中点提取 lane centerline; - 米制距离、方向对齐、端点排序和 polyline 拼接所需的无副作用 helper。 `scripts/lib/turn-lane-arrows.js` 改为导入共享 `laneCenterline()`,确保箭头和巡航对 osm2streets polygon 顺序使用同一契约。 ### `scripts/lib/vehicle-route.js` 保留现有 OSM 路线拓扑搜索,替换 `LANE_OFFSET_METERS` / `offsetClosedRouteRight()` 路径: 1. 加载并严格校验 `lane_polygons.geojson` 为 FeatureCollection。 2. 按 `road`、lane `index` 和 `direction=Fwd|Back` 建立 Driving lane 索引;`osm_way_ids` 仅用于追溯 OSM 标签。 3. 对每条 directed edge,使用实际横向位置按行驶方向排列同向车道;renderer `index` 只作为稳定 tie-breaker,不单独决定车道顺序。 4. 将 edge 末端的 maneuver 与 `turn:lanes:forward|backward` 对齐。左转/掉头选最左兼容车道,右转选最右兼容车道,直行选最右兼容车道;无显式 lane restriction 时按相同位置规则选择。 5. 每个 edge 对应一个 osm2streets internal road;禁止把同一 OSM way 下多个 internal road 当作无语义 fragment 直接拼接。 6. 车道中轴端点之间使用 tangent Bezier / U-turn 连接,并绑定共同的 internal intersection;全部采样点必须落在对应 `intersection_surface` 内或边界容差内。 7. 任一 edge 无法可靠匹配时丢弃该候选 route;继续搜索其他候选,最多输出 5 条。 ## 输出契约 保留顶层 `routes`、兼容别名 `segments`、`loop`、`speedMetersPerSecond`,以及每条路线的 `coordinates`、`centerlineCoordinates`、`edgeIds`、`maneuvers` 和 `lengthMeters`。 每条路线新增 `laneSegments`,每段至少记录: - `edgeId`、`osmWayId`、`direction`; - `laneIndex`、`widthMeters`、`centerOffsetMeters`; - `maneuver`、`source="lane_polygon_centerline"`; - 参与拼接的 polygon/road 标识。 顶层新增 `diagnostics`,按稳定 reason code 汇总被拒绝的 edge/route,例如 `missing_lane_polygon`、`invalid_lane_polygon`、`ambiguous_lane_order`、`no_compatible_turn_lane` 和 `disconnected_lane_fragments`。固定 `laneOffsetMeters` 不再作为几何输入;为避免伪造单值,不以平均偏移替代逐段事实。 ## 错误与降级语义 - 整个 lane polygon 文件缺失、JSON 无法解析或不是 FeatureCollection:preview stage 在写产物前失败。 - 单个 polygon 无效:记录诊断,该 polygon 不参与匹配。 - directed edge 缺少唯一可信车道:候选 route 被拒绝,生成器继续选择其他 route。 - 所有候选都被拒绝:生成合法的空 `routes` 和完整诊断;Cesium 场景仍可加载,但不显示巡航车辆。 - 禁止回退到固定 `1.3 m`、固定 `1.5 m` 或默认 lane width。 ## 兼容性 - Blender scene 经纬度投影改为 WGS84 ECEF→ENU,与 Cesium `eastNorthUpToFixedFrame` 的锚点坐标系一致;这是 route 与最终 GLB 道路重合的必要 跨层契约。 - `segments` 继续与 `routes` 引用相同数组。 - Cesium runtime 当前只消费 `coordinates` 等既有字段,无需理解 `laneSegments` 即可运行。 - preview manifest 新增 lane polygon input 后,旧 manifest 会被诊断为缺少记录并要求重建,这是预期迁移行为。 ## 验证策略 - 纯几何测试:四边形、曲线 polygon、反向 geometry、坏 ring。 - 路线 fixture:不同宽度、双向/单向、多车道和转向车道选择。 - 精度断言:路线道路区间采样点到 polygon 中轴距离不超过 `0.10 m`。 - 连续性断言:车道变化和路口连接处没有由数据拼接产生的异常横跳。 - 集成验证:目标区域重跑 preview,检查 route JSON diagnostics、manifest freshness、区域质量门和 Cesium 实际显示。 - 端到端视觉验证:重跑 `blender,cesium,preview`,对最终画面做道路横截面检查;不能用 route 与 lane polygon 的厘米级一致性代替 GLB/Entity 对齐验证。 ## Bug Analysis:GLB 与巡航路线随距离漂移 ### 1. Root Cause Category - **Category**:B - Cross-Layer Contract;D - Test Coverage Gap。 - **Specific Cause**:Blender 使用固定米/度的平面近似,Cesium 使用 WGS84 椭球 ENU; 两层没有共享坐标转换契约。 ### 2. Why Fixes Failed 1. 固定车道偏移:只处理症状,且假定所有车道宽度相同。 2. 从 Driving polygon 重建中轴:解决了车道宽度与 lane 选择,但只证明 GeoJSON 内部正确。 3. 路口切线连接:改善了 connector,却没有解释直线路段整套坐标同向平移。 ### 3. Prevention Mechanisms | Priority | Mechanism | Specific Action | Status | |---|---|---|---| | P0 | Architecture | `Projector` 使用 WGS84 ECEF→ENU,与 Cesium 锚点一致 | DONE | | P0 | Test Coverage | 测试 WGS84 局部经纬度比例与 ENU 方向 | DONE | | P1 | Documentation | 在 Blender、preview 与 cross-layer spec 固化契约 | DONE | | P1 | Integration | 坐标变更后强制重跑 `blender,cesium,preview` 并视觉核对 | DONE | ### 4. Systematic Expansion - **Similar Issues**:交通信号、语义模型、route polyline 等所有叠加在 GLB 上的 Cesium Entity 都依赖同一契约。 - **Design Improvement**:坐标转换只有 `Projector` 一个 Blender 事实源。 - **Process Improvement**:跨运行时几何必须验证最终组合画面,不能停在单层数值测试。 ### 5. Knowledge Capture - [x] 更新 Blender asset generation spec。 - [x] 更新 preview vehicle route spec。 - [x] 更新 cross-layer thinking guide。 - [x] 增加 `ProjectorTest` WGS84 断言。 ## 回滚 代码回滚只涉及 preview 路线生成和共享 JS helper;重跑 preview 即可恢复旧路线产物,不需要重建 Blender/GLB。用户已有区域配置修改保持不动。