1. 程式人生 > >ArcEngine GP工具使用心得

ArcEngine GP工具使用心得

在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來建立要素圖,