Kazerin 2f07a3a8dc feat(cockpit): 地形/影像接入、视角预设、生产形态与浮层布局(T21/T29/T30/T32/T33/T34) 1 mese fa
..
README.md 2f07a3a8dc feat(cockpit): 地形/影像接入、视角预设、生产形态与浮层布局(T21/T29/T30/T32/T33/T34) 1 mese fa
build-town.mjs 2f07a3a8dc feat(cockpit): 地形/影像接入、视角预设、生产形态与浮层布局(T21/T29/T30/T32/T33/T34) 1 mese fa
verify-town.mjs 2f07a3a8dc feat(cockpit): 地形/影像接入、视角预设、生产形态与浮层布局(T21/T29/T30/T32/T33/T34) 1 mese fa

README.md

沅陵县城「轻量体块」模型

⚠️ 这是示意体块,不是实测建筑。 除 OSM 的少量真实轮廓外,其余体块是按真实路网 / 建成区 / 水系程序化排布的可复用楼房单元,用途是让一张图的远景看起来像一座县城。 不得用于任何量测、统计或应急决策 —— 产物里的 meta.json 也写了同一条免责声明。

为什么存在这套工具

甲方给的 D:\GIS\GIS\yuanlingSHP(cesiumlab model2tiles 导出)经维护者目测判定 「明显错位 + 只是白色立方体,效果非常差」,不采用。维护者 2026-09-18 定的替代方向: 参照 GIS 数据做轻量建模,远景基本达标、不要求近景细节、楼房模型可复用。

地理配准由构造保证

原料是经纬度,生成时投影到以目标点(沅陵县城 110.39028164, 28.4436787)为原点的 ENU 米制坐标,再写成 3D Tiles 根的 transform —— 不存在"猜模型原点"这件事 (上一版的错位正是因为原始导出缺根 tileset.json、分块是局部坐标)。

原料(本机)

输入 用途
planet_...-shp/shpOutput/buildings.json OSM 真实轮廓(城区内 169 个,直接按真实形状起楼)
planet_...-shp/shpOutput/roads.json OSM 路网 —— 体块沿街排布(贴街是我国县城的常态)
planet_...-shp/shpOutput/waterways.json 水系(沅江)—— 体块避让 ≥22–26 m
output/resa.json 1:5 万居民地面(建成区范围)—— 区内抖动网格补白
cityMassing/terrain-grid.json 本地 DEM 采样网格 —— 体块坐到地形上(否则基准面在椭球 0 m,整片楼被埋进山里)

可复用楼房单元

三种单元反复使用,只有位置/朝向/层数/配色不同("楼房模型可复用"的落点):

单元 体量 层数 屋顶 出现位置
house 9 × 7.2 m 1–2 层 坡屋顶 城区外围
block 14 × 10 m 3–5 层 平顶 一般街区
slab 26 × 11 m 6–8 层 平顶 城区核心(≤400 m)

配色共 13 种(墙 8 + 屋顶 5),按位置哈希稳定分配 —— 同一输入每次生成结果一致,不会刷一次变一样。

用法

# 1) 先在本地 DEM 上采一张高程网格(需要 dev server 在跑:yarn dev)
node <一次性脚本> sample-terrain-grid.mjs        # 写到 <DATA_DIR>/terrain-grid.json

# 2) 生成
node tools/city-massing/build-town.mjs            # 产物写到 D:\GIS\GIS\cityMassing

# 3) 回验(地理配准 / tileset 自洽 / GLB 结构 / 免责声明)
node tools/city-massing/verify-town.mjs

生成后把它配到一张图上(map.tilesets):

"map": { "tilesets": [{ "url": "/gis/city/tileset.json" }] }

dev 环境由 .env.local 的 COCKPIT_GIS_MOUNTS 把 D:\GIS\GIS\cityMassing 挂到 /gis/city; 生产环境按 docs/cockpit-deployment.md 第 3 节的 nginx 片段挂同一目录。

踩过的坑(别再踩)

  • tileset 级 geometricError 必须 > 0:写成 0 时 Cesium 不请求根瓦片内容 —— tileset.json 拉到了、town.glb 始终不下载,页面上一栋楼都没有(已用诊断读数定位并修掉)。
  • glTF 是 Y-up,3D Tiles 的局部系是 Z-up:顶点要写 (east, up, -north), Cesium 装载时按 (x, -z, y) 转回来。写反了模型会躺倒/镜像 —— verify-town.mjs 里那条 "真实轮廓外接盒角点 2 m 内命中"就是专门证伪这条链的。

已知取舍

  • 不是实测:只有 74 个真实轮廓(城区内可用部分),其余是程序化体块。
  • 高度是估的:OSM 无 height/building:levels,层数按"离中心距离 + 位置哈希"给。
  • 地形做了简化:高程来自 17×17 采样网格的双线性插值,局部起伏会有几米误差。
  • 覆盖窗口:目标点 ±0.020 经 / ±0.015 纬(约 1.9 km × 1.7 km),超出窗口不生成。