欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ArcGIS Engine使用GP工具

程序员文章站 2022-07-14 09:59:34
...

     在ArcGIS Engine的开发过程中也必不可少的会遇到调用GP工具的问题,调用GP工具的方式有两种:一种是使用Geoprocessing类;另一种是使用Geoprocessor托管类。两者也可能混合使用。

一、GP工具的调用方式

以调用系统工具Dissolve为例:

准备数据:

ArcGIS Engine使用GP工具

1、使用Geoprocessing类

   工具参数使用IVariantArray方式输入;且参数是有顺序的,其顺序以工具帮助中的参数顺序为准。 如果想要略过某个参数,则传入空字符串(即采用该参数的默认值),以保证参数的顺序是正确的。工具的名称也要按照语法中的写。例如Dissove工具的名称为"Dissolve_management"。顺序写错导致执行失败。

ArcGIS Engine使用GP工具

     

private void Dissolve(IFeatureClass sourceFClass)
{
    ESRI.ArcGIS.Geoprocessing.IGeoProcessor gp = new ESRI.ArcGIS.Geoprocessing.GeoProcessorClass();
    gp.OverwriteOutput = true;
    //除了使用IGeoProcessorResult接口获取GP处理结果外,还可以直接将GP的输出结果写入FeatureClass中,方便进行使用
    ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult result = new ESRI.ArcGIS.Geoprocessing.GeoProcessorResultClass();
    // Create a variant array to hold the parameter values.
    IVariantArray parameters = new VarArrayClass();
    object sev = null;
    try
    {
        // Populate the variant array with parameter values.用参数值填充变量数组
        parameters.Add("F:\\GIS测试数据\\新建文件地理数据库.gdb\\ABCD");//parameters.Add(sourceFClass);
        parameters.Add("F:\\GIS测试数据\\新建文件地理数据库.gdb\\diss");

        ESRI.ArcGIS.Geoprocessing.IGpValueTableObject pObject = new ESRI.ArcGIS.Geoprocessing.GpValueTableObjectClass();  //对多个字段进行融合添加
        pObject.SetColumns(1);
        pObject.AddRow("MC");
        pObject.AddRow("DM");
        parameters.Add(pObject);  //等同于parameters.Add("MC;DM");

        parameters.Add("");   //传入空值,保证顺序正确 
        parameters.Add("SINGLE_PART"); // 等同于parameters.Add("false");
        // Execute the tool.
        result = gp.Execute("Dissolve_management", parameters, null);
        IFeatureClass dealFclss = gp.Open(result.ReturnValue) as IFeatureClass;
    }
    catch (Exception ex)
    {
        // geoprocessing execution error messages.
        gp.GetMessages(ref sev);  //不知为什么返回一直为null
        ReturnMessages(gp);

    }
}

2、使用Geoprocessor托管类

   需要创建工具对象,参数作为该工具对象的属性输入。需要添加该工具的工具箱的引用,例如Dissolve工具需要添加ESRI.ArcGIS.DataManagementTools引用。

private void Dissolve(IFeatureClass sourceFClass)
{
    ESRI.ArcGIS.Geoprocessor.Geoprocessor gp = new ESRI.ArcGIS.Geoprocessor.Geoprocessor();
    gp.OverwriteOutput = true; //是否覆盖原文件
    try
    {
        ESRI.ArcGIS.DataManagementTools.Dissolve diss = new ESRI.ArcGIS.DataManagementTools.Dissolve();
        diss.in_features = "F:\\GIS测试数据\\新建文件地理数据库.gdb\\ABCD";//sourceFClass;   可以填写文件路径或则要素类
        diss.out_feature_class = "F:\\GIS测试数据\\diss2.SHP";//"F:\\GIS测试数据\\新建文件地理数据库.gdb\\AC";
        diss.multi_part = "false";  //Boolean只能填写"false"或"true"
        diss.dissolve_field = "MC;DM";

        gp.Execute(diss, null);

        //IGeoProcessorResult result = (IGeoProcessorResult)gp.Execute(diss,null);
        ////除了使用IGeoProcessorResult接口获取GP处理结果外,还可以直接将GP的输出结果写入FeatureClass中,方便进行使用
        //IFeatureClass dealFclss = gp.Open(result.ReturnValue) as IFeatureClass;  
    }
    catch
    {
        ReturnMessages(gp);
    }
}

