ArcGIS Engine中如何調用GP工具(二)

上一篇文章最後提到過GP工具的許可,這篇文章就詳細講解一下調用GP工具的許可問題,這也是Engine中調用GP工具出錯最多的一類問題。除此之外,再介紹一下Engine中如何設置環境變量以及如何調用後臺64位GP。首先看下最最重要的許可問題。

一、許可問題

ArcGIS按產品來說可以分爲ArcGIS Desktop以及ArcGIS Engine(當然還包括ArcGIS Server、Portal for ArcGIS以及ArcGIS Runtime等,由於本文不涉及就不介紹了),這二者都是基於ArcObjects組件開發的產品。Desktop產品的許可分爲三個級別,即Basic、Standard以及Advanced;Engine產品的許可分爲兩個級別,即Engine許可以及Engine + Geodatabase Update擴展許可(簡稱EngineGeoDB許可)。AO幫助中說明了Engine許可相當於Desktop的Basic許可級別,而EngineGeoDB許可則相當於Desktop的Standard許可級別。

這裏寫圖片描述

Tips:至於Basic許可和Standard許可的區別(其實等同於Engine和EngineGeoDB許可的區別)可以參考Desktop help中ArcGIS for Desktop Basic and the geodatabase

爲什麼說上面一堆感覺無關主題的話呢,是因爲每個GP工具都有其相應的許可級別,Basic級別能調用的工具用Engine許可就可以調用,Standard級別能調用的工具用EngineGeoDB許可就可以調用,而只有Advanced級別能調用的工具Engine產品是無法調用的。具體可以在ArcMap中打開該工具,點擊GP對話框右下角的Tool Help,第一行就是該工具的License Level,如Buffer工具:

這裏寫圖片描述

前面小方框中打鉤就是說該許可級別可以調用,不打鉤就是無法調用,而小方框中畫黑色方框就是說使用過程中有限制,在工具幫助中會有相應說明,如:

這裏寫圖片描述

也就是說如果要將line_side設爲Left,Right等使用Engine許可或者EngineGDB許可是不行的。

再比如ExtractByMask工具,其License Level:

這裏寫圖片描述

最下方一行有說明,該工具需要Spatial Analyst擴展許可。

這裏寫圖片描述

也就是說Engine程序中需要檢出Spatial Analyst擴展許可才能執行該工具。有兩種方式檢出擴展許可:

一是使用LicenseControl控件:

選中LicenseControl控件,右鍵選擇屬性,在彈出窗體右側的Spatial Analyst方框處打鉤;

二是使用AO代碼檢出擴展許可:

ao.CheckOutExtension(esriLicenseExtensionCode.esriLicenseExtensionCodeSpatialAnalyst);

再比如Erase工具:

這裏寫圖片描述

只能Advanced許可才能調用,也就是Engine或EngineGeoDB許可無法調用該工具。但有的用戶說了,我就想在程序中調用Erase工具怎麼辦?辦法是有,但是有前提:首先機器上安裝了Desktop產品,並且授權了Advanced許可;其次是程序界面不能使用MapControl、TOCControl、ToolBarControl等控件,原因在於任何接口都有其適用的產品,比如IMapControl控件,AO幫助中明確說明只能在ArcGIS Engine產品下使用:

這裏寫圖片描述

所以如果想要調用Erase工具,而原有工程中使用了MapControl等控件的話,建議另外新建工程綁定Desktop產品(最好不要使用EngineOrDesktop,不然如果機子上安裝了Engine會默認綁定Engine產品),代碼中初始化Advanced許可,如下:

ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.Engine);
ESRI.ArcGIS.esriSystem.IAoInitialize ao = new ESRI.ArcGIS.esriSystem.AoInitialize();            ao.Initialize(ESRI.ArcGIS.esriSystem.esriLicenseProductCode.esriLicenseProductCodeAdvanced);

這裏做一下提醒:如果程序中初始化了Advanced許可,給客戶部署時也要求部署機上有該許可。

有一點很重要放在最後:一個程序中只能使用一種方式初始化一次許可。什麼意思呢?包含兩層意思:一是LicenseControl控件(左側單選,右側多選)和AO代碼初始化許可兩種方式只能選擇一種,不然如果兩種方法都用了但初始化的許可不一樣,程序無法判斷到底使用什麼許可;二是不要初始化多次許可,比如初始化過一次Engine許可,後來又初始化了EngineGeoDB許可,同樣,程序中也無法判斷。舉個例子,比如用戶調用SimplifyLine_cartography工具(該工具Basic許可無法調用),一直報沒有許可錯誤,但是用戶一口咬定就是初始化的EngineGeoDB許可,那怎麼還會報許可錯誤呢,查找原因就是因爲其初始化了兩次許可,而且還不一樣導致。

