What to build: 接入本地或甲方提供的 3D Tiles、地形和倾斜摄影资源,实现地面视图与管线视图切换。首期不依赖 Cesium Ion。
Blocked by: 03, 04
Status: resolved Labels: ready-for-agent
认领:2026-09-17 会话接手。维护者已给出本机 GIS 数据位置(
D:\GIS\GIS\yuanlingDEM量化网格地形 +D:\GIS\GIS\yuanlingPic3影像切片),本轮先做「地形 + 本地影像 + 免费全局底图」;地面/管线视图切换与 3D Tiles/倾斜摄影(数据未提供)留在本票后续。
map.basemap.source 支持 none / natural-earth(Cesium 自带离线影像)/ tianditu(填 map.tianditu.token,开发走 /tianditu.map 代理)/ xyz(任意 {z}/{x}/{y} 模板)。甲方本地瓦片若已是 XYZ/WMTS 切片,先按 xyz 配即可;本票专注地形、3D Tiles、倾斜摄影与地面-管线视图切换,不要重做底图影像层。天地图的真实取图也还没用真 tk 联调过,可在本票顺手验收。禁止项沿用决策地图调研:不使用 Ion token、Terrain.fromWorldTerrain、createOsmBuildings。
[x] 支持本地或甲方资源地址配置。
[x] 地形、3D Tiles 和倾斜摄影资源可加载。—— 地形:本机 DEM 实测取到 14 级瓦片、零 404(2026-09-17);2026-10-14 在 8000 运行态复测 gis/dem/*.terrain 与 gis/pic3/*.png 仍全 200。3D Tiles:入口链路早已用夹具验证;2026-10-14 在真实驾驶舱(http://127.0.0.1:8000/#/cockpit)实测已接入的 CAD BIM tileset 真实加载成功 —— public/cockpit/config.json 的 map.tilesets[0] 指向 /gis/cad-bim/city-regions-v7/coarse-tileset.json,其 113 个 region 的 city-regions-v6/coarse-*-0.glb 连续请求全部 HTTP 200、无失败请求,画面渲染出建筑体块(截图见本轮核验)。倾斜摄影:甲方从未提供该格式数据;原 D:\GIS\GIS\yuanlingSHP(cesiumlab model2tiles 导出,缺根 tileset.json、分块 boundingVolume 为局部坐标且无 transform)经维护者目测判定「明显错位 + 纯白立方体」已否决、不再采用,该验收口径由票 34 → 票 35 的轻量体块 / CAD BIM 替代方案承担,本条按「替代模型可加载」判定通过。
[x] 资源加载中、成功、失败和空状态可区分。—— 引擎 booting/ready/failed/disabled;地形 ready/invalid;3D Tiles ready/invalid(data-map-tilesets + stats.tilesetErrors)。
说明:「空状态」在本引擎里没有稳定信号——Cesium 按视锥懒加载,资源挂上了但当前视野无瓦片是正常态(此时 numberOfTilesWithContentReady 也为 0),据此报「空」会把好数据误判成空。故只保证三态如实,未伪造第四态。维护者 2026-10-14 裁定:「空状态」是正常态,不需要在 UI 上单独区分。 本条按裁定通过,不再作为未决项。
[x] 地面视图与管线视图可切换:管线视图压低相机并把地形与 3D Tiles 压成半透明,地面视图还原。
[x] 切换视图不重置旋转中心,也不改变左键/右键/滚轮三键分工。
[x] 不使用硬编码 Cesium Ion token。
[x] 有资源加载状态单测或走查记录。
地形感知的相机已由票 30 做掉(原先记在本票「下一步」第 3 条):
pickGroundAtCenter()改为按地形 拾取,并在地形就绪后采样「家」视角的实测高程 —— 拉到距离下限 120 m 时中心高程 111.6 m,近景不再黑屏。
2026-10-14 复检结论:按维护者指定入口 http://127.0.0.1:8000/#/cockpit 在真实驾驶舱复核本票全部验收项,全部通过;维护者当场裁定「空状态是正常的」,本票最后一个未决项随之关闭。
/gis/dem/*.terrain 连续 HTTP 200(含 3–12 级)。/gis/pic3/{z}/{x}/{y}.png 连续 HTTP 200。/gis/cad-bim/city-regions-v6/coarse-*-0.glb 被 Cesium 连续请求并全部 200(实测覆盖 coarse-0/2/3/4/8/9/15/17/18/24/28/30/34/39/43/44/46/48/51/55/57/58/59/60/61/69/70/71/73/77/78/80/89/100/101/105/107 等 40+ 个分块),失败请求过滤为空;画面实际渲染出建筑体块。domain/viewModes.js 计划一致。t21-terrain.mjs 通过(地形/叠加归一化 + 计划层 + 配置与 layer.json/meta.json 磁盘对齐);t21-view-modes.mjs 通过(含「切换不产中心字段」的构造性断言)。hm.baidu.com 第三方策略提示)。票面此前记「甲方模型数据仍不可加载 ← 本票唯一的硬阻塞」。该结论针对的是已被否决的 yuanlingSHP 白模;替代方案(票 34 → 票 35 的 CAD/BIM 体块)已于本轮证实可在真实驾驶舱加载,public/cockpit/config.json 的 map.tilesets[0] 现指向 /gis/cad-bim/city-regions-v7/coarse-tileset.json(113 region,内容复用 city-regions-v6)。故「3D Tiles 可加载」不再是阻塞项。
「空状态」是否要在 UI 上单独区分:引擎里没有稳定信号(Cesium 按视锥懒加载,资源挂上但当前视野无瓦片是正常态,此时 numberOfTilesWithContentReady 也为 0),据此报「空」会把好数据误判成空。维护者 2026-10-14 裁定:这是正常态,不需要区分 —— 引擎保持「加载中 / 成功 / 失败」三态如实即可。本项关闭。
本票交付「本地地形 + 本地影像 + 3D Tiles + 地面/管线视图切换」全部验收通过,已关闭。
map.terrain / map.overlays[] 配置化接入本机 cesiumlab 数据;2026-10-14 在 8000 运行态复测 /gis/dem/*.terrain 与 /gis/pic3/*.png 连续 HTTP 200、零 404。map.tilesets[] 逐项挂 Cesium3DTileset,单项失败不影响其它项,tileFailed 捕获内容阶段错误。2026-10-14 在真实驾驶舱实测已接入的 /gis/cad-bim/city-regions-v7/coarse-tileset.json(113 region,内容复用 city-regions-v6)真实加载成功:coarse-*-0.glb 40+ 分块全部 200、失败请求为空、画面渲染出建筑体块。yuanlingSHP 白模经维护者目测否决,替代方案(票 34 → 票 35 的 CAD/BIM 体块)承担该验收口径。viewHprFor() 签名里没有中心参数,从构造上保证不重置中心;三键分工不变。运行态实测切换生效。ready/invalid、3D Tiles ready/invalid 如实呈现;「空状态」按维护者裁定属正常态,不单独区分、不伪造第四态。Terrain.fromWorldTerrain / createOsmBuildings。verify/t21-terrain.mjs、verify/t21-view-modes.mjs 通过;verify/t21-gis-walkthrough.mjs 9/9、verify/t21-view-modes-walkthrough.mjs 10/10(2026-09-17 轮次);2026-10-14 8000 运行态复检(网络请求全 200 + 截图)。遗留(不属本票):CAD BIM 自身的视觉与性能签收归票 35(city-regions-v7/manifest.json 的 runtimeValidated: false)。
本轮(2026-09-17)做完「本地地形 + 本地影像 + 免费全局底图」这条主线,维护者要的「基础 GIS 地球地图」已经能看到沅陵县城真数据。
src/common/localGisStaticPlugin.js:dev server 把 COCKPIT_GIS_MOUNTS(.env.local 里给的 {prefix,dir} 列表)挂成静态路径 —— DEM 与影像上百 MB,既不进仓库也不进产物;没配就什么也不挂,别的机器照常跑。domain/mapLayers.js(新):planTerrain() / planOverlays() / planTilesets() 纯函数计划层;services/cockpitConfig.js 增加 map.terrain{url,requestVertexNormals}、map.overlays[]{url,minimumLevel,maximumLevel,bounds,credit}、map.tilesets[]{url,maximumScreenSpaceError,credit} 的归一化与校验。services/cesiumEngine.js:applyTerrain() 走 CesiumTerrainProvider.fromUrl(量化网格,scheme:"tms" 由 Cesium 自己认,服务端不用翻 y);applyOverlays() 把本地精细切片叠在全局底图之上(TMS 用 {reverseY},并按 bounds 设 rectangle,范围外不发请求);applyTilesets() 逐项挂 Cesium3DTileset,单项失败不影响其它项。domain/basemap.js 新增免费全局层 preset arcgis-imagery(ArcGIS 官方世界影像,免费免 key,模板顺序 {z}/{y}/{x});离线优先:默认与推荐都是 natural-earth。services/mapService.js:引擎启动时按计划挂地形 / 叠加层 / 3D Tiles,宿主带 data-map-terrain、data-map-tilesets,getLifecycleStats() 增 terrain / terrainError / overlays / tilesets / tilesetErrors;浮标变成「底图:… · 地形:… · 叠加影像 N 层 · 3D Tiles N 个」。public/cockpit/config.json(本机真实配置,gitignore)按 yuanlingPic3/meta.json 的 bounds 设 bounds、按 TMS 用 {reverseY};.env.local 挂目录并打开配置文件层。docs/cockpit-deployment.md(给运维的生产部署手册):一页速查表、配置四层与开启方式、逐字段改法(后端/底图/地形/影像/3D Tiles)、nginx location 片段与两条硬要求(别走 SPA 回退、要 CORS)、完整最小配置、8 条自检表、常见问题。public/cockpit/README.md 顶部指路过去(它偏开发期接数据)。.scratch/cockpit-shell-panel-layout/verify/fixtures/tiles/tileset.json(只有包围盒、无 content 的合法 tileset,用来验证入口链路,不伪造任何模型/影像)。yarn dev @ 8001,Chrome 152 headless)t21-terrain.mjs:通过。含配置与磁盘数据对齐核对(layer.json 的 quantized-mesh-1.0 / EPSG:4326 / scheme:"tms" / octvertexnormals,meta.json 的 tms / 3857 / bounds 与配置一致)。t21-gis-walkthrough.mjs → 9/9:三层都挂上;细层影像只请求声明范围内的瓦片;压到沅陵拉近后 DEM 192 块(最高 14 级)+ 影像 199 块,全部 HTTP 200、零 404(这条同时证明 TMS 的 y 约定、availability、{reverseY} 都对);镜头停在沅陵上空 4.6 km;DEM 地址配错时 invalid + 明确失败文案 + 回退椭球;3D Tiles 入口:合法 tileset 挂上(stats.tilesets==1)而同批里坏的 URL 单独记失败(tilesetErrors 1 条)、引擎与其它图层不受影响;全程无页面级报错。yarn dev 不注入任何东西直接打开 /cockpit —— 离线全局影像球 + 顶栏「配置就绪 · 数据源 mock」+ 浮标「底图:内置离线影像 Natural Earth II · 地形:dem · 叠加影像 1 层」;换中心 + 滚轮拉近 4.6 km 后是沅陵县城真影像(河道、桥、体育场、建筑)。t01 走查 20/20、t04 9/9、t29 6/6、t06/t28/t03-camera-contract/t01-panel-catalog/t21-terrain/t29-basemap 逻辑脚本全通过、yarn build exit 0。natural-earth;在线源只做模板与署名断言,未真机验证(维护者明确"能用内网离线就不用在线",故不作阻塞项)。天地图无 key,同样不做主路径。D:\GIS\GIS\yuanlingSHP 确实是 3D Tiles:cesiumlab model2tiles 导出,5 个层级(16–20)、769 个分块 *.json + 772 个 *.glb,每个分块 json 是自洽的 tileset 文档。但缺根 tileset.json,且分块 boundingVolume.box 是局部坐标(例:中心 6265/2293;叶子 20 级为 -3258, 9736, 105),没有任何 transform —— 也就是没有把模型放到地球上的地理参考。
2026-09-18 结论:维护者目测判定「明显错位 + 只是白色立方体,效果非常差」→ 不采用。
合成的根 tileset.json 已删除,/gis/models 挂载已移除,yuanlingSHP 那份数据不再使用。
替代方案见 票 34(参照 GIS 数据做轻量体块模型)。
当时的做法与机器验证留档(供以后判断"错位"到底出在哪):
h49c004002/*.prj 为 GEOGCS["CGCS_2000", ... UNIT["Degree"]],output/*.json 是 GeoJSON;transform;为什么仍然错位:锚定假设("稠密簇中心 == 维护者给的目标坐标")没有依据 —— 原始导出本就没有原点, 靠推测必然偏;且分块体块是单色白模,与影像里的城市形态对不上。这条路先放下。
决策地图票 05 已把语义锁死,本轮按它落地:
domain/viewModes.js(纯函数):planViewMode() 把「哪个视图」翻译成相机预设 + 图层透明度;
viewHprFor() 只产出 {heading, pitch, range} —— 签名里根本没有中心参数,从构造上保证「切换视图不重置中心」。
管线视图:pitch 抬到 -18°(上限放宽到 +5° 允许平视/轻微仰视)、弹簧臂压到当前距离的 35%(夹在 400–6000 m)、
地形 α0.45 / 3D Tiles α0.4;地面视图:还原为 α1 与常规俯视。stores/filterStore.js:视图条件并入 filterStore(决策地图指定 —— 与行业筛选同属全局条件,切一级模式不重置)。services/cameraControl.js:新增 setPitchLimits() 与 setHpr() —— 只改限制与 pitch/range,不碰输入绑定、不碰中心。services/cesiumEngine.js:applyTilesets() 现在回传实例(供改样式);新增 applyViewModeLayers() ——
地形走 globe.translucency,3D Tiles 走 Cesium3DTileStyle 的 color alpha;地面视图清掉样式而不是设成 1。services/mapService.js:setViewMode() / getViewMode();进管线前记下地面基线(倾角+距离),回地面时按它还原;
宿主带 data-map-view-mode(启动即为 ground,不是切换过才有)。CockpitShell.vue:筛选条加「视图:地面视图 / 管线视图」两个按钮(data-view-mode + aria-pressed),
与范围/行业同级、切一级模式不重置。services/cockpitConfig.js + 部署手册 2.7:map.viewMode.pipeline{ pitch, rangeFactor, terrainAlpha, tilesetAlpha }
可覆盖默认值,脏值忽略退回默认。verify/t21-view-modes.mjs(逻辑)与 verify/t21-view-modes-walkthrough.mjs(真机)。t21-view-modes.mjs:通过。含构造性断言:viewHprFor() 的返回值里没有 pivot 字段、
计划里也没有中心 —— 「不重置中心」不是靠人眼比对,而是类型层面就不可能;另有地面还原(按基线)、
clamp 边界(min>max 的坑已修)、脏配置兜底。t21-view-modes-walkthrough.mjs → 10/10:初始 ground;切管线后距离 12000 → 4200 m、
pitch -55° → -18°,而中心经纬高完全一致(110.39028164000001, 28.4436787, 111.57951503970997 前后逐位相同);
按钮 aria-pressed 与 data-map-view-mode 同步;管线视图里左键仍只平移(中心移动 −0.0036°、距离/倾角不变)、
滚轮仍只改距离(4200 → 6787 m、倾角不变);回地面按基线还原(-55° / 12000 m);
切一级模式后仍是管线视图(全局条件);全程无页面级报错。yarn build exit 0(57 s)。map.tilesets[0] 即可 —— 入口、三态可见性与运行态加载链路均已就绪并已实测。city-regions-v7 的 manifest.json 里 runtimeValidated: false,即其性能/视觉尚未正式签收),不在本票范围内重复承担。