工具执行后效果为:

ArcGIS Engine使用GP工具

二、设置GP环境变量

       GP工具有些通用的属性,当一个工具执行时,当前环境中的某些设置被当作全局输入参数,例如工作空间、输出数据的坐标系、容差等等,都可以在环境变量中设置。详细信息参考:Using environment settings

/// <summary>
/// 设置GP工具环境变量
/// </summary>
public void SetGPEnvironment()
{
    ESRI.ArcGIS.Geoprocessing.IGeoProcessor gp = new ESRI.ArcGIS.Geoprocessing.GeoProcessorClass();
    //或则ESRI.ArcGIS.Geoprocessor.Geoprocessor gp = new ESRI.ArcGIS.Geoprocessor.Geoprocessor();

    // Set overwrite option to true.
    gp.OverwriteOutput = true; 

    // Set workspace environment.
    gp.SetEnvironmentValue("workspace", "F:\\GIS测试数据\\测试.gdb"); 

    gp.SetEnvironmentValue("XYTolerance", "0.02 meters");
    // Get the workspace environment value.//获取当前环境变量的值
    object env = gp.GetEnvironmentValue("workspace");
    // Reset the environment values to their defaults. 重置到原始状态
    gp.ResetEnvironments();
}

三、GP工具参数写法的注意事项

1,如果GP工具的参数类型是要素类,要素图层,栅格数据,栅格图层的话,最好使用要素类或者栅格数据的绝对路径,这样最稳定。如果传入AO对象,比如IFeatureLayer、IFeatureClass、IRasterDataset、IRasterLayer等,不太稳定,有时可以成功,有时则失败,所以强烈推荐使用数据的绝对路径方式。还有一点需要注意就是要素类的路径中最好不要含有中文、空格等特殊字符、路径不要过长,并且需要对该数据具有读写权限。

2,如果要素类存储在SDE中,怎么写呢?可以使用该.sde连接文件的绝对路径+要素类名称的写法,比如: @”C:\Users\Feng\AppData\Roaming\ESRI\Desktop10.2\ArcCatalog\连接到 127.0.0.1.sde\SDE.diss”;当然这是使用的ArcCatalog中自动生成的.sde文件,如果没有或者不想使用该连接文件的话也可以使用IWorkspaceFactory.Create()方法或者GP工具Create ArcSDE Connection File根据参数来创建.sde连接文件。

3,GP工具的参数不会写或者写法有误的处理技巧:可以先在ArcMap中使用相同参数执行该GP工具成功后,然后在菜单栏–>Geoprocessing–>Results中打开Results窗口,查看刚才执行成功的GP历史,在Inputs项中查看或直接复制各参数的填写方式到代码中即可。

ArcGIS Engine使用GP工具

4,如果工具中需要输入多个要素类,参数怎么写?比如Intersect_analysis工具,如果对两个要素类求交可以这么写:intersect.in_features = @”C:\Users\a\Desktop\test\1.shp;C:\Users\a\Desktop\test\2.shp”; 
其实在Result界面有其分隔符的写法即分号。其它工具也类似,比如:Reclassify工具,其映射参数可以这样写reclassify.remap = “589 1070 1;1070 1555 2;1555 2169 3;2169 3311 4”; 不同类别用分号隔开,同一类别的最大最小值用空格隔开。再比如Clip_management工具,其范围可以这样写clip.rectangle = “-117.35334730268 33.8297125828826 -116.792366370644 34.4768962586111”;中间用空格隔开。再强调一下:最保险并且准确的就是ArcMap执行成功后,在Results界面复制其写法。

四、获取GP详细报错信息

      方法就是把执行GP的语句放进try-catch-finally的结构体中;尝试获取具体的报错信息,如许可级别不够、参数错误等。

