在ArcEngine时,GP无疑是GIS开发者的神器。自ArcEngine9.2开始新增一个程序集ESRI.ArcGIS.Geoprocessor,它能调用包含扩展模块在内的所有Geoprocessing工具。关于GP的使用问题,做如下总结:
1.许可问题
大家都知道,AE二次开发有两种许可定义方式:一是直接拖放License控件,右键设置其属性,另一种方式是使用IAoInitialize接口实现。但两者只需一种即可,建议使用后者。Program.cs文件Main函数中初始代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | //绑定Runtime if (!RuntimeManager.Bind(ProductCode.Engine)) { if (!RuntimeManager.Bind(ProductCode.Desktop)) { MessageBox.Show( "不能绑定ArcGIS Runtime,应用程序即将关闭!" ); return ; } } //初始化Advanced许可,还有Standard,Engine,Basic等 esriLicenseStatus licenseStatus = esriLicenseStatus.esriLicenseUnavailable; IAoInitialize m_AoInitialize = new AoInitialize(); licenseStatus = m_AoInitialize.Initialize(esriLicenseProductCode.esriLicenseProductCodeAdvanced); //检查扩展模块功能 licenseStatus = m_AoInitialize.CheckOutExtension(esriLicenseExtensionCode.esriLicenseExtensionCodeSpatialAnalyst); |
2.概念区分
Geoprocessor与Geoprocessing有什么区别?
Geoprocessing是GIS三大视角之一,能够通过分析处理已存在的数据,在新的数据集中产生结果。可以简单地理解为ToolBoxs中的工具。
Geoprocessor是ArcEngine9.2新增的一个基于NET Framework2.0的托管类,所有的Geoprocessing工具,包括扩展工具,都是由Geoprocessor对象调用运行,Geoprocessor能够通过设置不同的环境参数,简化执行Geoprocessing工具的过程,并返回相应的处理结果。(来看《插件式GIS应用框架的设计与实现——基于C#和ArcGIS Engine9.2》,这是一本不错的书!)
所以,一般地,在进行开发调用GP之前要添加Geoprocessor和Geoprocessing两个引用:
1 2 | using ESRI.ArcGIS.Geoprocessor; using ESRI.ArcGIS.Geoprocessing; |
3.寻找工具
在哪里去寻找我们需要的工具呢?
第一步,首先在ToolBox里找到要使用的工具,最好利用该工具测试一下实验数据,确保其正确性。工具右键属性可看到其英文名称。
第二步,去ESRI帮助中查找工具参数。在其中我们可以看到有哪些参数,分别是什么类型、含义,如果不知道怎么填写,可参考Python例子。
工具名称及对应命名空间:
AE/AO开发工具与全名空间对应表
工具名称 | 命名空间 |
3D Analyst tools | ESRI.ArcGIS.Analyst3DTools |
Analysis tools | ESRI.ArcGIS.AnalysisTools |
Conversion tools | ESRI.ArcGIS.ConversionTools |
Data Management tools | ESRI.ArcGIS.DataManagementTools |
Cartography tools | ESRI.ArcGIS.CartographyTools |
Coverage tools | ESRI.ArcGIS.CoverageTools |
Geocoding tools | ESRI.ArcGIS.GeocodingTools |
Geostatistical Analyst tools | ESRI.ArcGIS.GeostatisticalAnalystTools |
Linear Referencing tools | ESRI.ArcGIS.LinearReferencingAnalystTools |
Multidimension tools | ESRI.ArcGIS.MultidimensionTools |
Network Analyst tools | ESRI.ArcGIS.NetworkAnalystTools |
Samples | ESRI.ArcGIS.SamplesTools |
Spatial Analyst tools | ESRI.ArcGIS.SpatialAnalystTools |
Spatial Statistics tools | ESRI.ArcGIS.SpatialStatisticsTools |
第三步,查看它在哪个工具大类下,添加对应的引用,设置参数,调试运行即可。下表是EsriLicenseProduct,关于扩展许可详见esriLicenseExtensionCode
许可 | 代码 | 描述 |
esriLicenseProductCodeEngine | 10 | Engine Product Code |
esriLicenseProductCodeEngineGeoDB | 20 | Engine Enterprise GeoDatabase |
esriLicenseProductCodeArcServer | 30 | ArcServer Product Code |
esriLicenseProductCodeBasic | 40 | Basic Product Code |
esriLicenseProductCodeStandard | 50 | Standard Product Code |
esriLicenseProductCodeAdvanced | 60 | Advanced Product Code |
4.调用方式
以使用Buffer为例,调用GP实现缓冲区分析的方式:
方式一:实例化GP对象
1 2 3 4 5 6 7 8 9 | //初始化GP Geoprocessor GP = new Geoprocessor(); //初始化Buffer ESRI.ArcGIS.AnalysisTools.Buffer buffer = new ESRI.ArcGIS.AnalysisTools.Buffer(); buffer.in_features = @"D\data\temp.gdb\road" ; buffer.out_feature_class = @"D\data\temp.gdb\road_bf30" ; buffer.buffer_distance_or_field = 30; //默认单位 //执行工具 GP.Execute(buffer, null ); |
方式二:VariantArray传递参数
1 2 3 4 5 6 7 8 | Geoprocessor GP = new Geoprocessor(); GP.AddToolbox( @"C:\Program Files (x86)\ArcGIS\Desktop10.1\ArcToolbox\Toolboxes\Analysis Tools.tbx" ); //使用IVariantArray传递参数 IVariantArray array = new VarArrayClass(); array.Add( @"D\data\temp.gdb\road" ); array.Add( @"D\data\temp.gdb\road_bf30" ); array.Add(30); GP.Execute( "Buffer" , array, null ); |
当然,定义GP对象也有两种方法:一是通过引用ESRI.ArcGIS.Geoprocessing命名空间,使用IGeoProcessor2接口定义,注意其中的P是大写;二是使用Geoprocessor类。
1 2 | private static IGeoProcessor2 GP = new GeoProcessorClass(); // using ESRI.ArcGIS.Geoprocessing; private static Geoprocessor GP = new Geoprocessor(); // using ESRI.ArcGIS.Geoprocessor; |
5.调试函数
如果参数设置正确,能够输出想要的结果,如果设置错误,则不能输入结果,也不知哪里错了,这是写了一个调试的函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | /// <summary> /// 执行GP /// </summary> /// <param name="mGP">GP对象</param> /// <param name="process">GP工具</param> /// <param name="TC"></param> /// <returns>处理结果</returns> public static IGeoProcessorResult Execute(Geoprocessor mGP, IGPProcess process, ITrackCancel TC) { tGeoResult = null ; mGP.OverwriteOutput = true ; // 是否覆盖 try { tGeoResult = (IGeoProcessorResult)mGP.Execute(process, null ); ReturnMessages(mGP); } catch (System.Exception ex) { MessageBox.Show(ex.Message+ "\n\n" +ex.StackTrace); ReturnMessages(mGP); //当调试正确后注释本行 } return tGeoResult; } private static void ReturnMessages(Geoprocessor gp) { string ms = "" ; if (gp.MessageCount > 0) { for ( int Count = 0; Count <= gp.MessageCount - 1; Count++) { ms += "$" + gp.GetMessage(Count) + "\n\n" ; } } MessageBox.Show(ms); } |
修改GP的执行:
1 2 | //执行工具 Execute(GP,buffer, null ); // GP.Execute(buffer, null); |
6.运行结果
除了使用IGeoProcessorResult接口获取GP处理结果外,还可以直接将GP的输出结果写入FeatureClass中,方便进行使用。
IGeoProcessorResult的一个重要属性是ReturnValue,用于返回执行结果,使用示例:
1 2 | IGeoProcessorResult result=Execute(GP,buffer, null ); IFeatureClass mFeatureClass=GP.Open(result.ReturnValue); |
7.设置环境
每个GP工具都有自己的执行参数,其中有些参数是很工具都有的,如容差、输入、输出位置都是有的,像ArcMap中一样,在进行地理处理前要进行环境的设置。
使用setEnvironmentValue方法来设置环境变量的值,使用getEnvironmentValue方法来获取当前环境变量的值。例如:
1 2 3 4 5 6 7 | //获取和设置环境:单元格大小 String env = (String) gp.getEnvironmentValue( "cellsize" ); GP.setEnvironmentValue( "cellsize" , Double.valueOf(10.0)); // 设置输出坐标系统 gp.setEnvironmentValue( "outputCoordinateSystem" , "c:/Program Files/ArcGIS/Coordinate Systems/Projected Coordinate Systems/UTM/Nad 1983/NAD 1983 UTM Zone 21N.prj" ); // 重置 GP.resetEnvironments(); |
8.批量处理
GeoProcessor类为我们提供了一些提取数据的方法,即通过list来获取数据库中数据名称,结果是字符串,通过获取的路径再进行GP调用等操作:
listDatasets (string wildCard, string datasetType)
listFeatureClasses (string wildCard, string featureType, string dataset)
listRasters (string wildCard, string rasterType)
listTables (string wildCard, string tableType)
listToolboxes(string wildCard)
listWorkspaces (string wildCard, string workspaceType)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /// <summary> /// 要素筛选 /// </summary> /// <param name="filePath">数据库位置</param> /// <param name="featureType">文件类型,可填写Point,Polyline,Polygon等</param> /// <param name="wildCard">扩展通配符</param> /// <param name="dataset">要素集</param> /// <returns></returns> public static List< string > FeatureClassFilter( string filePath, string wildCard, string featureType, string dataset) { lstWorkspace.Clear(); GP.SetEnvironmentValue( "workspace" , filePath); IGpEnumList featureClasses = GP.ListFeatureClasses(wildCard,featureType,dataset); string featureClass = featureClasses.Next(); while (featureClass!= "" ) { lstWorkspace.Add(featureClass.ToString()); featureClass = featureClasses.Next(); } return lstWorkspace; } |
调用方法:
1 | FeatureClassFilter( @"D\data\temp.gdb" , "P*" , "poInt" , "net" ); |
此句的含义是遍历获取temp.gdb中net数据集下名为p开头的点层要素。
当然也可以通过IGPUtilities类直接打开要素层或要素类等。
1 | IFeatureClass mFeatureClass=gpUtilities.OpenFeatureClassFromString(dataPath); |
9.注意事项
(1)数据的测试
GP工具对输入、输出参数要求严格,因此首先要保证数据没有问题,可以先在ArcGIS中调用ArcToolBox进行操作,如果能正常执行,则说明数据基本没有问题。除数据本身名,还要注意数据的命名(不要出现中文的符号)、使用权限等问题。
(2)参数有多个值的设置
有的GP工具有多个输入,如联合(Union),如将数据库中的P1和P2进行联合操作,其输入要素要用分号隔开。
1 | union.in_features = @"D\temp.gdb\P1;D\temp.gdb\P2" ; |
如果已设置GP的默认数据库,可直接写成如下形式:
1 | union.in_features = " P1; P2" ; |
(3)"重分类"分类表设置
有的GP工具参数比较特殊,需要进行特别处理,可参考帮助文档中Python示例,如重分类工具,其重分类表参数设置如下:
1 2 3 4 | Reclassify rc = new Reclassify(); rc.reclass_field = "Value" ; rc.remap = "0.0 2.0 1; 2.0 2.5 2; 2.5 3.0 3 " ; …… |
即将原来的0-2重分类为1,原来2-2.5重分类为2,原来2.5-3重分类为3,同一类别的上限和下限用空格隔开,不同类别用分号隔开。
(4)"添加XY数据"的查找
我们经常将文本文件中的坐标数据转到ArcMap中的点,需要使用 "添加xy数据"工具,通常会选择"文件"-"添加数据"-"添加XY数据",这时,它属性哪个工具箱的呢?可以通过搜索的功能来查找它应该引用的类库。它在ToolBox中叫"创建XY事件图层"。当然,有些工具ToolBox是没有的,再怎么搜索也找不到,如"文件"-"共享为"-"服务"。
(5)"添加XY数据"的输出
工具"添加XY数据"的输出比较特殊,由此工具创建的是临时图层,需要保存,在ArcMap中右键导出结果即可,在ArcEngine中调用GP工具CopyFeatures(复制要素),FeatureToPoint(要素转点)或FeatureClassToFeatureClass(要素类转要素类)可导出为对应的图层。
(6)OpenRasterLayerFromString
IGPUtilities接口的OpenRasterLayerFromString函数总是不能得到结果,所以,只能使用IWorkspaceFactory接口来打开数据库中的栅格数据。示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | /// <summary> /// 打开栅格 /// </summary> /// <param name="path">文件路径</param> /// <param name="name">文件名</param> /// <returns>栅格图层</returns> public static IRasterLayer GetRater( string path, string name) { IWorkspaceFactory mWSF = new RasterWorkspaceFactoryClass(); IRasterWorkspace mRasterWorkspace = mWSF.OpenFromFile(path, 0) as IRasterWorkspace; IRasterDataset mRasterDataset = mRasterWorkspace.OpenRasterDataset(name); //创建rasterlayer从RasterDataset IRasterLayer mRasterLayer = new RasterLayerClass(); mRasterLayer.CreateFromDataset(mRasterDataset); return mRasterLayer; } |
(7)参数值的灵活设置
在使用ArcMap中的工具时,有的工具参数需要灵活的设置,不能固化。
如做缓冲区分析,缓冲的半径为图层范围最大值,不同的图层,其值则不相同,所以,读取到变量中,再进行缓冲区分析。
1 2 3 4 5 6 7 8 9 10 11 12 13 | private void BufferBounding500() { //读取范围,设置半径 IGeoDataset pGeodataset = gpUtilities.OpenFeatureClassFromString(gdbPath + filename+ "_xy" ) as IGeoDataset; IEnvelope pEnvelope = pGeodataset.Extent; double distance = Max(pEnvelope.XMax - pEnvelope.XMin, pEnvelope.YMax - pEnvelope.YMin); //缓冲区分析 ESRI.ArcGIS.AnalysisTools.Buffer bf = new ESRI.ArcGIS.AnalysisTools.Buffer(); bf.in_features = gdbPath + fileName + "_sp" ; bf.buffer_distance_or_field = distance + " Degrees" ; //注意设置缓冲半径的单位 bf.out_feature_class = gdbPath + fileName + "_bf500" ; RunGPTool(GP, bf, null ); } |
再如,做Kriging插值时,其参数"输出单元格大小"默认情况下是插值点范围的最大值除以250,但在实际中,这样的插值结果显示效果不很理想,因此,一般都是改为除以2500才比较合适。当然输出单元格大小越小,使用的内存和耗时就更多!
(8)裁剪栅格的范围参数
裁剪栅格Clip的rectangle参数需要设置为输出范围图层的四至。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | private void ClipRaster() { IGeoDataset pGeodataset = gpUtilities.OpenFeatureClassFromString(gdbPath + fileName + "_ clip" ) as IGeoDataset; IEnvelope pEnvelope = pGeodataset.Extent; //顺序:X 最小值、Y 最小值、X 最大值和 Y 最大值 string strEnvelope = pEnvelope.XMin.ToString() + "" + pEnvelope.YMin.ToString() + "" + pEnvelope.XMax.ToString() + "" + pEnvelope.YMax.ToString(); ESRI.ArcGIS.DataManagementTools.Clip cp = new ESRI.ArcGIS.DataManagementTools.Clip(); cp.in_raster = gdbPath + fileName + "_krg" ; cp.in_template_dataset = gdbPath + fileName + "_ clip" ; cp.rectangle = strEnvelope; cp.clipping_geometry = "true" ; cp.out_raster = gdbPath + fileName + "_re" ; RunGPTool(GP, cp, null ); } |
(9)按位置选择
按位置选择工具的输入必须是要素图层;不可以是要素类。所在在调用工具之前,需要先使用MakeFeatureLayer来创建要素图,详见:GP开发示例:数据库去重
作者:我也是个傻瓜
出处:http://www.cnblogs.com/liweis/
签名:成熟是一种明亮而不刺眼的光辉。