ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

第17章:CesiumJS 从入门到精通17:山峦的肌理——高程地形加载与分析

第17章:CesiumJS 从入门到精通17:山峦的肌理——高程地形加载与分析 专栏连载提醒本文是《CesiumJS 从入门到精通》第 17 篇建议按专栏顺序阅读完整搭建三维 GIS 知识体系写在前面上一章讲解影像栅格图层实现地球表面纹理贴图但无高程起伏的地球只是二维贴图。地形 DEM 高程数据是三维地球的骨架赋予山脉、盆地、平原真实高差立体感。 本章完整讲解 Cesium 地形系统地形瓦片原理、TerrainProvider 各类数据源加载、地形光照、垂直夸张放大、高程采样测量、高度参考贴地逻辑配套完整可运行综合 Demo覆盖地形可视化、地形分析、模型贴地等数字孪生高频场景。本章学习目标理解 DEM 数字高程模型、quantized-mesh 地形瓦片四叉树 LOD 加载机制熟练使用各类TerrainProvider加载 Cesium Ion 全球地形、自定义本地地形服务掌握enableLighting地形光照强化山体明暗立体效果通过verticalExaggeration垂直夸张系数放大微地形起伏使用sampleTerrain异步采样任意经纬度精确海拔实现地形剖面分析吃透HeightReference高度参考枚举解决模型埋地 / 悬空问题实现要素贴地渲染一、地形数据底层原理DEM 高程网格1.1 DEM 数字高程模型概念DEM数字高程模型用二维网格存储每个坐标点海拔高度区别于影像 RGB 颜色值像素存储米级高程负数代表海平面以下。 类比影像 地球皮肤纹理地形 DEM 地球骨骼高差。1.2 Cesium quantized-mesh 专用地形瓦片Cesium 自研量化网格地形格式对比普通 GeoTIFF 优势四叉树分层 LOD远距离粗瓦片、近距离高精度瓦片按需加载内置顶点法线支持实时太阳光阴影渲染附带水面掩码实现湖泊、海洋水面特效二进制轻量化压缩传输体积远小于原始 DEM1.3 地形瓦片加载流程全球地形四叉树分层递归切割从根节点全局低精度瓦片逐级细分至局部厘米 / 米级高精度瓦片相机移动自动调度、缓存、卸载瓦片。二、TerrainProvider 地形数据源加载器Cesium 采用多实现类统一抽象地形加载切换数据源无需改动渲染逻辑类名适用场景数据源EllipsoidTerrainProvider无地形平地模式内置椭球面所有高程 0CesiumTerrainProvider最常用quantized-mesh 标准Cesium Ion 全球地形 / 自研地形服务ArcGISTiledElevationTerrainProvider对接 ArcGIS 高程服务ArcGIS Server 在线高程VRTheWorldTerrainProvider全球公开简易地形VR-TheWorld 公开接口2.1 默认平地椭球地形无任何高程起伏适合平面地图展示viewer.terrainProvider new Cesium.EllipsoidTerrainProvider();2.2 Cesium Ion 全球标准地形项目首选assetId1 为 Cesium 全球免费地形需配置 Ion TokenCesium.Ion.defaultAccessToken 你的Ion密钥; // 简化写法Cesium1.106 const worldTerrain Cesium.Terrain.fromWorldTerrain({ requestVertexNormals: true, // 开启法线光照生效 requestWaterMask: true // 水面掩码 }); viewer.terrainProvider worldTerrain;2.3 自建本地 quantized-mesh 地形服务const customTerrain new Cesium.CesiumTerrainProvider({ url: https://xxx.com/terrain/tileset.json, requestVertexNormals: true, requestWaterMask: true }); viewer.terrainProvider customTerrain;核心配置参数requestVertexNormals请求顶点法线地形光照必须开启requestWaterMask开启水面识别实现湖面、海面渲染ellipsoid默认 WGS84 椭球一般无需修改三、enableLighting 地形太阳光立体光照3.1 光照作用默认关闭光照时山体无明暗区分灰蒙蒙一片开启后根据太阳方位计算坡面明暗山脊、沟壑立体感大幅提升。 性能轻微增加 GPU 着色计算大屏、PC 端建议常开低配移动端按需关闭。3.2 基础开关// 全局开启地形光照 viewer.scene.globe.enableLighting true; // 初始化Viewer时直接配置 const viewer new Cesium.Viewer(cesiumContainer, { terrain: Cesium.Terrain.fromWorldTerrain(), globe: { enableLighting: true } });3.3 动态切换 自定义太阳光强度 / 方位// 按钮切换光照 document.getElementById(lightBtn).onclick () { viewer.scene.globe.enableLighting !viewer.scene.globe.enableLighting; }; // 调整全局光照强度 viewer.scene.light.intensity 1.5; // 自定义太阳方向模拟早中晚光照 function setSunHour(hour) { const rad Cesium.Math.toRadians(hour / 24 * 360 - 90); viewer.scene.light.direction new Cesium.Cartesian3(Math.cos(rad),0.3,Math.sin(rad)); } setSunHour(14); // 下午两点阳光四、verticalExaggeration 地形垂直夸张系数4.1 功能说明对地形高程统一缩放倍数解决平原、微地形高差过小看不清的问题0.1~0.9压缩地形弱化起伏1.0真实比例默认1.5~5放大微地形地质、河道分析常用5极端夸张仅演示特效易出现穿模4.2 基础用法viewer.scene.verticalExaggeration 3; // 高程放大3倍4.3 滑块实时调节完整 HTMLJSdiv styleposition:absolute;bottom:20px;left:10px;z-index:999;background:rgba(0,0,0,0.7);color:#fff;padding:10px;border-radius:6px; 地形夸张span idexVal1.0/spanx input typerange min0.1 max5 step0.1 value1 idexSlider /divconst slider document.getElementById(exSlider); slider.oninput e { const val parseFloat(e.target.value); document.getElementById(exVal).innerText val.toFixed(1); viewer.scene.verticalExaggeration val; };五、sampleTerrain 高程异步采样测量5.1 应用场景单点海拔测量、两点高差计算、地形剖面线、淹没分析、飞行器安全高度判断。 特性异步请求地形瓦片批量支持多点同时采样返回精确米级高程。5.2 单点采样示例珠峰高程// 经纬度转弧度坐标 const point Cesium.Cartographic.fromDegrees(86.9250,27.9881); Cesium.sampleTerrain(viewer.terrainProvider, 12, [point]) .then(res { const height res[0].height; console.log(采样海拔, height.toFixed(2), 米); }) .catch(err console.error(采样失败, err));参数说明terrainProvider当前场景地形源level采样瓦片层级9~14层级越高精度越高、请求越多positionsCartographic 弧度坐标数组支持批量多点5.3 批量采样生成地形剖面两点之间均匀生成采样点批量获取高程数据可结合 ECharts 绘制剖面图async function getTerrainProfile(lon1,lat1,lon2,lat2,count100) { const points []; for(let i0;icount;i){ const t i/count; const lon Cesium.Math.lerp(lon1,lon2,t); const lat Cesium.Math.lerp(lat1,lat2,t); points.push(Cesium.Cartographic.fromDegrees(lon,lat)); } const data await Cesium.sampleTerrain(viewer.terrainProvider,12,points); return data.map(item({ lon:Cesium.Math.toDegrees(item.longitude), lat:Cesium.Math.toDegrees(item.latitude), height:item.height })); } // 调用拉萨-日喀则剖面 getTerrainProfile(91.1320,29.6604,88.8910,29.2669,100).then(profileconsole.log(profile));5.4 采样注意事项平地 EllipsoidTerrainProvider 采样高度恒为 0无实际意义高频循环采样需做缓存避免大量重复网络请求必须异步 await/then 获取高程同步读取会返回空值六、HeightReference 高度参考模型贴地核心6.1 两类核心枚举HeightReference.NONE高度基于 WGS84 椭球面0 海平面山区模型易埋入山体 / 高空悬空HeightReference.CLAMP_TO_GROUND高度基于地形地表0 紧贴地面自动跟随地形起伏6.2 实体模型贴地示例飞机模型viewer.entities.add({ position:Cesium.Cartesian3.fromDegrees(103.9470,30.5728,0), model:{ uri:airplane.glb, heightReference:Cesium.HeightReference.CLAMP_TO_GROUND, // 关键贴地配置 scale:1 } });逻辑position 内高度值为相对地面高度而非绝对海拔自动贴合起伏地形。6.3 对比演示同一坐标两种高度模式珠峰点位同时创建红色悬空点NONE、绿色贴地点CLAMP_TO_GROUND直观高差对比const lon86.9250,lat27.9881; // 椭球面500米埋在山体内部 viewer.entities.add({ position:Cesium.Cartesian3.fromDegrees(lon,lat,500), point:{pixelSize:15,color:Cesium.Color.RED}, label:{text:NONE 椭球面高度} }); // 地形上方500米悬浮山顶上空 viewer.entities.add({ position:Cesium.Cartesian3.fromDegrees(lon,lat,500), point:{pixelSize:15,color:Cesium.Color.LIME,heightReference:Cesium.HeightReference.CLAMP_TO_GROUND}, label:{text:CLAMP_TO_GROUND 相对地面高度} });6.4 贴地折线旧写法viewer.entities.add({ polyline:{ positions:Cesium.Cartesian3.fromDegreesArrayHeights([103,30,100,104,30.5,200]), clampToGround:true, // 折线强制贴地 width:5,material:Cesium.Color.RED } });七、综合完整 Demo地形控制面板 高程采样整合光照开关、地形夸张、区域飞行、中心高程采样开箱即用 HTML 页面!DOCTYPE html html head meta charsetutf-8 script srchttps://cesium.com/downloads/cesiumjs/releases/1.120/Build/Cesium/Cesium.js/script link hrefhttps://cesium.com/downloads/cesiumjs/releases/1.120/Build/Cesium/Widgets/widgets.css relstylesheet style html,body,#cesiumContainer{width:100%;height:100%;margin:0;padding:0;overflow:hidden} .tool{position:absolute;top:10px;left:10px;z-index:999;background:rgba(0,0,0,0.75);color:#fff;padding:15px;border-radius:8px;width:300px} .info{position:absolute;bottom:10px;right:10px;color:#0f0;background:rgba(0,0,0,0.7);padding:10px;border-radius:4px;font-family:monospace} /style /head body div idcesiumContainer/div div classtool h3地形控制面板/h3 labelinput typecheckbox idlightCheck checked 地形光照/label div stylemargin:8px 0 label夸张系数 span idexNum1.0/spanx/label input typerange min0.1 max5 step0.1 value1 idexSlide stylewidth:100% /div select idareaSel stylewidth:100%;padding:4px;margin:8px 0 option valueeverest珠穆朗玛峰/option option valuecanyon科罗拉多大峡谷/option option valueplain华北平原/option /select button idsampleBtn stylewidth:100%;padding:6px采样屏幕中心海拔/button /div div classinfo idinfoBox等待地形加载/div script Cesium.Ion.defaultAccessToken 替换为你的Ion Token; const viewer new Cesium.Viewer(cesiumContainer,{ terrain:Cesium.Terrain.fromWorldTerrain({requestVertexNormals:true,requestWaterMask:true}), globe:{enableLighting:true}, animation:false,timeline:false }); const infoBox document.getElementById(infoBox); // 光照切换 document.getElementById(lightCheck).onchange e{ viewer.scene.globe.enableLighting e.target.checked; }; // 地形夸张调节 const exSlide document.getElementById(exSlide); exSlide.oninput e{ const v parseFloat(e.target.value); document.getElementById(exNum).innerText v.toFixed(1); viewer.scene.verticalExaggeration v; }; // 区域飞行 const areaMap { everest:{lon:86.925,lat:27.9881,alt:20000}, canyon:{lon:-112.112,lat:36.097,alt:15000}, plain:{lon:117.2,lat:39.13,alt:50000} }; document.getElementById(areaSel).onchange e{ const a areaMap[e.target.value]; viewer.camera.flyTo({ destination:Cesium.Cartesian3.fromDegrees(a.lon,a.lat,a.alt), orientation:{heading:0,pitch:Cesium.Math.toRadians(-45),roll:0}, duration:3 }) }; // 屏幕中心采样高程 document.getElementById(sampleBtn).onclick async (){ const ray viewer.camera.getPickRay(new Cesium.Cartesian2(viewer.canvas.clientWidth/2,viewer.canvas.clientHeight/2)); const hit viewer.scene.globe.pick(ray,viewer.scene); if(!hit) return alert(对准地面再采样); const carto Cesium.Cartographic.fromCartesian(hit); const [res] await Cesium.sampleTerrain(viewer.terrainProvider,12,[carto]); infoBox.innerHTML 经度:${Cesium.Math.toDegrees(res.longitude).toFixed(4)}br纬度:${Cesium.Math.toDegrees(res.latitude).toFixed(4)}br高程:${res.height.toFixed(2)} m; } /script /body /html八、性能与调试工具8.1 地形优化要点低配移动端降低verticalExaggeration关闭requestVertexNormals、地形光照大范围宏观浏览调高 sampleTerrain 采样层级 level9~10减少请求高精度地形分析场景 level12~14限制单次采样点数水面特效无用时关闭requestWaterMask减少瓦片体积8.2 调试参数viewer.scene.debugShowFramesPerSecond true; // 显示实时帧率 viewer.scene.globe.tileLoadProgressEvent; // 监听瓦片加载进度本篇总结地形核心载体为 DEM 高程模型Cesium 采用 quantized-mesh 四叉树瓦片分层 LOD 加载兼顾精度与加载性能。CesiumTerrainProvider是主流地形加载器支持 Ion 全球地形与自研本地地形服务法线、水面掩码按需开启。enableLighting太阳光阴影强化山体立体感verticalExaggeration垂直放大微地形适配地质、河道分析场景。sampleTerrain异步批量采样任意坐标海拔可实现单点测量、地形剖面线等高阶 GIS 分析功能。HeightReference两种高度参考模式CLAMP_TO_GROUND实现模型、折线、点位自动贴地解决山区埋地 / 悬空问题。配套完整可交互地形控制面板 Demo覆盖地形可视化、高程测量、动态参数调节全业务需求。课后实操练习数据源切换分别切换 Ellipsoid 平地、Ion 全球地形对比视觉差异与加载速度。日照动画定时器循环修改太阳方位模拟 24 小时日照变化观察山体光影变化。地形剖面工具两点绘制采样剖面使用 Canvas 绘制高程折线图。模型贴地对比同一山区坐标分别使用 NONE/CLAMP_TO_GROUND 放置 GLB 模型直观区分两种高度模式。图层组合结合第 16 章影像图层实现多影像 多地形源切换管理器。下一篇预告CesiumJS 从入门到精通 18万物生长的法则 ——3D Tiles 与 Batched 3D Model详解 b3dm 瓦片格式原理、批量模型存储结构、倾斜摄影 / BIM 数据解析结合要素属性表、样式着色实现城市三维建筑可视化。
返回列表