当前位置: 首页 > news >正文

Cesium 空间分析:一个完整的 “方量分析” 工具

用 Vue 3 + Cesium.js 撸了一个单文件 HTML 的挖填方计算工具,支持鼠标绘制多边形、地形采样、体积计算和 3D 可视化,完整代码直接贴末尾。

开篇

做三维 GIS 这几年,我发现一个挺有意思的事:方量分析这个需求,几乎所有做工程方向的团队都会遇到——修路的要知道挖多少填多少,做矿山的要算剥离量,搞建筑的要做土方平衡。说实话,Cesium 官方压根没给现成的轮子。

所以只能自己造一个。

这事儿其实不复杂。核心链路就四步:画多边形 → 采样地形高度 → 积分算体积 → 3D 可视化。但每一步都有坑,每一步踩过去才算真的搞懂了。下面我按 ++Cesium.js 1.140++ + ++Vue 3.5++ + ++Turf.js 7++ 这个技术栈,把整个工具拆开来讲。

核心架构:三个库撑起一个工具

先看一眼依赖关系。这个工具只靠三个外部库,全部从 CDN 加载:

  • @@Cesium.js@@ 负责 3D 地球 + 地形采样 + 可视化实体
  • @@Turf.js@@ 负责空间计算(面积、网格、多边形布尔)
  • @@lil-gui@@ 负责右侧那个调参面板
  • @@Vue 3@@ 做状态管理和生命周期

为什么选这几个?&&Cesium 在三维 GIS 领域没对手,地形采样 API 是刚需&&。Turf.js 处理空间运算比手写快得多,lil-gui 绑几个数值控制器只需要 5 行代码。Vue 3 的 CDN 引入方式对单文件 HTML 极其友好——createApp({...}).mount('#app')一口气搞定。

整个架构一句话:Cesium 负责"看",Turf 负责"算",Vue 负责"管",lil-gui 负责"调"。

交互绘制:鼠标画多边形那点事

交互设计这个工具我最终用了 ++左键加点 → 右键结束++ 的模式,比"双击结束"更不容易误触——这事儿是我在好几个项目里被用户投诉之后总结出来的(鼠标右键在浏览器里默认弹菜单,但 Cesium 的ScreenSpaceEventHandler能拦截,倒也省心)。

来看看ScreenSpaceEventHandler怎么接住三种鼠标动作:

  1. %%MOUSE_MOVE%%:实时预览多边形形状——用CallbackProperty动态重建顶点数组,鼠标移动到哪,半透明的黄绿色预览就画到哪。这一步如果不用CallbackProperty而是每次都新建 Entity,性能会炸
  2. %%LEFT_CLICK%%:记录顶点坐标,tooltip 跟手显示"已添加 N 个点"
  3. %%RIGHT_CLICK%%:结束绘制,触发计算管线

这里有一个容易被忽略的细节:depthTestAgainstTerrain = true。如果不开启地形深度检测,你画的多边形会被地形遮挡,用户根本看不见自己画了啥。&&这个设置对方量分析是必需的,但它会略微增加 GPU 负担,所以在不需要地形交互的场景下建议关掉。&&

另外,每次startMeasure之前强制clearMeasure清掉上一轮的所有实体和数据。这不是"好习惯",是必须——留一个旧的CallbackProperty在那里,预览会乱套。

地形采样:最核心也最容易翻车的环节

画完多边形后,不能直接拿那几个顶点算体积——那叫"用 5 个点代表一个足球场"。正确做法是:在区域内均匀撒点网格,每个点采样地形高度,逐格积分

// 1. Turf 计算网格this.cellsize=Math.sqrt(this.polygonArea/10000);// 约10000个格constgrid=turf.pointGrid(bbox,this.cellsize,{units:"meters"});constptsWithin=turf.pointsWithinPolygon(grid,polygon);// 2. Cesium 采样constsamples=awaitCesium.sampleTerrain(this.viewer.terrainProvider,this.terrainLevel,// 地形精度等级,默认13cartographics,);

关键参数有两个:

  • @@cellsize@@:格子边长,按面积/10000 自动算,保证网格密度适中。面积越大格子越大,避免采样点爆炸
  • @@terrainLevel@@:传给sampleTerrain的精度等级,范围 7-15,用 lil-gui 的滑块随时调。精度越高采样越慢,我实测 level 13 在江苏 DEM 上是性价比最好的