/// <summary>
/// 获取GP工具执行后信息
/// </summary>
/// <param name="gp">gp对象(工具调用者)</param>
/// <returns></returns>
private string ReturnMessages(object gpr)
{
    string ms = "";
    if (gpr is ESRI.ArcGIS.Geoprocessor.Geoprocessor gp)
    {
        if (gp.MessageCount > 0)
        {
            for (int Count = 0; Count <= gp.MessageCount - 1; Count++)
            {
                ms += "$" + gp.GetMessage(Count) + "\n\n";
            }
        }
    }
    else if(gpr is ESRI.ArcGIS.Geoprocessing.IGeoProcessor gp2)
    {
        if (gp2.MessageCount > 0)
        {
            for (int Count = 0; Count <= gp2.MessageCount - 1; Count++)
            {
                ms += "$" + gp2.GetMessage(Count) + "\n\n";
            }
        }
    }
    return ms;
}

五、给GP工具注册事件

1、ExecuteAsync方法是提交工具到当前进程已存在的geoprocessing队列中,当后台执行到这个工具时会触发ToolExecuting事件,这时该工具的IGeoProcessorResults.Status属性变为esriJobStatus.esriJobWaiting。该事件所有工具都会触发。
2、在工具执行过程中能触发MessagesCreated和ProgressChanged事件,这些事件依赖于所使用的工具以及工具处理的数据量。
3、当工具执行完成时触发ToolExecuted事件,该事件所有工具执行结束时都会触发。
4、工具可以在任何时刻取消,调用IGeoProcessorResult2.Canael() 即可,取消后其状态变为esriJobStatus.esriJobCancelled。当工具执行失败时,返回esriJobStatus.esriJobFail。

原文来自:https://blog.csdn.net/xinying180/article/details/70159142

/// <summary>
/// 注册GP工具事件
/// </summary>
public void RegisterGPEvent()
{
    ESRI.ArcGIS.Geoprocessor.Geoprocessor gp = new ESRI.ArcGIS.Geoprocessor.Geoprocessor();
    gp.ProgressChanged += new EventHandler<ESRI.ArcGIS.Geoprocessor.ProgressChangedEventArgs>(gpProgressChanged);
    gp.ToolExecuted += new EventHandler<ESRI.ArcGIS.Geoprocessor.ToolExecutedEventArgs>(gpToolExecuted);

    // Set overwrite option to true.
    gp.OverwriteOutput = true;

    // Set workspace environment.
    gp.SetEnvironmentValue("workspace", "F:\\GIS测试数据\\测试.gdb");

    // Create a variant array to hold the parameter values.
    IVariantArray parameters = new VarArrayClass();
    // Populate the variant array with parameter values.用参数值填充变量数组
    parameters.Add("ABC");//parameters.Add(sourceFClass);
    parameters.Add("DISS");

    parameters.Add("");
    parameters.Add("");   //传入空值,保证顺序正确 
    parameters.Add("SINGLE_PART"); // 等同于parameters.Add("false");

    ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult result = (ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult)gp.ExecuteAsync("Dissolve_management", parameters);
    //result.Cancel(); //取消
}

public void gpToolExecuted(object sender, ToolExecutedEventArgs e)
{
    ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult result = e.GPResult as ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult;
    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.
        }
    }
    else
    {
        //Get all messages.
        string ms = "";
        IGPMessages msgs = result.GetResultMessages();
        for (int i = 0; i < result.MessageCount; i++)
        {
            IGPMessage2 msg = msgs.GetMessage(i) as IGPMessage2;
            //Application specific code.
            ms += "$" + result.GetMessage(i) + "\n\n";
        }
    }
}

public void gpProgressChanged(object sender, ESRI.ArcGIS.Geoprocessor.ProgressChangedEventArgs e)
{
    ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult gpResult = (ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult)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):
            var v= (int)e.ProgressPercentage;
            //progressBar.Value = (int)e.ProgressPercentage;
            break;
        default:
            throw new ApplicationException(
                "unexpected ProgressChangedEventsArgs.ProgressChangedType");
    }
}