Geoprocessor是ArcObjects SDK中定義Tool執行器。IGPProcess介面是ArcObjects SDK中定義的ArcTool介面。也就是說ArcObjects SDK定義的ArcTool都會繼承該介面實現。理論上,在ArcToolbox的出現的系統工具都應該可以在SDK中找到。
private static Geoprocessor _Geoprocessor = null; /// <summary> /// 實際的地理處理器 /// </summary> public Geoprocessor Geoprocessor { get { if (_Geoprocessor == null) { _Geoprocessor = new Geoprocessor { OverwriteOutput = true }; } return _Geoprocessor; } } public object ExecuteByGP(IGPProcess pGPProcess) { try { return Geoprocessor.Execute(pGPProcess, null); } catch { object mySeverity = null; string myMessage = Geoprocessor.GetMessages(ref mySeverity); throw new Exception(myMessage); } }
ArcToolBox的對應的類在SDK中找不到,我們一般從ArcMap上著手。首先先在ArcMap上的Toolbox中找到Buffer工具,並開啟。如下圖所示。
我們可以通過點選Tool Help按鈕,檢視該工具的具體用法。特別是引數說明部分。通過幫助中的資訊,分析出屬於那個dll檔案,如果沒有參照的話,參照下。如下圖所示。
後面有個Analysis,那麼該功能在ArcObjects SDK中是被定義在ESRI.ArcGIS.AnalysisTools.dll中的。例如Dissolve工具,後面的括號內是Data Management,那麼該工具被定義到了ESRI.ArcGIS.DataManagementTools.dll中。
using System.IO; using System.Reflection; using System.Xml; using ESRI.ArcGIS.Geoprocessor; namespace ESRI.ArcGIS.AnalysisTools { public class Buffer : IGPProcess { private object[] m_gpParameters; private string m_ToolboxDirectory; public object in_features { get { return m_gpParameters[0]; } set { m_gpParameters[0] = value; } } public object out_feature_class { get { return m_gpParameters[1]; } set { m_gpParameters[1] = value; } } public object buffer_distance_or_field { get { return m_gpParameters[2]; } set { m_gpParameters[2] = value; } } public string line_side { get { return m_gpParameters[3] as string; } set { m_gpParameters[3] = value; } } public string line_end_type { get { return m_gpParameters[4] as string; } set { m_gpParameters[4] = value; } } public string dissolve_option { get { return m_gpParameters[5] as string; } set { m_gpParameters[5] = value; } } public object dissolve_field { get { return m_gpParameters[6]; } set { m_gpParameters[6] = value; } } public string ToolboxDirectory { get { return m_ToolboxDirectory; } set { m_ToolboxDirectory = value; } } public string ToolboxName => "Analysis Tools.tbx"; public string ToolName => "Buffer"; public string Alias => "analysis"; public object[] ParameterInfo => m_gpParameters; public Buffer() { m_gpParameters = new object[7]; m_ToolboxDirectory = ResolveDirectory(); } public Buffer(object in_features, object out_feature_class, object buffer_distance_or_field) { m_gpParameters = new object[7]; m_ToolboxDirectory = ResolveDirectory(); this.in_features = in_features; this.out_feature_class = out_feature_class; this.buffer_distance_or_field = buffer_distance_or_field; } private string ResolveDirectory() { string result = "[SYSTEMTOOLBOXLOCATION]"; Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = executingAssembly.Location + ".config"; FileInfo fileInfo = new FileInfo(text); if (fileInfo.Exists) { XmlDocument xmlDocument = new XmlDocument(); xmlDocument.Load(text); XmlNode xmlNode = xmlDocument.SelectSingleNode("configuration/toolbox"); if (xmlNode != null) { result = xmlNode.Attributes["directory"].Value; } } return result; } } }
有些引數設定比較好理解,例如in_features,可以設定一個shape檔案路徑、IFeatureClass物件、IFeatureLayer物件或者.Lyr檔案路徑等。但為了執行穩定,保險期間,我一般都設定檔案路徑。
out_feature_class引數也比較好理解,設定一個輸出的Shape檔案路徑即可。
後面的line_side、line_end_type、dissolve_option都是字串型別的可選引數,這種一般還比較簡單寫,看幫助中的參數列部分,基本上可以解決我們的問題。
還有兩個引數buffer_distance_or_field和dissolve_field,這兩個比較難設定。dissolve_field還好,是一個可選引數,我之前也沒用過,可以先不管。但buffer_distance_or_field引數,看到這個名字就知道這個引數非常重要。按正常理解的話,這個引數應該是一個數位型別的引數,用來設定緩衝距離。我們再看下幫助是如何描述這個引數的。
這個欄位可識別的型別有欄位和線性單位,通過描述可以知道,引數可以傳數位+單位以及欄位名稱。如果只傳一個數位,那麼就按照該數位以及資料本身的單位進行緩衝區分析;如果傳數位+單位,就按照傳入的數位和單位進行緩衝區分析;如果傳欄位名稱,就按照該欄位的值進行緩衝區分析。就是說,我們設定數位100、字串」100 Meters」或者一個數位型別的欄位名稱均是可以的。
但如果傳欄位,欄位型別是字串,裡面的值為數位+單位的格式是否識別?或者該引數傳一個IField物件是不是可以識別?再或者欄位是數位型別,我們傳欄位名稱+單位是不是也可以?因為這些在實際應用中,沒有應用過,所以並沒有進行驗證。如果有需要這麼處理的,可以去驗證下。
如果還不知道這個引數如何引數,那麼還有一個更直觀的辦法。先用自己想設定的引數在ArcMap中執行一下。如下圖所示。
點選OK按鈕執行,之後後,去Toolbox的Result模組檢視執行的py指令碼。如下圖所示。
這樣我們是不是就可以知道buffer_distance_or_field引數要怎麼設定了?dissolve_field引數更復雜,但通過這樣的方法,也可以獲取該引數的設定格式。
Tool設定引數的時候,資料儘量用路徑,路徑儘量不要有漢字、空格等,傳入的引數路徑名稱儘量以字母開頭;
在程式碼中呼叫報錯,用同樣的資料、同樣的引數,在ArcMap裡面去執行一下,一般兩者是沒什麼差別的,在ArcMap找到什麼原因後,再去修改程式碼;