Cesium.sampleTerrain是异步的——它要从terrainProvider读高程瓦片。如果用的是本地地形服务(像我这个http://127.0.0.1:8888/3dtiles/jiangsu/dem/),延迟可以忽略;如果用 Cesium Ion 的全球地形,&&强烈建议加 loading 状态,不然用户以为页面卡死了&&。

多说一句:%%如果你的地形源挂了,sampleTerrain静默返回高度为 0 的数组,不会抛错。所以一定要在结果里检查 height 值是否合理,别让 0 米高度混进计算。%%

体积算法:其实就一个网格积分

方量计算本身简单到让人怀疑——就是小学几何

把每个格子的高度跟基准面比较:

  • height > planeHeight→ 挖方(土多了,要挖掉)
  • height < planeHeight→ 填方(土少了,要填上)
// 格柱体积 = 高度差 × 格子面积constdiff=h-planeHeight;if(h>planeHeight){cutVol+=diff*cellsize*cellsize;// 挖方累加}// 填方 = 基准面以下总体积 - 地形自身体积constplaneBulk=polygonArea*(planeHeight-wallMinHeight);constfillVol=planeBulk-(totalVolume-cutVol);

基准面默认取多边形顶点的最低海拔——也就是说,第一次画完多边形后,基准面自动贴在地形最凹处。然后你可以用面板手动改,改了之后applyAdjust()就地重算,不重新采样。

这里有个我踩过的坑:fillVol会出现负数。为什么呢?因为planeHeight - wallMinHeight可能是负的(你把基准面拖到了墙底之下)。所以代码里加了fillVol > 0 ? fillVol : 0的保护。

一句话总结这个算法:把不规则的地形切成 N 个规则的小方柱,每个方柱单独算,然后加起来。

3D 可视化:围墙、基准面与实时调参

算出来数字不够直观?那就在 3D 场景里把结果"画"出来。

我用了三个 ++Cesium Entity++ 来表达方量分析结果:

  1. @@Wall(围墙)@@:从wallMinHeightwallMaxHeight的半透明青色墙体,沿多边形边界拉伸。视觉上就像一个从地形里切出来的"蛋糕块"。outline: true加白边,不然透明材质在深色背景上根本看不清。
  2. @@Polygon(基准面)@@:一个height = planeHeight的绿色半透明面,浮在围墙内部,它就是挖填方的分界线——面以上的土挖掉,面以下的坑填上。
  3. @@Label(标签)@@:画在多边形质心上方,显示"挖方体积/填方体积/横切面积",颜色用GOLD,带描边,不贴地(CLAMP_TO_GROUND在围墙内部会被挡住)

顶点上还有一圈金色海拔标签——&&这个细节在调试 DEM 数据的时候巨有用,一眼能看出来哪个顶点取到的是异常高度值&&。

参数调整是通过 lil-gui 的三个滑块完成的:基准面高、围墙底高、围墙顶高。每次拖滑块点"应用调整",applyAdjust()会同步更新围墙的minimumHeights/maximumHeights数组并重算体积。%%注意:围墙底高不能大于基准面高,代码里有自动修正。%%

lil-gui:让调参从"改代码"变成"拖滑块"

这部分其实可以展开说说。lil-gui是一个轻量级 UI 面板库,它的 API 设计有一个让我特别喜欢的地方:

// 传一个普通对象和控制属性名,自动生成控件letcutDisplay={cutVolume:"—"};this._ctrlCutVol=gui.add(cutDisplay,"cutVolume").name("挖方量").disable();// 更新显示只需要改原对象,然后调 updateDisplay()this.cutDisplay.cutVolume="1.23万立方米";this._ctrlCutVol.updateDisplay();

对象是数据源,GUI 只是视图层。这种单向数据流让状态管理极其干净——没有"面板里的值和 JS 变量里的值不一致"的问题。

整个面板分了四个功能区:

  • &&测量操作&&:开始绘制、清除、重置视角
  • &&参数调节&&:基准面、围墙底/顶高、地形精度滑块
  • &&计算结果&&:挖方量、填方量、横切面积(只读)
  • &&图层控制&&:影像开关、透明度

每个区都是一个addFolder,视觉上清晰分层。lil-gui 默认会折叠所有 folder 再展开第一个——所以"测量操作"默认可见,符合操作流。

(扯远一句:lil-gui 的作者是 @georgealways,这个库只有 15KB gzipped,比 dat.gui 轻一个数量级。如果你还在用 dat.gui,真的可以换了。)

环境搭建与底图

环境:一个能跑 HTTP 的本地服务器就行。没有 webpack、没有 vite,浏览器直接打开 HTML 文件就能跑。前提是有地形数据——我用的是本地 DEM 瓦片服务跑在 8888 端口。如果你没有,&&把initTerrain里的注释打开,切到Cesium.createWorldTerrain(),但需要 Cesium Ion Token&&。

底图:ArcGIS World Imagery 卫星图,通过UrlTemplateImageryProvider加载,这东西的好处是免费+全球覆盖+不用 Token。缺点是国内部分地区加载速度一般,你可以换成天地图或其他 WMTS 服务。

[SEC]

完整代码

以下是完整的volume_analysis.html,可以保存到本地直接打开==(需替换Cesium.Ion.defaultAccessToken为你自己的 Token):

文章首发:“GIS 开发手记” ,原文地址:https://mp.weixin.qq.com/s/lHdXVWTexFcwVtcjG93BqA

写在最后

这个工具从写第一行到能跑通大概花了一个下午,但打磨交互细节(实时预览、tooltip 跟手、参数面板的组织方式)花了两天。

说实话,Cesium.js 做方量分析的硬核部分不是公式,而是三件事:一是地形采样 API 的异步时序要处理好,二是depthTestAgainstTerrain这类配置开关要知道什么场景用什么值,三是可视化实体(Wall / Polygon / Label)的组合方式要让人一眼看懂数据。

&&如果你也在做类似的东西,这个单文件 HTML 可以直接保存到本地改。换自己的地形服务、换底图、加导出 Excel 功能——代码结构很直,改起来不费劲。&&

有什么问题或者更好的实现思路,欢迎留言聊。我可能说错的地方也有——毕竟这东西迭代了好几版,每版都推翻过前面的设计。

往期精选

  • 3D 城市限高分析:Cesium 实战示例
  • Cesium 中北斗网格可视化
  • 深度解析 GB/T 39409-2020《北斗网格位置码》
  • Cesium 空间分析:坡度分析
  • Cesium 通视分析:3D 城市模型上"划线"看可见区
  • Cesium 3D 热力图:从 Canvas 热力到 GPU 顶点着色器
  • Cesium 点聚合:海量点地图可视化方案
  • 自定义虚线箭头材质:把两个内置 Material 焊在一起
  • Cesium 中文字体:贴地 / 贴墙 / 动态文字方案
  • 网络地图坐标系完全指南:WGS84 / GCJ02 / BD09 / CGCS2000 与坐标转换实战
http://www.jsqmd.com/news/1301092/

相关文章:

  • 企业AI定制:你的公司真的需要吗?
  • 百联ok卡回收的正确流程和闲置卡券处理建议 - 圆圆收
  • 基于STM32与Rd-03雷达模组实现人体感应灯:嵌入式开发实战
  • 想找新南威尔士大学留学中介?可按这四个类别缩小选择范围 - 米諾
  • 鸿蒙开发语言选择指南:ArkTS、Java与C++的应用场景解析
  • 3步搞定云原神签到:告别手动烦恼的终极自动化方案
  • 计算机毕业设计之基于springboot毕业设计管理系统的设计与实现
  • 汕头汽车音响技术老店亲测2026汽车音响首推汕头车韵 - 米諾
  • 完全掌控大疆无人机固件:DankDroneDownloader专业级固件管理完全手册
  • 如何快速修复损坏视频:untrunc免费开源工具的终极指南
  • 2026开封家电维修师傅上门电话空调冰箱洗衣机热水器燃气灶同城急修推荐 - 全国家电维修上门服务
  • 皮质、五金影响回收价,2026 合肥蜀山区奢侈包回收,易奢福评估标准公开 - 易奢福
  • Java CompletableFuture异步编排实战与优化
  • Switch第三方控制器终极指南:如何用sys-con免费解锁全平台手柄支持
  • python 的字典结构中 key 是否必须用引号
  • Langfuse-开源AI观测分析平台,结合dify工作流
  • 同城双中心:为什么一家上了网关,一家还在救火
  • 142、eIQ的预测维护案例
  • 库卡焊接机器人氩气省气装置
  • 3步快速恢复Windows经典开始菜单:Open-Shell-Menu终极配置指南
  • 盈兴通:告别产线“隐形杀手”:一张无尘卷轴布,如何为精密制造筑牢品质防线?
  • 如何3分钟掌握专业数据恢复:免费开源工具的终极指南
  • 2026廊坊家电维修师傅上门电话空调冰箱洗衣机热水器燃气灶同城急修推荐 - 全国家电维修上门服务
  • Windows 与 Mac 双端适配,OpenClaw 2.7.9 轻量化安装与功能调试教程
  • 男生学网络安全怎么样?武汉新华网络信息防护专业 - 湖北升学规划
  • 终极网页资源嗅探工具:猫抓浏览器扩展完整指南
  • 中高端木纹砖源头厂家
  • C++实现跨平台云备份工具:架构设计与工程实践
  • AI流利度:提升人机交互体验的关键指标
  • 2026阜阳婚纱照实力榜单:资深婚礼策划推荐的3家定制婚纱摄影 - 商业信息快查