大家好,我是日拱一卒的
攻城师不浪
,致力于前沿科技探索,摸索小而美工作室,这是2025年输出的第59/100篇原创文章。
效果预览
www.bilibili.com/video/BV1bg...
前言
在工程建设领域,土方量的精确计算一直是个技术活。传统的测量方式不仅耗时费力,而且精度难以保证。这时候,就体现出数字化能力的重要性了!
今天,我们用Cesium
来构建一个专业级的填挖方分析工具,让复杂的土方计算变得简单、直观又精确。
为什么选择数字化土方分析?
想象一下,你在施工现场需要计算一片不规则区域的土方量。传统方法需要大量的实地测量点,然后用复杂的数学公式进行计算。
而我们的数字化方案,只需要在三维场景中圈定区域,系统就能自动完成复杂的计算工作。
这套系统主要解决三个核心问题:
-
交互性:用户可以直接在三维场景中绘制分析区域
-
精确性:基于高精度地形数据进行体积计算
-
可视化:直观展示填方、挖方的分布情况

技术原理:把复杂问题简单化
多边形细分:化整为零
首先,我们来看看系统是如何处理用户绘制的不规则多边形的。在 ExcavationAndFillAnalysis
类中,有这样一段关键代码:
javascript
createPolygonGeo(points) {
let granularity = Math.PI / Math.pow(2, 11);
granularity = granularity / this.precision;
let polygonGeometry = new Cesium.PolygonGeometry.fromPositions({
positions: points,
vertexFormat: Cesium.PerInstanceColorAppearance.FLAT_VERTEX_FORMAT,
granularity: granularity,
});
this.geom = Cesium.PolygonGeometry.createGeometry(polygonGeometry);
}
这里的 granularity
参数很有意思,它控制着多边形的细分程度。Math.PI / Math.pow(2, 11)
计算出约等于0.00153的弧度值,这个值除以精度参数后,决定了多边形会被分解成多少个小三角形。
精度越高,三角形越多,计算越精确,但性能开销也越大。
海伦公式:古老数学在现代工程中的应用
对于每个小三角形,我们需要计算它的面积。这里用到了著名的海伦公式:
javascript
computeArea4Triangle(pos1, pos2, pos3) {
let a = Cesium.Cartesian3.distance(pos1, pos2);
let b = Cesium.Cartesian3.distance(pos2, pos3);
let c = Cesium.Cartesian3.distance(pos3, pos1);
let S = (a + b + c) / 2;
return Math.sqrt(S * (S - a) * (S - b) * (S - c));
}
海伦公式的美妙之处在于,只需要知道三角形的三边长度,就能算出面积。
在我们的场景中,pos1
、pos2
、pos3
是投影到水平面的三个顶点,通过 Cesium.Cartesian3.distance
计算出边长,然后套用公式即可。
填挖方判断依据:基准面
最核心的逻辑在于如何判断某个区域是需要填方还是挖方:
javascript
const averageHeight = (returnPosition.pos0.height + returnPosition.pos1.height + returnPosition.pos2.height) / 3;
if (averageHeight < this.height) {
// 需要填方的部分
fillArea += area;
fillVolume = fillVolume + area * (this.height - averageHeight);
} else {
// 需要挖方的部分
cutArea += area;
cutVolume = cutVolume + area * (averageHeight - this.height);
}
一个简单而有效的思路:
-
计算三角形三个顶点的平均高度
-
与设定的基准面高度
this.height
比较 -
低于基准面的需要填方,高于基准面的需要挖方
-
体积 = 面积 × 高度差
交互式绘制:让用户体验更友好

DrawPolygon
类负责处理用户的交互操作:
javascript
start(callback) {
this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
this.handler.setInputAction((event) => {
let earthPosition = this.viewer.scene.pickPosition(event.position);
// 处理左键点击,添加顶点
this.activeShapePoints.push(earthPosition);
this.createPoint(earthPosition);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
this.handler.setInputAction((event) => {
// 处理鼠标移动,实时更新多边形
let newPosition = this.viewer.scene.pickPosition(event.endPosition);
this.floatingPoint.position.setValue(newPosition);
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
}
让用户可以:
-
左键点击:添加多边形顶点
-
鼠标移动:实时预览多边形形状
-
右键点击:完成绘制并开始分析
-
Ctrl+Z:撤销上一个点
地形高度采样:精度的保障
在 returnPosition
方法中,有一个关键的高度获取逻辑:
javascript
let height = this.viewer.scene.sampleHeightSupported
? this.viewer.scene.sampleHeight(cartographic)
: this.viewer.scene.globe.getHeight(cartographic);
这里做了一个兼容性处理:
-
优先使用
sampleHeight
,它能提供更精确的高度信息 -
如果不支持,则使用
getHeight
作为备选方案
这种设计确保了在不同的 Cesium
版本和配置下,都能获取到可靠的地形高度数据。
可视化展示:让数据说话
计算出结果,要直观地展示出来:

javascript
// 计算三个点的平均高度
const averageHeight = (pos0.height + pos1.height + pos2.height) / 3;
// 根据平均高度判断是挖方(红色)还是填方(绿色)
const materialColor = averageHeight < this.height ? Cesium.Color.GREEN : Cesium.Color.RED;
let polygon = this.viewer.entities.add({
polygon: {
hierarchy: [pos0.topheightPos, pos1.topheightPos, pos2.topheightPos],
perPositionHeight: true,
material: materialColor,
extrudedHeight: this.height,
},
});
this.entitypolygon.push(polygon);
根据三角形的三个点计算他们的平均高度,然后跟基准面高度进行对比,小于基准面的(填方)用绿色
,大于基准面(挖方)的用红色
表示。
性能优化的考量
我们在工具中添加了对不同精度的支持:
javascript
const fly3DTiles = async () => {
precision.value = 256 // 3D模型场景使用较高精度
};
const flyMountain = () => {
precision.value = 20 // 山体地形使用较低精度
};
这是一个很实用的优化策略:
-
3D建筑模型:细节丰富,需要高精度分析
-
自然地形:相对平缓,可以适当降低精度以提升性能
实际应用场景
这套系统特别适合以下场景:
-
建筑工地:计算基础开挖和回填土方量
-
道路建设:分析路基的填挖方分布
-
景观设计:规划地形改造的工程量
-
矿山开采:估算开采和复垦的土方需求
最后
通过 Cesium
强大的三维能力,我们将复杂的土方分析变成了一个直观、精确、易用的数字化工具。
该系统目前可同时支持倾斜摄影
以及山地地形
的填挖方测量!

想系统学习Cesium的小伙伴儿,可以了解下不浪的教程
《Cesium从入门到实战》
,将Cesium的知识点进行串联,让不了解Cesium的小伙伴拥有一个完整的学习路线,并最终完成一个智慧城市
的完整项目,关注公众号:攻城师不浪,即可获取教程介绍,也可+作者:brown_7778(备注来意)。
有需要进可视化&Webgis交流群
可以加我:brown_7778(备注来意)。