二、如何設置環境變量?

GP工具有些通用的屬性,當一個工具執行時,當前環境中的某些設置被當作全局輸入參數,例如Extent、輸出數據的座標系、新生成柵格數據的像元大小等等,都可以在環境變量中設置。

1,設置環境變量

所有環境變量名稱都用string表示,並且不區分大小寫,即”workspace”和”Workspace”均可。下面是一些常用變量的寫法:

設置workspace:

gp.SetEnvironmentValue("workspace", @"C:\data\saltlake.gdb");

設置extent:

gp.SetEnvironmentValue("extent", "-3532000, -911000, -3515000, -890000");

設置輸出座標系:

gp.SetEnvironmentValue("outputCoordinateSystem", @"…\NAD 1983 UTM Zone 11N.prj");
或者
gp.SetEnvironmentValue("outputCoordinateSystem",   "PROJCS['NAD_1983_UTM_Zone_11N',GEOGCS['GCS_North_American_1983',DATUM['D_North_American_1983',SPHEROID['GRS_1980',6378137.0,298.257222101]],PRIMEM['Greenwich',0.0],UNIT['Degree',0.0174532925199433]],PROJECTION['Transverse_Mercator'],PARAMETER['False_Easting',500000.0],PARAMETER['False_Northing',0.0],PARAMETER['Central_Meridian',-117.0],PARAMETER['Scale_Factor',0.9996],PARAMETER['Latitude_Of_Origin',0.0],UNIT['Meter',1.0]]");

設置Mask:

gp.SetEnvironmentValue("mask", @"E:\ZhuXinying\testData\Data.gdb\polygonMask");

2,獲取當前環境變量的值並重置到原始狀態

// Get the cell size environment value.
object env = gp.GetEnvironmentValue("cellsize");
// Reset the environment values to their defaults.
gp.ResetEnvironments();

3,將設置的環境變量保存爲.xml,後續使用的話可以直接加載:

gp.SetEnvironmentValue("workspace", @"C:/data/mydata.gdb");
gp.SetEnvironmentValue("extent", "-3532000, -911000, -3515000, -890000");
// Save environment settings to an XML file.
string settingsFile = @"C:\sdk\MyCustomSettings.xml";
gp.SaveSettings(settingsFile);
// Load previously saved environment settings.
gp.LoadSettings(settingsFile);
object sExtent = gp.GetEnvironmentValue("workspace");

詳細信息可以參考Using environment settings

三、如何調用後臺GP?

不知您是否注意到ArcGIS Engine安裝光盤裏有這樣一個安裝包:

這裏寫圖片描述

這個安裝包就是Engine的後臺64位GP工具包,該包是在ArcGIS Engine 10.1 SP1中開始出現的,只能安裝在64位機子上,安裝後會在Engine的安裝目錄下多一個bin64的目錄(後臺執行應該使用的是這裏的dll),在使用Geoprocessor.ExecuteAsync異步執行GP工具時調用。

相關事件:

1,ExecuteAsync方法是提交工具到當前進程已存在的geoprocessing隊列中,當後臺執行到這個工具時會觸發ToolExecuting事件,這時該工具的IGeoProcessorResults.Status屬性變爲esriJobStatus.esriJobWaiting。該事件所有工具都會觸發。

2,在工具執行過程中能觸發MessagesCreated和ProgressChanged事件,這些事件依賴於所使用的工具以及工具處理的數據量。

3,當工具執行完成時觸發ToolExecuted事件,該事件所有工具執行結束時都會觸發。

4,模型工具可以看作單一工具,觸發ToolExecuting以及ToolExecuted事件,MessagesCreated事件描述模型中每一個工具的進度。

5,工具可以在任何時刻取消,調用IGeoProcessorResult2.Canael()即可,取消後其狀態變爲esriJobStatus.esriJobCancelled。當工具執行失敗時,返回esriJobStatus.esriJobFail。

下面看下具體實現:

Geoprocessor gp = new Geoprocessor();
gp.OverwriteOutput = true;
gp.ToolExecuting += new EventHandler<ESRI.ArcGIS.Geoprocessor.ToolExecutingEventArgs>(gpToolExecuting);
gp.ProgressChanged += new EventHandler<ESRI.ArcGIS.Geoprocessor.ProgressChangedEventArgs>(gpProgressChanged);
//Register to receive the geoprocessor event when the tools have completed execution.
gp.ToolExecuted += new EventHandler<ESRI.ArcGIS.Geoprocessor.ToolExecutedEventArgs>(gpToolExecuted);

