# Config:区域配置 > 覆盖 `config/areas/*.json`、`config/examples/template.json`、`config/default.json`。 > 无运行时——这是**管线三层共同消费的契约**,改一个字段会同时影响 Node、Blender、 > 预览页。 --- ## 两层配置 用户只写第一层,第二层是机器生成的中间产物: ``` config/areas/.json ← 你写的 │ scripts/lib/area-config.js: normalizeAreaConfig() │ 补默认值 + 推导输出路径 ▼ /_pipeline/osm2streets-qgis.config.json ← 生成的,不要手改 │ ▼ build-osm2streets-qgis.js / reimport-gpkg.js ``` 派生配置落在 `_pipeline/` 而不是临时目录——**构建失败时它还在**,可以直接拿去复现。 `config/default.json` 和 `config/hanyang-block.json` 是**低层脚本** (`npm run build:qgis`)用的旧格式配置,与 `config/areas/` 不是一回事。 新工作一律用 `config/areas/`。 --- ## 新增一个区域 ```bash cp config/examples/template.json config/areas/my-area.json ``` 改 `id` 和 `input` 就能跑。其余全有默认值。 --- ## 字段全表 ### 顶层 | 字段 | 必填 | 默认 | 说明 | |---|---|---|---| | `id` | ✅ | — | 区域标识。**同时是默认输出目录名和全部产物的文件名 stem** | | `input` | ✅ | — | OSM XML 的**绝对路径**。不存在直接抛错 | | `outputRoot` | | `/outputs` | 输出根目录 | | `qgisApp` | | `/Applications/QGIS.app` | 也可用环境变量 `QGIS_APP` | | `blenderApp` | | `/Applications/Blender.app` | | | `stages` | | 见下 | 各阶段默认开关 | | `qgis` | | 见下 | QGIS/osm2streets 旋钮 | | `turnLaneArrows` | | 见下 | 从 OSM `turn:lanes:*` 生成自定义车道箭头的发布开关 | | `osm2streets` | | 见下 | 透传给 osm2streets 的选项 | | `blender` | | 见下 | Blender 侧选项 | | `compress` | | 见下 | 默认交付压缩阶段的 GLB 压缩选项 | | `budget` | | 见下 | 区域 GLB 性能与体量预算 | | `outputs` | | 从 `id` 推导 | 输出路径覆盖,逃生舱 | **路径一律绝对**。`normalizeAreaConfig` 对每一项都做 `path.resolve`,相对路径会 相对于**进程 cwd** 解析,不是相对于配置文件——所以别用。 ### `stages` | 字段 | 默认 | 说明 | |---|---|---| | `intermediates` | `true` | 旧名 `qgis` 仍被接受 | | `blender` | `true` | | | `cesium` | `true` | | | `compress` | `true` | 压缩 staged GLB,供随后发布使用 | | `package` | `true` | 将通过校验的静态模型原子发布到 `package/` | | `preview` | `true` | 基于已发布 package 写验证预览及 `_preview/` 动态资源 | `reimport` **在这里配也没用**——`normalizeAreaConfig` 把它硬编码为 `false`,只能靠 `--stages` 显式请求。`compress`、`package` 和 `preview` 始终默认开启。 > 恢复动作(reimport)不该被一份配置文件变成默认行为;压缩、发布和验证预览是标准交付链的一部分。 `--stages` 会整体覆盖这里的默认值。 ### `qgis` | 字段 | 默认 | 说明 | |---|---|---| | `arrowScale` | `0.8` | 导出前对 osm2streets 车道箭头多边形的缩放 | | `arrowMergeTriangles` | `true` | 把箭头的三角网合并成一个合法多边形。**保留原箭头形状和转向**,同时消掉共享三角边处的渲染缝隙 | | `arrowOutlineSimplifyMeters` | `0.05` | 去掉合并后箭头外轮廓上的亚分米级折角。默认值刚好去掉两个畸形尾顶点而**不动箭头头部**,剩下的尾边与杆身垂直 | | `intersectionCornerSourceMaxDimensionMeters` | `2.6` | 只保留小尺寸的 `sidewalk corner` 多边形。**大的路口标记多边形不当人行道处理**,因为它们会盖住可行驶的路口 | | `clipPad` | `0.002` | 送进 osm2streets 的裁剪框外扩(度) | | `canvasPad` | `0.001` | QGIS 画布范围外扩(度) | | `previewPad` | `0.0007` | 预览图范围外扩(度) | | `canvasExtent` | `null` | 显式画布范围,覆盖 `canvasPad` | | `previewExtent` | `null` | 显式预览范围,覆盖 `previewPad` | | `layerPrefix` | `"osm2streets"` | QGIS 图层名前缀 | 三个 pad 单位是**度不是米**,且必须 `>= 0`(`build-osm2streets-qgis.js:49-53` 校验)。 `arrowScale` 必须 `> 0`。 > 这四个 arrow/corner 旋钮的默认值都是调出来的,**改之前先看 README 里记的理由**。 > 尤其 `arrowOutlineSimplifyMeters`——调大会开始削箭头头部。 ### `turnLaneArrows` | 字段 | 默认 | 说明 | |---|---|---| | `enabled` | `false` | 仅在样张经用户确认后启用。启用时从 `turn:lanes:forward` / `turn:lanes:backward` 追加经过测试的自定义箭头;未测试素材永不参与映射。 | 该开关经 `normalizeAreaConfig()` 和 `writeDerivedConfig()` 传入 intermediates 阶段。必须用 `??` 保留 `false`;不要将它改为按隐式标签或环境变量自动启用。 ### `osm2streets` 原样透传给 `JsStreetNetwork` 构造函数(`build-osm2streets-qgis.js:77`)。默认: ```json { "debug_each_step": false, "dual_carriageway_experiment": false, "sidepath_zipping_experiment": false, "inferred_sidewalks": true, "osm2lanes": true } ``` ⚠️ **给了就整体替换,不做逐字段合并**(`raw.osm2streets || {...}`)。 只想改一个开关也必须把五个字段全写上,否则其余四个会退到 osm2streets 自己的默认值。 ### `blender` | 字段 | 默认 | 说明 | |---|---|---| | `treeStyle` | `"natural"` | 合法值见 `generate_scene.py` 的 `TREE_STYLES`(`natural`、`procedural`、`shapespark`) | | `officeOverrides` | `""` | 旧名 `office_overrides` 仍被接受 | ### `compress` 完整构建和显式 `--stages compress` 都使用此配置。默认压缩链是 texture resize + WebP transcode,成功后替换**package staging** 中的主 GLB 与 manifest;未压缩源只保留在构建临时目录。 只有随后的 `package` 阶段才会原子发布到 `package/`。 | 字段 | 默认 | 说明 | |---|---|---| | `textureSize` | `768` | 最大纹理宽高,范围 `64..4096` | | `quality` | `82` | WebP 质量,范围 `1..100` | | `effort` | `80` | WebP 编码 effort,范围 `0..100` | | `meshopt` | `false` | 是否追加 `EXT_meshopt_compression`。开启前要单独验证 Cesium 兼容性 | ### `budget` `budget` 是 `diagnose:area`、`check:area` 和 Cesium / compress manifest 共用的 GLB 限制。未配置时采用全局默认;用户字段统一用 MB 或整数,归一化后内部使用 bytes / counts: | 字段 | 默认 | 说明 | |---|---:|---| | `glbSizeMb` | `25` | GLB 文件总大小(MB) | | `nodes` | `1000` | GLB node 数量 | | `images` | `24` | GLB image 数量 | | `triangles` | `250000` | node 实例化后的 render triangles,不是唯一 mesh 的静态 triangles | | `embeddedImageBytesMb` | `20` | GLB 内嵌图片字节(MB) | | `reason` | `""` | 任一值高于默认时必填,记录区域例外原因 | 所有数值必须为正数,`nodes` / `images` / `triangles` 必须为正整数。收紧任何默认值不需要 `reason`;放宽任一默认值而没有非空 `reason` 会在配置归一化时失败。 ### `outputs`(逃生舱) 默认全部从 `id` 推导。发布给下游的静态资产固定在 `//package/`,临时静态资产在 `_pipeline/package-staging/`,预览专用动态资源在 `//_preview/`。需要定制时逐项覆盖: ```json { "outputs": { "areaDir": "/absolute/path/to/custom-area", "blend": "/absolute/path/to/custom.blend", "packageDir": "/absolute/path/to/custom-package", "cesiumPreview": "/absolute/path/to/custom-preview.html" } } ``` 可覆盖的键(`scripts/lib/area-config.js`):`areaDir`、`fileStem`、`geojsonDir`、`gpkg`、 `qgisProject`、`qgisPreview`、`blend`、`render`、`glb`、`metadata`、`cesiumPreview`、 `vehicleRoute`、`vehicleModel`、`pipelineDir`、`stageManifestDir`。 静态发布路径另有 `packageDir`、`packageStagingDir`、`packageManifest`、 `packageStagingManifest`、`packageModelDir`、`packageStagingModelDir` 与 `packagePrimaryGlb`;预览路径另有 `previewDir` 与 `previewDescriptor`。除非在迁移旧调用, 不要覆盖 `glb` / `metadata`:它们是 staging 内部路径,不是下游资产入口。 **优先改 `fileStem` 或 `areaDir`**——它们能一次性影响全部派生路径。逐个覆盖容易漏。 --- ## 加一个配置字段 1. `normalizeAreaConfig`(`scripts/lib/area-config.js`)里加进对应的分组,**用 `??` 不用 `||`** (`false` / `0` 可能是合法值) 2. 只写两级 fallback:`raw.?. ?? 默认值`。 **不要**制造新的顶层平铺别名——那三级写法是历史兼容,不是模式 3. 若要传给低层脚本,加进 `writeDerivedConfig` 的 `derivedConfig` 对象 4. 若是数值,在消费侧加 `Number.isFinite` + 范围校验,**在任何副作用之前** 5. 更新 `config/examples/template.json` 6. 若字段影响区域质量门,确认 `diagnose:area`、`check:area` 和 stage manifest 共用同一 个评估 helper,不能在入口脚本各自比较阈值 7. 更新本文档的字段表 若新字段产出新文件,同时在 `outputs` 里加一行路径推导。 --- ## 已沉淀的区域 - `config/areas/nantaizi-lake-innovation-valley.json`(默认构建目标) - `config/areas/hanyang-block.json` 两者都是 parity 校验的样本区域(`parity.js:26` 的 `DEFAULT_AREAS`)—— **改动它们会影响基线比对**。 --- ## 反模式 | 反模式 | 后果 | |---|---| | 用相对路径 | 相对 cwd 解析,换个目录跑就错 | | 手改 `_pipeline/*.config.json` | 下次构建被覆盖 | | 只写 `osm2streets` 的一个字段 | 其余四个静默退到 osm2streets 默认值 | | 布尔字段用 `\|\|` 兜底 | `false` 被翻转 | | 给新字段造顶层平铺别名 | 扩大历史包袱 | | 逐个覆盖 `outputs` 而不用 `fileStem` | 漏掉某个产物路径 | | 将 `glb` / `metadata` 当作下游入口 | 它们位于 staging;应只读取 `package/manifest.json` | | 在 `stages` 里配 `reimport` | 无效,被硬编码为 false | | 加数值字段不做范围校验 | 错配置在中途才崩,输出已被破坏 | --- ## 相关 - [CLI 与阶段](../pipeline/cli-and-stages.md):配置怎么被读取和派生 - [外部工具调用](../pipeline/external-tools.md):`qgisApp` / `blenderApp` 怎么用 - README「区域配置」节:面向使用者的说明