本文提供使用IMapAlgebraOp接口实现大部分栅格计算的简单方法。
1.首先,ArcObjects提供了很多关于栅格计算的方法,有条件运算、逻辑运算及数学表达式,如下:
开发的过程中如果为每个计算都写一个方法,那实在是太累了,而且还不如手动在ArcMap里面点击工具,说到工具,想起ArcToolbox的Map Algebra/Raster Calculator可以实现大部分栅格相关的运算。
Raster Calculator工具界面
通过界面发现,不仅有简单的+ - * /、逻辑后面的框里面还有大量函数,功能很强大。那就看看ArcObjects提供的相应接口吧 !
找到IMapAlgebraOp Interface,
可怜的三个方法,能支持大部分运算吗?
阅读一下方法说明,
BindRaster,两个参数IGeoDataset geoDataset,String symbol,把geoDataset绑定到symbol,即给栅格数据起别名,方便使用
UnbindRaster,取消绑定
Execute,只有一个string类型参数,但这个参数可以是任意符合Map Algebra的表达式!也就是可以执行很多上面的运算。
强大的东西有种简洁的美。
2.牛刀小试
创建一个MapAlgebra方法,接收三个参数:一个IGeoDataset栅格数据pGeoDataset,一个string的别名symbol,一个string的表达式expression;
功能:把pGeoDataset绑定到symbol,执行expression,取消绑定,返回执行结果。
1 public static IGeoDataset MapAlgebra(IGeoDataset pGeoDataset, string symbol, string expression) 2 { 3 try 4 { 5 IMapAlgebraOp pMapAlgebraOp = new RasterMapAlgebraOp() as IMapAlgebraOp; 6 pMapAlgebraOp.BindRaster(pGeoDataset, symbol); 7 IGeoDataset resDataset = pMapAlgebraOp.Execute(expression); 8 pMapAlgebraOp.UnbindRaster(symbol); 9 return resDataset; 10 } 11 catch (Exception e) 12 { 13 throw e; 14 } 15 }
调用,对一个栅格数据执行Int运算:
1 IGeoDataset pGeoDatasetInt = GeoAnalyst.MapAlgebra(pGeoDataset, "inRaster", "Int([inRaster])");
说明:表达中需要用" [ ] " 把symbol括起来。
再试一个 “ * ” 乘法运算:
1 IGeoDataset pGeoDatasetTimes = GeoAnalyst.MapAlgebra(pGeoDatasetTimes, "inRaster", "[inRaster]*100");
运行,报错 ERROR 010316: Unable to open the input raster
查找既没发现文件占用,也没发现表达式有问题,在ArcMap里面同样的计算也能执行,最后经多方查找发现操作符前后需要留有空格,也即是如下:
1 IGeoDataset pGeoDatasetTimes = GeoAnalyst.MapAlgebra(pGeoDatasetTimes, "inRaster", "[inRaster] * 100");
至此,完美解决。
等等,如果有多个栅格输入呢,总不能一直增加参数个数吧。其实,栅格增加一个,symbol增加一个,expression的数量还是一个,
可以构建一个实体,包含栅格和symbol两个属性,把他们放入一个列表中,这样就可以应对多个栅格数据的情况了。
修改MapAlgebra方法如下:
1 public static IGeoDataset MapAlgebra(ListpDatasetWithSymbolList, string expression) 2 { 3 try 4 { 5 IMapAlgebraOp pMapAlgebraOp = new RasterMapAlgebraOp() as IMapAlgebraOp; 6 7 foreach (DatasetWithSymbol item in pDatasetWithSymbolList) 8 { 9 pMapAlgebraOp.BindRaster(item.PGeoDataset, item.Symbol); 10 } 11 IGeoDataset resDataset = pMapAlgebraOp.Execute(expression); 12 foreach (DatasetWithSymbol item in pDatasetWithSymbolList) 13 { 14 pMapAlgebraOp.UnbindRaster(item.Symbol); 15 } 16 return resDataset; 17 } 18 catch (Exception e) 19 { 20 throw e; 21 } 22 }
它接收一个包含栅格和symbol两个属性的实体列表,循环做BindRaster,执行后再UnbindRaster。
实体如下:
1 public class DatasetWithSymbol 2 { 3 public DatasetWithSymbol(IGeoDataset pGeoDataset, string symbol) 4 { 5 this.pGeoDataset = pGeoDataset; 6 this.symbol = symbol; 7 } 8 9 IGeoDataset pGeoDataset; 10 string symbol; 11 12 public IGeoDataset PGeoDataset 13 { 14 get 15 { 16 return pGeoDataset; 17 } 18 19 set 20 { 21 pGeoDataset = value; 22 } 23 } 24 25 public string Symbol 26 { 27 get 28 { 29 return symbol; 30 } 31 32 set 33 { 34 symbol = value; 35 } 36 } 37 }
使用方法如下:
1 DatasetWithSymbol pDatasetWithSymbol = new DatasetWithSymbol(pRasterDataset as IGeoDataset, "inRaster"); 2 ListpDatasetWithSymbolList = new List (); 3 pDatasetWithSymbolList.Add(pDatasetWithSymbol); 4 IGeoDataset pGeoDatasetTimes = GeoAnalyst.MapAlgebra(pDatasetWithSymbolList, "[inRaster] * 100");
这样只要表达式配合好,添加多个栅格都不成问题。
结束,欢迎留言交流~