// Create a variant array to hold the parameter values.
IVariantArray parameters = new VarArrayClass();
// Populate the variant array with parameter values.
parameters.Add(FileGDBPath + "\\testPoint_10w");
parameters.Add(FileGDBPath + "\\testPoint_10w_Copy");
IGeoProcessorResult2 gpResult = gp.ExecuteAsync("CopyFeatures_management", parameters) as
                IGeoProcessorResult2;
public void gpToolExecuting(object sender, ToolExecutingEventArgs e)
{
  IGeoProcessorResult2 result = e.GPResult as IGeoProcessorResult2;
            //Determine if this is the tool to handle this event.
            if (result.Process.Tool.Name.Equals("CopyFeatures_management") && result.GetInput(0)
                .GetAsText().Equals(FileGDBPath + "\\testPoint_10w") && result.GetOutput(0)
                .GetAsText().Equals(FileGDBPath + "\\testPoint_10w_Copy"))
            {
                //Application specific code.
            }
        }
 public void gpProgressChanged(object sender, ESRI.ArcGIS.Geoprocessor.ProgressChangedEventArgs e)
        {
            System.Windows.Forms.ProgressBar progressBar = progressBar1;
            IGeoProcessorResult2 gpResult = (IGeoProcessorResult2)e.GPResult;
            switch (e.ProgressChangedType)
            {
                case (ProgressChangedType.Show):
                    //The tool that is running reports progress or has stopped reporting progress; make the 
                    // progress bar visible if appropriate. 
                    //progressBar.Visible = e.Show;
                    break;
                case (ProgressChangedType.Message):
                    //The application does not use these, since a tool being used reports percentage progress.
                    break;
                case (ProgressChangedType.Percentage): progressBar.Value = (int)
                    e.ProgressPercentage;
                    break;
                default:
                    throw new ApplicationException(
                        "unexpected ProgressChangedEventsArgs.ProgressChangedType");
                    break;
            }
        }
public void gpToolExecuted(object sender, ToolExecutedEventArgs e)
        {
            IGeoProcessorResult2 result = e.GPResult as IGeoProcessorResult2;
            if (result.Status.Equals(esriJobStatus.esriJobSucceeded))
            {
                //Check that there are no information or warning messages.
                if (result.MaxSeverity == 0)
                {
                    //Get the return value.
                    object returnValue = result.ReturnValue;
                    //Application specific code, 
                    //for example, find the layer to which this return value corresponds.
                }
                else
                {
                    //Application specific code.
                }
                myWatch.Stop();
                string time = myWatch.Elapsed.TotalSeconds.ToString();
                MessageBox.Show(time + " Seconds"); 
            }
            else
            {
                //Get all messages.
                IGPMessages msgs = result.GetResultMessages();
                for (int i = 0; i < result.MessageCount; i++)
                {
                    IGPMessage2 msg = msgs.GetMessage(i) as IGPMessage2;
                    //Application specific code.
                }
            }
        }

再來測試下對相同數據前臺執行Copy Features工具和後臺執行Copy Features工具的用時對比:

10萬個點:前臺用時13.26秒,後臺用時13.42秒

100萬個點:前臺用時1分55秒,後臺用時1分50秒

最後總結一下調用後臺GP的優勢:

1,後臺GP執行時,用戶界面是可響應的,可以執行工具的同時與MapControl進行交互。如果一個GP工具花費很長時間,而用戶界面不可能一直無響應,這時使用後臺GP就比較好。

2,由於ArcGIS Engine 是32位應用程序,因此,最大隻能利用4G內存,如果數據量大或者計算複雜會導致內存超過4G或接近這個數,那麼在32位下可能會出錯,但是如果安裝了64位的後臺GP工具包,則不會有這個限制。

3,如果處理小數據量數據用不用後臺GP差別不大,但是處理數據量大的話,調用後臺GP處理速度更快。

4,不過也有一些限制,如不支持mdb數據、不能調用Geodatabase administration toolset裏的工具、操作SDE數據時需要安裝64位客戶端等,具體可以參考Desktop幫助:Background Geoprocessing (64-bit)

Demo

使用ArcGIS Engine 10.5,Visual Studio 2013編寫,界面爲:

這裏寫圖片描述

工程下載地址:

GP_ArcGISEngine

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章