Files
osmWorkflow/.trellis/spec/pipeline/layer-registry.md

165 lines
7.5 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.
# 图层表:跨语言的单一事实源
> 适用:改动 osm2streets 九个渲染图层的任何一方——新增图层、删图层、调顺序、调
> 颜色、调高度。**动手前必读**,这里的错误不会报错,只会让产物静默错栈。
---
## 一句话
九个图层在 **JS 和 Python 各存一份表**,两份**故意只同步"集合与顺序"、不同步颜色**
一致性靠运行时的 `catalog.check_layers()` 用产物文件对账。
---
## 两份表分别管什么
| | JS 侧 | Python 侧 |
|---|---|---|
| 位置 | `scripts/lib/scene-layers.js:15` `SCENE_LAYERS` | `blender/osmassets/catalog.py:28` `ROAD_LAYERS` |
| 服务于 | 2D 调试链路GeoJSON 拆分、GeoPackage 导入、QGIS 工程符号 | 3D 场景链路Blender 材质与几何高度 |
| 关键字段 | `id``splitKey``zIndex``title``fill`/`outline`sRGB hex | `id``material``color`(线性 RGB`z`(米) |
| 消费点 | `build-osm2streets-qgis.js:91,98,109,1315``reimport-gpkg.js:53,63,77` | `generate_scene.py:759,844` |
`id` 是两侧唯一的连接键,同时也是 GeoJSON 文件名的 stem`layerFile()`
`<id>.geojson`,见 `scene-layers.js:103`)。
## 这份表从前复制了四遍
`scene-layers.js:3-13` 的注释写明了它存在的理由:同一批图层的顺序曾同时躺在
merged-scene 的 z_index 表、场景样式 JSON、生成的 QGIS 工程、以及 README 的手工重建
片段里。加一个图层要同步改四处,漏一处**不报错**,只是下游 Blender/Cesium 里的场景
悄悄错栈。
`catalog.py:3-7` 记录的是 Python 侧的同一个病:九个图层的绘制顺序在 JS、Blender 高度
在一个 `layer_z` dict、颜色在一个 `road_mats` dict——两种语言三份拷贝手工对齐。
**推论**:看到任何地方开始第二次枚举这九个图层,那就是 bug 的温床,改成从这两份表
之一派生。
## 为什么颜色刻意不同步
`catalog.py:11-15` 明确列为"deliberate non-goal"
- `scene-layers.js``fill` 是给 **QGIS 2D 调试地图**用的 sRGB hex
- `catalog.py``color` 是给 **Blender 3D 场景**用的线性 RGB
- 两套值是**分别调出来的**,不存在换算关系
所以 `check_layers()` 只校验图层的**集合与顺序**——那是必须一致的部分——**不碰调色板**。
> 不要"顺手统一"两边的颜色。那不是清理重复,是把两个独立的设计意图合并成一个错的。
## 对账机制
桥梁是产物文件 `osm2streets_scene_style.json`(两侧常量都叫 `SCENE_STYLE_FILE`
`scene-layers.js:101``catalog.py:49`
```
JS 侧 sceneStyle() ──写──▶ osm2streets_scene_style.json ──读──▶ catalog.check_layers()
scene-layers.js:126 (落在 geojson 输出目录) catalog.py:162
```
写入点:`build-osm2streets-qgis.js:100`intermediates 阶段)、
`reimport-gpkg.js:79`reimport 阶段)。
读取点:`generate_scene.py:842`,每次构建场景时执行。
`check_layers()` 报三类问题(`catalog.py:183-194`
1. style 里有、`ROAD_LAYERS` 里没有 → 该图层**到不了 3D 场景**
2. `ROAD_LAYERS` 里有、style 里没有 → **不会有 GeoJSON 产出**给它
3. 集合相同但顺序不同 → 打印两侧的实际顺序
**这是 warn 不是 fail**`catalog.py:168-169` 写明理由):过期或缺失的输出目录不该
阻断一次重建。所以——
> 构建日志里的 `Layer catalog warning:` 不是噪音。它是这套双表设计**唯一**的自动
> 报警,被忽略就等于没有。
## 顺序是承重的
`catalog.py:16-18`
- **材质创建顺序固定了导出 GLB 里的材质索引**
- 图层顺序固定了 mesh 创建顺序
所以 `ROAD_LAYERS``MATERIALS`**list 不是 dict****追加是唯一安全的编辑**。
在中间插入一个图层会平移其后所有材质索引——GLB 结构变了parity 校验会红,
Cesium 侧引用的材质会错位。
JS 侧的 `zIndex` 同样兼作绘制顺序(`scene-layers.js:12`**最小值先画、位于栈底**。
它同时是写进每个 feature 的 `z_index` 属性(`mergeScene()``scene-layers.js:117-119`)。
## 派生函数:只加派生,不要加第二份枚举
`scene-layers.js` 导出的四个派生函数是这份表的全部合法用法:
| 函数 | 位置 | 用途 |
|---|---|---|
| `layerFile(layer)` | `:103` | `<id>.geojson` 文件名 |
| `mergeScene(getCollection)` | `:109` | 合成 `osm2streets_scene.geojson`,逐 feature 打上 `render_layer` / `z_index` |
| `sceneStyle()` | `:126` | 生成对账用的 style JSON |
| `qgisRgba(hex, alpha)` | `:143` | hex → QGIS 要的 `"r,g,b,a"` 字符串 |
`mergeScene` 收的是**回调**而不是数组,这样 build 阶段(从内存的 split 取)和
reimport 阶段(从磁盘读回)能共用同一套合并逻辑(`scene-layers.js:107-108`)。
新增第三种数据来源时沿用这个模式,不要复制合并循环。
`outline: null` 表示无描边QGIS 侧由 `qgisRgba` 转成全透明(`scene-layers.js:13-14,145`)。
Python 侧同理:`road_material_specs()``catalog.py:156`)把 `ROAD_LAYERS` 转成
`MATERIALS` 形状的规格,`generate_scene.py:759``zip` 与图层配对——保持这条派生链,
不要在 `generate_scene.py` 里另起一份材质名列表。
---
## 改动清单
### 新增一个图层
1. `scene-layers.js:SCENE_LAYERS` **末尾追加**`id``splitKey``zIndex`(大于现有
最大值)、`title``fill``outline``outlineWidth`
2. 确认 osm2streets 的拆分结果里确实有 `splitKey` 对应的键
`build-osm2streets-qgis.js:92``split[layer.splitKey]`
3. `catalog.py:ROAD_LAYERS` **末尾追加**`id`(与第 1 步一致)、`material`(新名字)、
`color`(线性 RGB独立调`z`(米,高于前一层避免 z-fighting
4. 跑一次 `intermediates` + `blender`,确认日志里**没有** `Layer catalog warning:`
5. 该图层的 GeoPackage 导入、QGIS 符号、场景合并、reimport 全部自动跟上,**无需**再
`reimport-gpkg.js` 或 QGIS 工程生成代码
### 删除一个图层
两侧同时删。只删一侧的话 `check_layers()` 会 warn但构建**照常出产物**——一份少了
该图层的产物。
### 调整顺序
`zIndex` 的同时必须把 `ROAD_LAYERS` 的**元素位置**也调成一致。注意这会移动材质
索引,属于会改变产物的变更,**必须跑 parity 校验**,见
[产物一致性指南](../guides/artifact-parity-guide.md)。
### 只调颜色
改一侧即可,不要同步到另一侧(见上文"为什么颜色刻意不同步")。
---
## 反模式
| 反模式 | 后果 |
|---|---|
| 在 `generate_scene.py` / QGIS 生成代码里硬编码图层名列表 | 回到"复制四份"的旧病 |
| 从 `scene-layers.js``fill` 换算 Blender 的 `color` | 抹掉两套独立调过的配色 |
| 在 `ROAD_LAYERS` / `MATERIALS` **中间**插入条目 | GLB 材质索引整体平移 |
| 把 `ROAD_LAYERS` / `MATERIALS` 改成 dict | 顺序语义丢失,见 `catalog.py:16-18` |
| 把 `check_layers()` 从 warn 改成 raise | 输出目录过期就无法重建 |
| 忽略 `Layer catalog warning:` | 双表设计唯一的报警失效 |
---
## 相关
- [外部工具调用](./external-tools.md):图层如何进出 GeoPackage
- [CLI 与阶段](./cli-and-stages.md):哪个阶段写、哪个阶段读这些文件
- [Blender 资产生成](../blender/asset-generation.md)`MATERIALS` 的其余部分
- [产物一致性指南](../guides/artifact-parity-guide.md):改动顺序后如何验证