docs: Archive osmassets refactor plan
This commit is contained in:
@@ -85,7 +85,7 @@ def assemble(ring, [way_id,] scene_xmin, scene_xmax, scene_ymin, scene_ymax,
|
|||||||
|
|
||||||
### 加一种新 OSM 要素
|
### 加一种新 OSM 要素
|
||||||
|
|
||||||
目标形态(`docs/refactor-plan.md`):**新增一个模块 + 注册一行,不改 `build()`**。
|
目标形态:**新增一个模块 + 注册一行,不改 `build()`**。
|
||||||
|
|
||||||
1. 新建 `osmassets/<feature>.py`,写 `assemble(...)`,签名照抄上面
|
1. 新建 `osmassets/<feature>.py`,写 `assemble(...)`,签名照抄上面
|
||||||
2. 只 import 需要的:`from osmassets.geom import clip_polygon`、
|
2. 只 import 需要的:`from osmassets.geom import clip_polygon`、
|
||||||
@@ -176,7 +176,7 @@ export_cesium.py # 优先读 material custom property
|
|||||||
否则新生成的 `.blend` 不会自带契约
|
否则新生成的 `.blend` 不会自带契约
|
||||||
- `catalog.py` 仍属纯 Python 层,不能 import `bpy`;序列化发生在 `materials.py`
|
- `catalog.py` 仍属纯 Python 层,不能 import `bpy`;序列化发生在 `materials.py`
|
||||||
- `"Office White Metal Facade"` 在四张表里都有,但 `catalog` 里**已无此材质**
|
- `"Office White Metal Facade"` 在四张表里都有,但 `catalog` 里**已无此材质**
|
||||||
(`docs/refactor-plan.md` 记为缺陷 D1)。它只能作为旧 `.blend` 回退兼容存在,
|
(历史上记为缺陷 D1)。它只能作为旧 `.blend` 回退兼容存在,
|
||||||
不要迁回新契约源
|
不要迁回新契约源
|
||||||
|
|
||||||
**改材质名时**:`catalog.MATERIALS` + `catalog.ROAD_LAYERS` + 四张旧回退表全部
|
**改材质名时**:`catalog.MATERIALS` + `catalog.ROAD_LAYERS` + 四张旧回退表全部
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ node scripts/parity.js compare control-1 control-2 # 必须全绿
|
|||||||
|
|
||||||
没做这步就开始改代码,你会分不清一个差异是"重构引入的 bug"还是"本来就每次都不一样"。
|
没做这步就开始改代码,你会分不清一个差异是"重构引入的 bug"还是"本来就每次都不一样"。
|
||||||
|
|
||||||
已完成的 control 结论(`docs/refactor-plan.md`):
|
已完成的 control 结论:
|
||||||
|
|
||||||
- `.blend` **结构摘要两次完全一致** ← 这是主校验信号,可信
|
- `.blend` **结构摘要两次完全一致** ← 这是主校验信号,可信
|
||||||
- `.blend` 文件 sha256 不一致
|
- `.blend` 文件 sha256 不一致
|
||||||
@@ -147,7 +147,7 @@ capturedAt / durationMs / label
|
|||||||
|
|
||||||
## 风险高的改动要分次提交
|
## 风险高的改动要分次提交
|
||||||
|
|
||||||
`docs/refactor-plan.md` 对风险最高的一期写着:
|
要素注册表这类高风险重构必须按要素分次提交:
|
||||||
|
|
||||||
> 逐要素分次提交,每次单独跑 parity。
|
> 逐要素分次提交,每次单独跑 parity。
|
||||||
|
|
||||||
@@ -155,9 +155,9 @@ capturedAt / durationMs / label
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 当前重构进度(`docs/refactor-plan.md`)
|
## 当前重构进度
|
||||||
|
|
||||||
那份计划是**临时工作文档**,P3 收尾后会并入 changelog 并删除。当前状态:
|
临时施工计划已删除;长期状态以本指南和 `docs/changelog.md` 为准:
|
||||||
|
|
||||||
| 期 | 内容 | 状态 |
|
| 期 | 内容 | 状态 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|
|||||||
2
.trellis/tasks/08-03-archive-refactor-plan/check.jsonl
Normal file
2
.trellis/tasks/08-03-archive-refactor-plan/check.jsonl
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
{"file": ".trellis/spec/guides/artifact-parity-guide.md", "reason": "Check that parity/control knowledge survives after deleting the temporary refactor plan."}
|
||||||
|
{"file": ".trellis/spec/guides/index.md", "reason": "Check guide references remain accurate and no stale refactor-plan links remain."}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
{"file": ".trellis/spec/guides/artifact-parity-guide.md", "reason": "Contains refactor-plan status and references that must be preserved without linking to the deleted temporary file."}
|
||||||
|
{"file": ".trellis/spec/guides/index.md", "reason": "Shared guide routing for cross-layer and parity documentation changes."}
|
||||||
35
.trellis/tasks/08-03-archive-refactor-plan/prd.md
Normal file
35
.trellis/tasks/08-03-archive-refactor-plan/prd.md
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# Archive refactor plan
|
||||||
|
|
||||||
|
**类型**:docs · **范围**:docs/spec · **创建**:2026-08-03
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
收尾临时文档 `docs/refactor-plan.md`:把仍有价值的 P0-P3 重构结论并入长期文档,
|
||||||
|
然后删除这份已过期的临时计划,避免后续 AI 或开发者读到 P3 未做、旧行号、旧 `CESIUM_EXPORT`
|
||||||
|
状态等过期事实。
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
1. `docs/changelog.md` 必须新增一条 2026-08-03 记录,总结材质导出契约化、Trellis
|
||||||
|
spec 初始化,以及 `docs/refactor-plan.md` 的收尾处理。
|
||||||
|
2. 删除 `docs/refactor-plan.md`,因为它开头已声明 P3 收尾后应并入 changelog 并删除。
|
||||||
|
3. 更新 `.trellis/spec/guides/artifact-parity-guide.md` 中对 `docs/refactor-plan.md` 的
|
||||||
|
直接依赖,保留 parity/control 结论和 P0-P3 当前状态,但不引用已删除文件。
|
||||||
|
4. 不改业务代码,不改 Blender/Cesium 产物,不修 D1-D3。
|
||||||
|
5. 删除后不得留下指向 `docs/refactor-plan.md` 的断链引用。
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
|
||||||
|
- [ ] `docs/refactor-plan.md` 不存在。
|
||||||
|
- [ ] `docs/changelog.md` 顶部有 2026-08-03 条目,记录 P3 完成和临时计划归档。
|
||||||
|
- [ ] `rg "docs/refactor-plan.md|refactor-plan" docs .trellis/spec README.md` 不再发现活文档引用。
|
||||||
|
- [ ] `git diff --check` 通过。
|
||||||
|
- [ ] 工作范围只包含 docs、`.trellis/spec` 和当前 Trellis task 文件。
|
||||||
|
|
||||||
|
## Out of Scope
|
||||||
|
|
||||||
|
- P2 要素注册表补完。
|
||||||
|
- D1/D2/D3 修复。
|
||||||
|
- 任何 `blender/`、`scripts/`、`config/` 业务代码改动。
|
||||||
30
.trellis/tasks/08-03-archive-refactor-plan/task.json
Normal file
30
.trellis/tasks/08-03-archive-refactor-plan/task.json
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"id": "archive-refactor-plan",
|
||||||
|
"name": "archive-refactor-plan",
|
||||||
|
"title": "Archive refactor plan",
|
||||||
|
"description": "Move completed osmassets refactor-plan conclusions into changelog and remove the stale temporary plan.",
|
||||||
|
"status": "in_progress",
|
||||||
|
"dev_type": "docs",
|
||||||
|
"scope": "docs/spec",
|
||||||
|
"package": null,
|
||||||
|
"priority": "P2",
|
||||||
|
"creator": "dingkang",
|
||||||
|
"assignee": "dingkang",
|
||||||
|
"createdAt": "2026-08-03",
|
||||||
|
"completedAt": null,
|
||||||
|
"branch": null,
|
||||||
|
"base_branch": "main",
|
||||||
|
"worktree_path": null,
|
||||||
|
"commit": null,
|
||||||
|
"pr_url": null,
|
||||||
|
"subtasks": [],
|
||||||
|
"children": [],
|
||||||
|
"parent": null,
|
||||||
|
"relatedFiles": [
|
||||||
|
"docs/changelog.md",
|
||||||
|
"docs/refactor-plan.md",
|
||||||
|
".trellis/spec/guides/artifact-parity-guide.md"
|
||||||
|
],
|
||||||
|
"notes": "Lightweight docs cleanup. Remove stale temporary refactor plan after merging durable conclusions into changelog/spec.",
|
||||||
|
"meta": {}
|
||||||
|
}
|
||||||
@@ -1,5 +1,20 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2026-08-03
|
||||||
|
|
||||||
|
- 初始化 Trellis 项目规范,把 `trellis init` 误生成的 frontend spec 替换为本项目真实的
|
||||||
|
`pipeline` / `blender` / `preview` / `config` 四层规范,并把跨层 parity、图层顺序、
|
||||||
|
外部工具 staging、纯 Python / bpy 边界等反直觉约定固化到 `.trellis/spec/`。
|
||||||
|
- 完成 Cesium 材质导出契约化:`catalog.MATERIALS[*]["cesium"]` 现在由
|
||||||
|
`materials.from_spec()` 写入 `.blend` 材质自定义属性 `material["cesium_export"]`,
|
||||||
|
`export_cesium.py` 优先读取该属性;旧四张材质名表仅保留为旧 `.blend` 回退路径。
|
||||||
|
parity before/after 只有 `.blend` 新增 `props.cesium_export` 与 `.blend` bytes 变化,
|
||||||
|
无 GLB/material/metadata 结构漂移。
|
||||||
|
- 收尾临时 `osmassets` 重构施工计划:P0/P1/P3 的长期知识已经进入 changelog 和 Trellis spec;
|
||||||
|
P2 仍是后续重构方向(`building` / `fountain` / `roads` 仍在 `generate_scene.py` 里,
|
||||||
|
尚未形成完整 `features/` 注册表)。删除临时计划文件,避免继续传播旧行号和
|
||||||
|
`catalog.CESIUM_EXPORT` 死代码等过期事实。
|
||||||
|
|
||||||
## 2026-07-31(三)远看发黑的真正原因:反照率没被提亮
|
## 2026-07-31(三)远看发黑的真正原因:反照率没被提亮
|
||||||
|
|
||||||
(二)里加的 emissive 提到 0.8 仍然发黑。原因是 emissive 乘的是本来就很暗的
|
(二)里加的 emissive 提到 0.8 仍然发黑。原因是 emissive 乘的是本来就很暗的
|
||||||
|
|||||||
@@ -1,112 +0,0 @@
|
|||||||
# 重构施工计划:`osmassets` 包化(P0–P3)
|
|
||||||
|
|
||||||
> 临时工作文档。P3 收尾后把结论并入 `docs/changelog.md`,本文件删除。
|
|
||||||
|
|
||||||
## 目标
|
|
||||||
|
|
||||||
把「从 OSM 生成 Blender / Cesium 资产」的逻辑从两个单体脚本里拆成可复用的库,使得:
|
|
||||||
|
|
||||||
- 新增一种 OSM 要素 = 新增一个 `features/*.py` + 注册一行,不改 `build()`
|
|
||||||
- 道路图层表、材质规格只有一份定义,JS 侧与 Python 侧不再各存一份
|
|
||||||
- `export_cesium.py` 不再靠材质名字符串跟 `generate_scene.py` 对接
|
|
||||||
- 纯几何 / 解析逻辑脱离 `bpy`,可用系统 python 直接测
|
|
||||||
|
|
||||||
## 硬约束:严格产物一致
|
|
||||||
|
|
||||||
P0–P3 全程 **不改变任何输出**。每期结束必须通过 parity 校验,任何差异都要么消除、要么在本文件里逐条记录原因。
|
|
||||||
|
|
||||||
已知缺陷(本轮**只记录、不修**):
|
|
||||||
|
|
||||||
| # | 位置 | 现象 |
|
|
||||||
|---|---|---|
|
|
||||||
| D1 | `export_cesium.py:26,34,40,52` | `"Office White Metal Facade"` 四张表里都有,`generate_scene.py` 里已无此材质——死条目 |
|
|
||||||
| D2 | `scene-layers.js:15` vs `generate_scene.py:1017` | 同一批图层的颜色两侧各自手调,无一致性保证 |
|
|
||||||
| D3 | `generate_scene.py:788` | `tuft_density_wave` 注释仍在跟已删除的 hedge banding 作对比 |
|
|
||||||
|
|
||||||
## Parity 工具与基线
|
|
||||||
|
|
||||||
`outputs/` 已在 `.gitignore` 中,基线快照放 `outputs/_refactor-baseline/`,不入库。
|
|
||||||
|
|
||||||
| 工具 | 位置 | 作用 |
|
|
||||||
|---|---|---|
|
|
||||||
| 场景摘要 | `blender/tools/scene_digest.py` | 在 Blender 内打开 `.blend`,输出稳定 JSON:对象名/顶点数/面数/材质槽/自定义属性、材质参数、场景属性 |
|
|
||||||
| GLB 摘要 | `scripts/glb-digest.js` | 纯 Node 读 GLB 的 JSON chunk,输出 node/mesh/material 清单与 PBR 参数,附 buffer 字节长度 |
|
|
||||||
| 驱动 | `scripts/parity.sh <label>` | 跑 blender+cesium 阶段 → 收集 `SCENE_DONE` / `CESIUM_EXPORT_DONE` / 两份摘要 / 渲染 PNG 到 `outputs/_refactor-baseline/<label>/` |
|
|
||||||
|
|
||||||
**先做对照实验(control)**:用未改动的代码连跑两次,diff 两份摘要。这一步确定哪些字段天然不确定,把这些字段列入忽略名单。没做这步的 parity 校验是假的。
|
|
||||||
|
|
||||||
已完成,结论如下(`control-1` vs `control-2`,两区域):
|
|
||||||
|
|
||||||
- `.blend` **结构摘要两次完全一致** —— 这是主校验信号,可信
|
|
||||||
- `.blend` 文件 sha256 不一致:内嵌绝对路径 + 图片打包顺序随哈希表走
|
|
||||||
- 渲染 PNG sha256 不一致:EEVEE 非位级可复现
|
|
||||||
- GLB 结构(node / mesh / primitive / material / image)两次完全一致,但 accessor 数 399 vs 398、buffer 差 720 字节:glTF 导出器会去重相同 accessor,而 `smart_project` 的 UV 带浮点噪声,一次能去重一次不能
|
|
||||||
|
|
||||||
忽略名单(写在 `scripts/parity.js:IGNORED_PATHS`,附原因):`files.{blend,glb,render}.sha256`、`files.{glb,render}.bytes`、`glbDigest.{fileBytes,buffers,counts.accessors}`。
|
|
||||||
|
|
||||||
保留比对的即真正的契约:`SCENE_DONE` / `CESIUM_EXPORT_DONE` 标记、`.blend` 全量结构摘要、GLB 的 node/mesh/material/image 结构、`<area>.json` 元数据。加上 `control-1`、`control-2` 两份基线已落盘。
|
|
||||||
|
|
||||||
样本区域:
|
|
||||||
|
|
||||||
- `nantaizi-lake-innovation-valley` — 主样本,OSM + osm2streets GeoJSON 齐全
|
|
||||||
- `hanyang-block` — 次样本,只有 `intermediates` 产物,需先补跑一次 blender 阶段生成基线
|
|
||||||
|
|
||||||
## 分期
|
|
||||||
|
|
||||||
### P0 — 抽纯函数(行为零变化)
|
|
||||||
|
|
||||||
新建 `blender/osmassets/`,只搬运、不改逻辑:
|
|
||||||
|
|
||||||
| 目标文件 | 从 `generate_scene.py` 搬入 | 依赖 |
|
|
||||||
|---|---|---|
|
|
||||||
| `osm.py` | `tags` (94)、`parse_osm` (99)、`Projector` (140)、`parse_height` (506) | 无 bpy |
|
|
||||||
| `geom.py` | `geometry_rings` (406)、`feature_in_bounds` (418)、`clip_polygon` (426)、`sample_tree_row` (513)、`polygon_area` (688)、`point_in_polygon` (697)、`distance_to_ring` (712) | 无 bpy |
|
|
||||||
|
|
||||||
- `generate_scene.py` 顶部加 `sys.path` 引导(`--factory-startup` 下 `blender/` 不在 `sys.path`),改为 `from osmassets import ...`
|
|
||||||
- 新增 `blender/tests/test_geom.py`、`test_osm.py`,`unittest` 标准库,系统 `python3` 直接跑(本机 3.9,避免 3.10+ 语法)
|
|
||||||
- 验收:`python3 -m unittest discover blender/tests` 通过 + parity 全绿
|
|
||||||
|
|
||||||
### P1 — 单一定义源
|
|
||||||
|
|
||||||
新建 `blender/osmassets/catalog.py`:
|
|
||||||
|
|
||||||
- `ROAD_LAYERS`:`id` / `blender_z` / `material_name` / `color`,替换 `generate_scene.py:1017` 的 `road_mats` 与 `1122` 的 `layer_z` 两份副本
|
|
||||||
- `MATERIAL_SPECS`:目前散在 `build()` 里的全部 `make_material` / `make_textured_material` 调用参数
|
|
||||||
- 新增一致性检查:读输出目录里已存在的 `osm2streets_scene_style.json`,比对图层 id 集合与顺序,不一致则打 warning(**不**改颜色,改了就破坏 parity → 见 D2)
|
|
||||||
|
|
||||||
验收:parity 全绿;手动删一个图层 id 验证 warning 生效。
|
|
||||||
|
|
||||||
### P2 — 要素注册表
|
|
||||||
|
|
||||||
新建 `blender/osmassets/features/`,每种要素一个模块,导出 `SPEC`:
|
|
||||||
|
|
||||||
```
|
|
||||||
water.py natural=water / water=lake
|
|
||||||
grass.py landuse=grass(含 tuft 散布)
|
|
||||||
scrub.py natural=scrub
|
|
||||||
tree.py natural=tree 节点 + natural=tree_row + 两种树风格
|
|
||||||
building.py building=*(含 roof / windows)
|
|
||||||
fountain.py amenity=fountain
|
|
||||||
roads.py osm2streets GeoJSON 图层 + highway 折线回退
|
|
||||||
```
|
|
||||||
|
|
||||||
- `scene.py::assemble()` 遍历注册表;`build()` 收缩为「解析 → assemble → 灯光相机 → 存盘渲染」
|
|
||||||
- 计数器改由注册表汇总,但 `SCENE_DONE` 与 `scene[...]` 的键名、顺序保持逐字不变
|
|
||||||
- if/elif 的**匹配顺序**是语义的一部分(`building` 分支在最后),注册表必须保序
|
|
||||||
|
|
||||||
验收:parity 全绿 —— 这期风险最高,逐要素分次提交,每次单独跑 parity。
|
|
||||||
|
|
||||||
### P3 — 材质契约化
|
|
||||||
|
|
||||||
- `catalog.py` 的材质规格扩展出 cesium 段:`tint` / `metallic` / `base_color` / `emission`
|
|
||||||
- `generate_scene.py` 把规格写进材质自定义属性 `material["cesium_export"] = json.dumps(spec)`
|
|
||||||
- `export_cesium.py` 优先读自定义属性;读不到时回落到现有四张名字表(**原样保留,含 D1 死条目**),保证旧 `.blend` 仍能导出且 parity 成立
|
|
||||||
- `Tree Crown` 的程序化贴图特例保持不变
|
|
||||||
|
|
||||||
验收:parity 全绿;另外用重构前生成的旧 `.blend` 跑一次导出,确认回落路径可用。
|
|
||||||
|
|
||||||
## 不在本轮范围
|
|
||||||
|
|
||||||
- 输出目标可插拔(整场景 / 每要素单独 GLB)——原 P4
|
|
||||||
- `build-area.js` 里 390 行内联 HTML 与手写 glTF 的拆分——原 P4
|
|
||||||
- 上表 D1–D3 的修复
|
|
||||||
Reference in New Issue
Block a user