进入测绘这行第七年的时候,我接了个任务:矿山排土场回填区要做一个场地平整,业主给的CAD图上只有边界和几个高程控制点,要求三天内给出一份填挖方量。办公室没有飞时达授权,现装正版根本来不及,手头只有一台装了Arcmap 10.4的电脑。说实话,就是在那个时候我才认真开始研究用Arcmap算土方量。后来发现在不少中小项目里,这套流程不仅够用,而且比专用软件更透明——每一步都能看得见、查得清,出了问题也知道往哪查。这篇文章我把完整流程和真实踩坑记录写下来,给同样临时上阵的兄弟们一条能直接走的路。
下面的内容按数据准备、表面建模、填挖方计算、结果验证和出图几个环节展开,每个环节我都会把操作步骤和背后的原理放在一起讲,因为只给步骤不给理由,换个数据你就不会活了。
1. 为什么Arcmap能算土方量:先搞懂计算原理
1.1 土方量计算的数学本质
土方量计算的本质是体积差。我们把施工前的现状地面和一个设计地面放在同一个空间里,两个面之间的空隙就是需要填进来或者挖出去的土体体积。这个体积不是一个容易用公式直接求出来的规则几何体,而是一个不规则曲面之间的夹层。
在实际计算中,我们把这个夹层切成无数个微小柱体,每个柱体的底面积是一个很小的平面单元,高度是这个单元上两个表面的高程差,然后把这些微小体积全部累加。这就是计算机做土方计算的底层思路——积分思想的离散化。
在Arcmap里,这个"微小平面单元"可以是栅格中的一个像元,也可以是TIN(不规则三角网)中的一个三角形面片。像元面积由分辨率决定,1米分辨率和2米分辨率,同样一块场地,参与累计的像元数差四倍,计算量不同,精度也不同。三角形面片则是由原始高程点直接连接而成,面积大小不均匀,但在表达地形起伏时更贴近真实。
1.2 Arcmap中的三条实现路线
Arcmap的3D Analyst扩展模块为土方计算提供了几条不同路径,我在实际项目中主要使用三种。
| 方法 | 核心原理 | 输出结果 | 适用场景 |
|---|---|---|---|
| Cut/Fill(填挖方工具) | 对两个栅格按像元逐一比较高程差,乘以像元面积得体积 | 一个填挖体积栅格 | 全场快速评估、区域面积较大 |
| Polygon Volume(面体积工具) | 以TIN表面为基础,统计某个参考面之上/之下的体积 | 体积统计表和多边形面 | 有明确边界、需要精确分区块统计 |
| Surface Difference(表面差分工具) | 直接比较两个TIN,生成差异多面体 | 多面体要素,属性含体积 | 需要可视化填挖区域、斜坡广布 |
这三种方式我都用公式给业主复核过,结果基本吻合。差异主要来自数据源是栅格还是TIN,以及边界处理方式。后面在实操部分我会逐一说清算法和注意点。
1.3 什么情况下推荐用Arcmap算土方
Arcmap不是专门的土方软件,但它在几种场景下很占优势。第一,项目范围内不仅要做土方,还要做地类分析、坡度分析、径流分析等多专业叠加,一套数据多个用途,用Arcmap能把土方计算无缝嵌进整个流程里。第二,计算过程完全可追溯,每一步都有中间数据,方便后来人检查,这在做审计、结算时特别重要。第三,对有无人机航测成果的项目,正射影像和DSM可以直接进Arcmap构建现状面,省掉大量外业。
不过也要说清楚,Arcmap不适合对施工算量要求极其严格的场景,比如高速铁路站场、大面积高标准农田整治这类需要精确到几方的工程,还是交给南方CASS或者专业土方软件更稳妥。Arcmap的优势在于快速评估、方案比选、多期对比,它的角色更像是一个"决策支持工具"而不是"造价算量工具"。
2. 动手前必须做对的数据准备
土方量计算里有个不成文的规矩:算出来的结果错得最离谱的时候,十次有八次不是算法出了问题,而是数据本身有问题。我踩过最大的坑就是坐标系不统一,白算了一整天。
2.1 坐标系不统一,算出来就是废的
Arcmap做表面分析时,虽然能把不同坐标系的图层动态叠加显示到一个视图里,看起来完全重合,但真正做裁切、体积计算时,底层会按各自的坐标系参与运算。如果现状高程点是CGCS2000高斯投影,设计面CAD是西安80,两者在同一视图里可能只差几米到几百米,动态投影肉眼看不出,但算出来的填挖方体积已经被扭曲得离谱。
更隐蔽的问题是数据源是地理坐标系,单位是度。如果你在建TIN时没有做投影转换,模型本身也能建,但算出来的面积单位是"平方度",体积单位是"立方度"。这个数值没有任何实际意义,而且你换个位置、换个纬度,同样的场地算出来体积都不同,因为经线纬度代表的弧长在不同地方不一样。
所以在动手前,务必把所有数据统一到一个投影坐标系。我的习惯是全部转到CGCS2000 3度分带的高斯投影,或者UTM对应分带,并把Z值单位统一为米。
2.2 Excel高程点导入Arcmap并生成shp
做土方计算最少不了的数据就是高程点。外业采集的高程点很多时候以Excel表格形式存放,格式是分列的点号、X坐标、Y坐标和高程。把表格数据变成能参与表面分析的shp文件,步骤并不复杂,但有几个细节要注意。
- 确认Excel表里字段名不要有中文和特殊字符,最好是"PID, X, Y, Z"这种格式,避免后续工具识别字段时出问题。
- 在Arcmap中单击"文件"菜单,选择"添加数据",再选"XY数据",弹出窗口中X字段选经度或X坐标列,Y字段选纬度或Y坐标列。
- 最关键的一步,设置坐标系统时要选择表格数据实际使用的坐标系。很多人习惯性点确定忘了这一步,后面全部白做。
- 生成的事件图层只是一个临时展示,必须右键图层,选择"数据"->"导出数据",导出为真正的shp文件,后续TIN工具才能正常使用。
- 高程Z值此时还没有作为要素属性,需要给shp添加一个Z字段。用"工具箱"里的"添加Z值"或直接用字段计算器,将高程列赋给Z字段。
数据量比较大时,比如几千个点以上,excel导入的过程可以选择直接用ArcToolbox里的"Excel转表"工具先转成dBASE表,再按上述步骤添加,速度会快很多。
2.3 高程异常点的识别与清理
外业采集的高程点里有飞点很正常,特别是植被覆盖的山地和建筑边角,一个突兀的高程点会在TIN里形成一根尖刺,从而在填挖方计算时凭空多出几百上千方。
识别异常点最直观的办法是先把高程点做渐变符号化,用"拉伸"方式按Z值渲染,然后用眼睛扫一遍,看有没有色调突变的点。更严格的做法是对高程点做一次统计分析,计算每个点的Z值与周围点的差值,超过三倍标准差的就标记出来,核对原始记录后再决定是否剔除。
我在生产中的做法比较笨但靠谱:先把高程点建一个TIN,在ArcScene里三维查看地形表面,凡是出现明显土柱、突刺的地方,就回到点图层定位检查。这样虽然耗时,但能发现很多自动检测漏掉的坏点。
2.4 设计面的两种获取方式
计算土方量必须有两个表面:现状面和一个"设计完成后的地面"。设计面怎么来,通常有两种情况。
第一种是水平设计面,场地平整后地面是一个固定高程。这是最简单的情况,你甚至不需要建设计面TIN,直接在填挖方工具里指定一个参考高度即可。Polygon Volume工具里可以直接填一个常数。
第二种是斜面或复杂设计面,比如道路、渠道、梯田整治,设计面在不同位置高度不同。这种情况一般从设计单位的CAD图中获取设计等高线,或者根据设计控制点构建。我的做法是把CAD等高线转成Arcmap的要素类,先检查等高线有没有标高字段,没有的还需要人工赋值,然后用等高线构建设计面TIN。
这里有一个经验:CAD转过来的等高线经常存在不闭合、自相交、重复线段等问题,直接拿去建TIN会出现畸形三角形。建TIN之前先用"修复几何"工具跑一遍,再用"生成要素节点"把断点标出来检查处理,能省掉后面大量排查时间。
3. 创建TIN和DEM:这一步决定了计算精度
表面模型的精度决定了土方计算结果的精度。Arcmap里建表面模型有两种主流方式,TIN和DEM,它们的适用范围差异很大。
3.1 为什么首选TIN而不是直接插值成DEM
很多教程一上来就让你用高程点插值成DEM,然后做填挖方计算。这其实容易出问题。当你手里高程点分布比较均匀、数量也比较多时,DEM和TIN差别不大。但当你的高程点分布不均匀,有密有疏时,DEM的一些插值算法(比如反距离权重法、克里金法)会平滑地形,把某些真实的地形特征消掉,同时在外围产生一些离谱的推测值。
TIN的优势在于它直接由原始高程点连线构成三角网,三角形顶点都落在实测点上,不产生新的推测数据。对于高差变化剧烈的场地,TIN表达地形的方式更忠实。面积较大的区域计算量会增加,但对于大多数中小型场地,这个差异可以忽略。
所以我的建议是:如果数据只有高程点,直接用高程点建TIN;如果有成熟的等高线数据,可以先用等高线做约束构建TIN,再转成DEM做栅格计算;如果是从无人机影像提取的DSM,已经是栅格了,那就不必绕弯子了,直接使用。
3.2 创建现状面TIN的详细操作
在ArcToolbox中依次展开"3D Analyst工具"->"数据管理"->"TIN"->"创建TIN",或者直接在搜索框中输入"创建TIN"。
输入要素选择你的高程点shp,在"SF_Type"里面选"Mass_Points",在"Height_Field"下拉框中选Z字段。如果你的数据里有地形断裂线(山脊线、坡脚线、地块边界线),也要作为"硬断线"输入进去。硬断线的作用是强制保留地形突变特征,避免三角网穿透道路边线或者坡坎。
输出坐标系务必改成项目使用的投影坐标系。这里有个容易被忽视的选项:"约束性Delaunay"勾选与否。勾选的话三角形的边可以和输入线要素重合,不勾选则优先满足Delaunay三角网的空圆特性。对土方计算来说,我建议勾选,因为这样地形特征线会被保留。
创建TIN之后,先在ArcMap里叠加高程点检查三角网形态。如果发现某些区域出现非常狭长的三角形,说明这些地方和周围点的连接关系有问题,可能是坏点或者缺少边界约束。狭长三角形会在体积计算时造成局部误差,尤其是做栅格转换时,这些三角形会被细化成很多像元,影响更明显。
3.3 创建设计面TIN与计算范围裁剪
设计面如果是水平面,最简单的方法是用"创建TIN"这个工具,加入一个矩形边界面,高程设为设计高程。这个矩形范围要完全覆盖你的计算区域,并且要比项目边界稍微外扩一点,防止后续分析时TIN边缘出现空洞。
如果设计面是斜面,建议从设计等高线建TIN。操作方式和现状面一样,将等高线加进TIN作为硬断线,高度字段选等高线的高程字段。
建好两个TIN后,有一个容易忽略的问题:两个TIN的覆盖范围是否一致。现状TIN的范围由高程点分布决定,设计TIN的范围由设计边界决定,它们往往不完全重合。在填挖方计算中,范围不一致的区域会产生无意义的计算结果,所以在正式计算之前,用你的计算边界做一个缓冲去裁剪两个TIN是非常必要的。
裁剪可以用"数据管理"下的"裁剪TIN"工具,或者直接用"提取分析"中的"按掩膜提取"把TIN转栅格时同时裁掉。我习惯用后者,因为土方计算严格来说只需要计算边界内的体量,边界外的三角形即使存在也不应该参与体积加总。
4. 填挖方计算实操:三个主流工具一次讲透
现在到了最关键的部分。前面准备的现状面TIN和设计面TIN,在这一步被用来计算体积。我会分别讲三个工具的使用方法和差异。
4.1 Cut/Fill:适合全场快速评估
Cut/Fill工具在ArcToolbox里的路径是"3D Analyst工具"->"栅格表面"->"填挖方"。这个工具要求输入两个栅格表面,一个代表施工前(Before),一个代表施工后(After)。如果你的数据是TIN,需要先用"TIN转栅格"工具把两个TIN都转成DEM。
TIN转栅格时的采样距离一定要设置合理。我一般用1米分辨率,高差变化大的山区用0.5米,平地用2米。采样距离越大,地形细节丢失越多,体积偏差越大。工具的计算逻辑是:逐个像元比较After和Before的高程差,用这个高程差乘像元面积得到该像元的体积,最后一个栅格里存储每个像元的体积值。
操作时填好Before surface、After surface、输出位置之后,记得把"输出测量单位"设为立方米。如果不设置,工具会按照输入数据的线性单位自动推算体积单位,多数情况下是对的,但也出现过单位显示错误的问题,所以看清楚结果再取数。
结果栅格出来后,在属性表里能看到每个像元的体积。正值和负值的含义需要观察,不要凭记忆判断。我的习惯是:找一个小范围、填挖方向已知的场地跑一次,确认正值对应的是需要挖方还是填方,再回到大面积结果里去统计。
统计全场总挖方和总填方时,可以用"鉴定分析"工具或者直接在属性表里分别对正负值求和。注意:Cut/Fill工具输出的只是一个像元级的体积栅格,它不会自动给你全场的合计值,这一点很多新手会误解。
4.2 Polygon Volume:更适合边界明确的精细计算
如果你手里是TIN数据,而且只需要统计某个明确边界内的土方量,那Polygon Volume工具比Cut/Fill更直接。这个工具的位置在"3D Analyst工具"->"功能性表面"->"面体积"。
它的原理是:以一个基准高度作为参考平面,计算TIN表面和这个参考平面之间的体积。TIN表面高于参考平面的部分,是"高出"的体积;低于参考平面的部分,是"低出"的体积。当参考平面代表设计高程时,高出部分就是需要挖掉的土方量,低出部分就是需要填进去的土方量。
操作上,输入表面选现状TIN,"高度"参数设置成设计高程值(如果是水平设计面),"输出体积要素类"指定一个位置和名称,方向选择通常选"ABOVE_AND_BELOW",这样把挖和填的量一次都算出来。
运行完成后,打开结果的属性表,会看到几个关键字段:
- Area:多边形覆盖的面积
- Positive Volume / Negative Volume:对应参考面以上和以下的体积
- Total Volume:两者之和的绝对值
我需要特别提一句:用这个工具时,当前TIN的Z单位必须是米。如果你之前的TIN是以厘米、英寸为单位建的,这里的体积计算结果会相差巨大。考证Z单位最直接的方法是在"图层属性"里看Z值显示范围,如果高程点的数值是几百几千,那基本是米;如果是几万几十万,那就要警惕了。
4.3 Surface Difference:比较两个TIN,结果最直观
Surface Difference工具是三者中可视化效果最好的一个。它把两个TIN直接做差,输出一组多面体要素,每一个多面体代表两个表面之间的一个差异块。属性表里记录了每个差异块的体积,正负表示方向,空间上能一眼看出哪个区域填方多、哪个区域挖方多。
操作路径是"3D Analyst工具"->"3D要素"->"表面差分"。输入表面选现状TIN,参考表面选设计TIN,输出要素类指定位置即可。工具参数里有个"Z容差",表示两个表面对齐时允许的误差范围,默认值0可以采用,但如果两个TIN的节点并不完全重合,可以适当稍微调大容差来消除很多细碎多边形。
这个工具在斜坡地和边坡分析时特别好用。普通场地平整因为填挖区边界通常就是一条等高线,Cut/Fill的栅格结果会出现锯齿状边界,而Surface Difference输出的是矢量多面体,边界顺滑得多,用于出图汇报效果好很多。
4.4 三种方式结果对不上时怎么排查
三个工具算出的结果不一致是常有的事,不必慌。我先说一下通常会差多少:对于一个5万平方米的场地,高差起伏正常的情况下,三种算法结果差距在3%以内都属于正常范围。如果差距超过5%,就得从这几个方向排查。
先查两个TIN的范围是否一致。如果现状TIN比设计TIN大了一圈,多出来的环形区域全是填方或挖方,体积自然就不一样。解决办法是用边界要素统一切割,把两边的计算范围对齐到同一个多边形。
再查栅格分辨率。Cut/Fill用1米分辨率和2米分辨率计算,结果差距主要取决于地形复杂的程度。用TIN转栅格后和原始TIN做一下体积对比,能看出你选的采样距离是否对原始地形损耗过大。
最后查坐标和单位。这个不用多解释了,前面说过,凡是体积差异大得离谱(比如差一个数量级),十有八九就是坐标系或单位出了问题。
5. 结果验证与可视化出图
算出来的数不能直接写到报告里,至少要做一个独立验证和一次可视化检查。我在实际项目中会用两种方法做交叉验证,互相对上了才敢签"建议采用"这几个字。
5.1 抽查验证:原型图斑上的填挖厚度
最直观的验证方法,是在场地上找一个你知道填挖方向的小区域,用"3D Analyst"工具里的"插值Z值"分别从现状面和设计面上提取该点的高程。两点的高程差就是该处的设计填挖厚度。
多点抽查之后,把每个抽查点的填挖厚度和从体积栅格里读出的像元值做个对比。比如在挖方区,抽查点计算的厚度是1.2米,体积栅格那个像元显示的等效厚度也应该是1.2米左右。如果某处对不上,顺着那个位置去看TIN三角网的形态,基本上能发现是坏点还是边界问题。
还有个更省事的检查办法:直接把设计DEM减去现状DEM,用栅格计算器得到一个填挖厚度栅格。这个厚度栅格里的正值和负值在空间上的分布,和Cut/Fill的结果应该是高度一致的。肉眼扫一眼分布形状就能判断大方向有没有搞错。
5.2 用体积守恒快速自检
当你算出了全场总挖方和总填方,可以做一个粗略的守恒检查。原理很简单:如果场地是封闭场地、没有外运土方的话,全场总挖方约等于总填方。当然实际情况里场地平整往往会外运或借土,总挖方和总填方不一定相等,但差值应该在合理范围内。
另一种自检方法是"平均厚度法":用总面积乘以平均填挖厚度,得到一个体积量级,然后和工具结果比。比如一块5万平方米的场地,总面积均匀填高0.5米,估算体积就是25000立方米左右。如果工具算出来的结果是1500立方米,那肯定哪里出了错;如果是24000到26000立方米,基本可信。
面积可以在面体积工具的输出要素表里直接读到,平均填挖厚度可以用栅格计算器统计,然后再乘起来。这个方法虽然粗糙,但用来筛掉明显的计算错误特别有效,我几乎每个项目都会做这一步。
5.3 把计算过程做成标准出图的几个建议
Arcmap算土方的另外一个好处是出图方便。拿到热搜词里"arcmap如何制图出图"我就多说几句。
填挖方结果出图时,我习惯做一个"填挖方分区图":用填充色把挖方区、填方区、无变化区分开,挖方区用红色系表示,填方区用蓝色系表示,透明度设置成50%左右,底下叠正射影像或地形图。图例、比例尺、指北针是标配,放在布局视图里调整。
还有一个细节:导出图片前一定要把图层符号化做干净,图斑之间不要出现颜色穿插。用Cut/Fill栅格直接出图时,因为栅格像元是规则的方形,边界会有锯齿感,建议先把栅格转成矢量面再出图。Surface Difference输出的多面体在ArcScene里看会有立体感,但平面出图时要把Faces转成MultiPatch再压平,或者直接用属性表里的体积字段做专题图。
导出分辨率设置为300dpi,格式选PDF或TIFF,方便直接放到报告里。如果要在CAD里套用边界,也可以把结果以shp格式单独导出。
6. 真实项目里最常见的五个坑
最后这部分是我这些年用Arcmap算土方量最想跟新手说的内容。很多问题不是算法问题,而是习惯问题。
6.1 单位不一致导致数量级错误
这个坑我见过太多次了。有人从CAD里导出等高线,Z值是以毫米为单位的,就这么稀里糊涂建了TIN,最后算出来的体积数据和施工方结算差了几百倍。还有人的设计图纸高程用米,现状点高程用厘米,建完两个TIN之后才发现坐标系都对但高程量纲不一致。
我在建TIN之前,会先把每个数据源的高程值范围列出来看一下,判断单位逻辑是否自洽。比如场地海拔大概在300米左右,那所有数据的Z值应该在300这个量级附近波动,如果有数据量级到了3万,那就肯定有问题。这个习惯帮我提前发现了很多次"低级"但致命的错误。
6.2 TIN边界锯齿和区域外插值
TIN在数据边缘的三角网往往会向外延伸,形成很大的扁三角形,这些三角形在高程上有时会突然抬升或下降,产生严重的边缘误差。如果计算区域边界没有硬性约束,这些边缘三角形会被计入体积,几万方的差值就出来了。
解决方法是把计算边界作为硬约束边加入TIN,或者在建完TIN之后用"裁剪TIN"把边界外的部分裁掉。另外在用Cut/Fill做栅格计算时,环境设置里记得把"处理范围"和"掩膜"设成计算边界面,这样输出栅格天然不会越界。
6.3 高程点在局部区域密度不足
有人拿外业记录的所有高程点直接建TIN,觉得点越多越好。但实际上,如果场地西南角的高程点间距是2米一个,东北角却是15米一个,那TIN在东北角的三角形面积要大得多,地形细节丢失严重。填方区如果正好在这个稀疏区域,计算结果偏差会非常大。
在建TIN之前可以先做个点密度分析,把密度明显不足的地方标出来。如果条件允许,补充测量;如果补不了,就在报告中明确说明该区域计算结果可信度较低。很多土方量的争议,最后都落在这些区域样本不足的问题上,提前说明是对自己负责。
6.4 填挖方方向搞反
这个说出来有点不好意思,但真发生过。填挖方工具输出的栅格属性值里,正值是填方还是挖方,不同版本不同数据情况下容易混淆。你辛辛苦苦算出来了,结果报告里把挖方写成填方,那就闹笑话了。
现在我每接到一批新数据,都会先圈出一小块看得到的区域做试算,比如场地里有个已知要挖掉的土堆,单独算一下它的体积,验证工具输出的正负是否符合预期。确认无误后,再跑全场的计算。这个步骤只需要几分钟,但能避免后面改报告时的几小时返工。
6.5 大范围栅格计算内存不足
范围特别大的项目,比如几个平方公里,用Cut/Fill做栅格计算时经常会出现"999999"错误或者程序崩溃。因为栅格计算是把整个范围内的每个像元都读进内存参与运算的,像元数量太大内存就吃紧。
解决方法是分块处理。按标准分幅或道路网格把大区域切分成若干块,对每一块单独算填挖方,最后汇总各块的体积。还有一个方案是先把TIN转栅格时的像元大小调大,比如从1米调整为2米或5米,计算量能下降很多,代价是精度也相应降低。这算是一个权衡,看项目要求来定。
我自己的操作习惯是:超过1平方公里的区域,先分地块进行计算,同一套参数同一套边界切分标准,最后在Excel里汇总,这样既保证了精度,又不会让Arcmap跑一个通宵然后崩溃。