利用兩期地表DEM數據計算工程土方量需要準許以下數據:
當前地圖有3個圖層,兩個柵格圖層和一個矢量圖層
兩個柵格圖層:beforeDem為工程施工前的地表DEM模型
? ? ? ? ? ? ? ? ? ? ? ? ?afterDem為工程施工后的地表DEM模型
一個矢量圖層:pFeatureLayer
第一步生成掩膜:面轉柵格 conversion.PolygonToRaster 生產名稱為“poly”的柵格數據。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?OID為pFeatureLayer的字段
pFeatureLayer = PMap.FindLayers(ComboBox4.Text).FirstOrDefaultIf pFeatureLayer IsNot Nothing ThenGoTo qqwwDim maskRaster As String = Path.Combine(Project.Current.DefaultGeodatabasePath, $"poly")va = Geoprocessing.MakeValueArray(pFeatureLayer, "OID", maskRaster) ' 直接傳遞環境參數列表Dim result = Await Geoprocessing.ExecuteToolAsync("PolygonToRaster_conversion", va)If result.IsFailed ThenThrow New Exception($"掩膜生成失敗: {String.Join(vbCrLf, result.ErrorMessages)}")End If
第二步生成掩膜:按掩膜提取分別生成兩個柵格圖層
? ? ? ? ? ? ? ? ? ? ? ? ? before_clipped:為工程施工前的地表DEM的提取模型
? ? ? ? ? ? ? ? ? ? ? ? ? after_clipped ? :為工程施工后的地表DEM的提取模型
Dim outputName As StringDim inputRaster As StringDim outputPath As StringDim envSettings = New List(Of KeyValuePair(Of String, Object))For i = 1 To 2If i = 1 Then inputRaster = beforeDem : outputName = "before_clipped"If i = 2 Then inputRaster = afterDem : outputName = "after_clipped"'直接傳遞環境參數列表envSettings = New List(Of KeyValuePair(Of String, Object)) From {New KeyValuePair(Of String, Object)("cellSize", "MAXOF"), New KeyValuePair(Of String, Object)("template", inputRaster)}outputPath = Path.Combine(Project.Current.DefaultGeodatabasePath, outputName)Dim extractParams = Geoprocessing.MakeValueArray(inputRaster, maskRaster, outputPath, "INSIDE")result = Await Geoprocessing.ExecuteToolAsync("ExtractByMask", extractParams) 'ExtractByMaskIf result.IsFailed ThenMsgBox(inputRaster & "柵格按掩膜提取失敗")End IfNext
第三步CutFill分析:執行CutFill分析,分析結果生成分析柵格數據CutFill_Result
'1. 裁剪DEM到指定范圍Dim clippedBefore = Path.Combine(Project.Current.DefaultGeodatabasePath, "before_clipped")Dim clippedAfter = Path.Combine(Project.Current.DefaultGeodatabasePath, "after_clipped")'2. 執行CutFill分析outputName = "CutFill_Result"outputPath = System.IO.Path.Combine(Project.Current.DefaultGeodatabasePath, outputName)Dim parameters = Geoprocessing.MakeValueArray(clippedBefore, clippedAfter, outputPath, "METER")result = Await Geoprocessing.ExecuteToolAsync("CutFill", parameters)If result.IsFailed ThenThrow New Exception($"CutFill分析失敗: {String.Join(vbCrLf, result.ErrorMessages)}")End If
第四步分析成果按屬性提取:ExtractByAttributes,提取的數據仍然為柵格數據
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?屬性提取Where 子句使用 SQL 查詢?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"VOLUME < 0" ?填方
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"VOLUME > 0" ?挖方
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"VOLUME = 0" ?未變化
? ? ? ?輸出柵格的屬性表用于確定顯示方式,并且分別將正體積和負體積視為挖出材料的位置(已移除)和填充材料的位置(已添加)。
' 計算挖方量
Dim cutParams = Geoprocessing.MakeValueArray(cutFillRasterPath, "VOLUME > 0", GeodaPath & "\WFMJ") '按屬性提取
gpResult = Await Geoprocessing.ExecuteToolAsync("ExtractByAttributes", cutParams)
If gpResult.IsFailed ThenMsgBox("挖方區域提取失敗.")
End If' 計算填方量Dim fillParams = Geoprocessing.MakeValueArray(cutFillRasterPath, "VOLUME < 0", GeodaPath & "\" & "TFMJ") '按屬性提取gpResult = Await Geoprocessing.ExecuteToolAsync("ExtractByAttributes", fillParams)If gpResult.IsFailed ThenMsgBox("填方區域提取失敗.")End If' 計算未變化方量Dim wbhParams = Geoprocessing.MakeValueArray(GeodaPath & "\" & cutFillRasterPath, "VOLUME = 0", GeodaPath & "\" & "WBHMJ")gpResult = Await Geoprocessing.ExecuteToolAsync("ExtractByAttributes_management", wbhParams)If gpResult.IsFailed ThenMsgBox("未變化區域提取失敗.")End If
第五步獲取柵格數據屬性如:
- x 方向上的像元大小—x 方向上的像元大小。
- y 方向上的像元大小—y 方向上的像元大小。
va = Geoprocessing.MakeValueArray("TFMJ", {"CELLSIZEX", "CELLSIZEY"})gpResult = Await Geoprocessing.ExecuteToolAsync("management.GetRasterProperties", va)If gpResult.IsFailed ThenMsgBox("柵格數據屬性提取失敗.")End If
第六步分析柵格數據屬性表訪問Attributes:
TryAwait QueuedTask.Run(Sub()' 獲取柵格數據集Dim raster As Raster = rasterLayer.GetRaster()If raster Is Nothing Then Return' 正確檢查屬性表的方法Dim hasTable As Boolean = FalseTry' 嘗試獲取屬性表Using table As Table = raster.GetAttributeTable()hasTable = True' 獲取字段信息'Dim fields As IReadOnlyList(Of Field) = table.GetDefinition().GetFields()'Dim fieldNames As String = String.Join(", ", fields.Select(Function(f) f.Name))'MessageBox.Show($"找到屬性表,包含字段: {fieldNames}")Dim tabrow = table.Search(Nothing, False)Do While tabrow.MoveNext'訪問屬性表 LoopEnd UsingCatch ex As Exception When TypeOf ex Is NotSupportedException OrElseTypeOf ex Is InvalidOperationException' 捕獲不支持屬性表的異常hasTable = FalseEnd TryIf Not hasTable ThenMessageBox.Show("該柵格沒有屬性表")End IfEnd Sub)Catch ex As ExceptionMessageBox.Show($"訪問屬性表時出錯: {ex.Message}")End Try
如果只需要計算方量,第四步、第五步可省略。
運行后,可得: