使用ArcEngine自定义GP Tool

概述

GP 工具是ArcGIS中的一个重要组成部分,用户可以使用ArcGIS提供的数百个GP 工具进行各种分析,并且提供了工具可以自由的组合这些工具,进行更复杂的分析。ArcGIS提供的GP 工具如下:

如果想执行一个GP 工具,可以双击该工具,系统会弹出该工具的界面,如下图所示:

除了可以执行单个的GP 工具,还可以使用ArcGIS提供的Model Builder来组合现有的GP工具,界面如下:

既然ArcGIS预警提供了那么丰富的GP工具以及GP工具组合方式,那么为什么还需要自定义GP工具呢?

为什么需要自定义GP工具?

  1. 某个行业中如果要有针对该行业的一些分析方法,可能ArcGIS提供GP工具满足不了要求,就需要自定义。
  2. 从ArcGIS10.0开始,使用ArcEngine编写的代码已经不能通过WebService发布了,所以自定义ArcEngine功能要想发布出来给Web使用的话只能用ArcServer,ArcServer也提供了GPServer和SOE Server两种方式,其中GPServer一直都存在,SOE服务是新增的,但在arcGIS10.0种使用还比较麻烦,ArcGIS 10.1中就方便一些了。所以自定义的GP工具可以发布成服务。

但我一般自定义GP还是因为第二个原因。有些对数据复杂的操作,可以通过在服务器端发布自定义GP工具的方式实现。因为是ArcEngine代码,里面的操作就可以很灵活。安装ArcEngine开发包后,在安装目录下也会有自定义GP工具的例子。路径如下:

C:\Program Files (x86)\ArcGIS\DeveloperKit10.1\Samples\ArcObjectsNet\GPCustomCalculateAreaFunctionTool

自定义GP工具

上面的gp工具就是我们自定义的工具,通过输入一个FeatureClass获取FeatureClass中元素的个数。

下面就说面下,该工具如何定义。

要想自定义GP工具,需要使用到重要的接口,IGPFunction2和IGPFunctionFactory。

IGPFunction2是定义GP工具要实现的接口。

IGPFunctionFactory是创建GP工具的工厂接口,当我们把我们编译后的dll注册到ArcGIS中时,ArcGIS就是识别该接口,来确定该dll中有哪些GP工具。

代码如下:

    //定义gp工具
    public class GetFeatureCountGPFunction:IGPFunction2
    {
        //工具的名称
        public static string ToolName = "GetFeatureCount";
        private IGPUtilities m_GPUtilities;

        public GetFeatureCountGPFunction()
        {
            m_GPUtilities=new GPUtilitiesClass();
        }
<pre name="code" class="csharp">        //应该是对话框的一个标识,不重要,返回null,即可
        public ESRI.ArcGIS.esriSystem.UID DialogCLSID
        {
            get { return null; }
        }

        //重要,工具的名称
        public string Name
        {
            get { return GetFeatureCountGPFunction.ToolName; }
        }
        //工具显示的名称
        public string DisplayName
        {
            get { return "Get Feature Count From FeatureClass"; }
        }
        //工具的全部名称,包括内容看下面的属性就很容易理解
        public IName FullName
        {
            get 
            {
                IGPFunctionName myGPFunctionName = new GPFunctionNameClass();
                myGPFunctionName.MinimumProduct = esriProductCode.esriProductCodeAdvanced;
                IGPName myGPName= (IGPName)myGPFunctionName;
                myGPName.Name = this.Name;
                myGPName.Category = "BM_0";
                myGPName.Description = "Get Feature Count From FeatureClass";
                myGPName.DisplayName =this.DisplayName;
                BMGPFunctionFactory myBMGPFunctionFactory = new BMGPFunctionFactory();
                myGPName.Factory = myBMGPFunctionFactory;
                return myGPFunctionName as IName;
            }
        }
        //目前还不命该该函数的作用,但如果用不到 返回null即可
        public object GetRenderer(IGPParameter pParam)
        {
            return null;
        }
        //帮助的上下文标识 返回0即可
        public int HelpContext
        {
            get { return 0; }
        }
        //帮助文件,如果没有 返回空字符串即可
        public string HelpFile
        {
            get { return ""; }
        }
        //验证许可
        public bool IsLicensed()
        {
            IAoInitialize myAoInitialize = new AoInitializeClass();
            ILicenseInformation myLicenseInformation = (ILicenseInformation)myAoInitialize;
            string myLicenseProductName = myLicenseInformation.GetLicenseProductName(myAoInitialize.InitializedProduct());
            if (myLicenseProductName == "Advanced")
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        //元数据文件 这个返回空字符串也可以
        public string MetadataFile
        {
            get
            {
                string myFilePath;
                myFilePath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
                myFilePath = System.IO.Path.Combine(myFilePath, this.Name+".xml");
                return myFilePath;
            }
        }
        //重要,定义参数列表,包括输入和输出参数都在此定义
        public IArray ParameterInfo
        {
            get 
            {
                ArrayClass myParameterArray= new ArrayClass();

                IGPParameterEdit3 myGPParameterClass = new GPParameterClass();
                myGPParameterClass.DataType = new GPFeatureLayerTypeClass();
                myGPParameterClass.Direction = esriGPParameterDirection.esriGPParameterDirectionInput;
                myGPParameterClass.DisplayName = "In_FeatureClass";
                myGPParameterClass.Name = "In_FeatureClass";
                myGPParameterClass.ParameterType = esriGPParameterType.esriGPParameterTypeRequired;
                myGPParameterClass.Value = new GPFeatureLayerClass();
                myParameterArray.Add(myGPParameterClass);

                myGPParameterClass = new GPParameterClass();
                myGPParameterClass.DataType = new GPDoubleTypeClass();
                myGPParameterClass.Direction = esriGPParameterDirection.esriGPParameterDirectionOutput;
                myGPParameterClass.DisplayName = "Out_FeatureCount";
                myGPParameterClass.Name = "Out_FeatureCount";
                myGPParameterClass.ParameterType = esriGPParameterType.esriGPParameterTypeDerived;
                myParameterArray.Add(myGPParameterClass);
                return myParameterArray;
            }
        }

        //执行函数
        public void Execute(IArray paramvalues, ITrackCancel TrackCancel, IGPEnvironmentManager envMgr, IGPMessages message)
        {
            IGPParameter parameter = (IGPParameter)paramvalues.get_Element(0);
            IGPValue parameterValue = m_GPUtilities.UnpackGPValue(parameter);

            // Open Input Dataset
            IFeatureClass myInputFeatureClass;
            IQueryFilter qf;
            m_GPUtilities.DecodeFeatureLayer(parameterValue, out myInputFeatureClass, out qf);

            if (myInputFeatureClass == null)
            {
                message.AddError(2, "Could not open input dataset.");
                return;
            }

            IGPParameterEdit3 myOutFeatureCountGPParameter = paramvalues.get_Element(1) as IGPParameterEdit3;
            GPDoubleClass myGPValue = new GPDoubleClass();
            myGPValue.Value = myInputFeatureClass.FeatureCount(null);
        }


        //更新进度信息,因为我们这个比较简单,也没有什么进度信息,如果需要可以查看帮助和示例看如何定义
        public void UpdateMessages(IArray paramvalues, IGPEnvironmentManager pEnvMgr, IGPMessages Messages)
        {
        }
        //更新参数,有些工具需要设置好一个参数后,才能设置下一个参数,例如需要选择一个矢量数据之后,才能选择数据中的字段,这样的工作可在该代码中定义,如何定义还需要查看帮助和示例
        public void UpdateParameters(IArray paramvalues, IGPEnvironmentManager pEnvMgr)
        {
        }
        //验证合法性、如果不需要验证就直接返回new GPMessagesClass()
        public IGPMessages Validate(IArray paramvalues, bool updateValues, IGPEnvironmentManager envMgr)
        {
            return new GPMessagesClass();
        }
    }

FunctionFactory的代码如下:

    [
    Guid("f4d75962-a8ba-43f6-b3c2-fa06ba7d8680"),
    ComVisible(true)
    ]
    public class BMGPFunctionFactory:IGPFunctionFactory
    {
        [ComRegisterFunction()]
        static void Reg(string regKey)
        {
            GPFunctionFactories.Register(regKey);
        }

        [ComUnregisterFunction()]
        static void Unreg(string regKey)
        {
            GPFunctionFactories.Unregister(regKey);
        }

        public string Name
        {
            get { return "BM"; }
        }

        public string Alias
        {
            get { return "BM"; }
        }

        public UID CLSID
        {
            get 
            {
                UID myUID = new UIDClass();
                myUID.Value = this.GetType().GUID.ToString("B");
                return myUID;
            }
        }

        public IGPFunction GetFunction(string Name)
        {
            if (Name == GetFeatureCountGPFunction.ToolName)
            {
                return new GetFeatureCountGPFunction();
            }
            return null;
        }

        public IEnumGPEnvironment GetFunctionEnvironments()
        {
            return null;
        }

        public IGPName GetFunctionName(string Name)
        {
            IGPName myGPName=null;
            if (Name == GetFeatureCountGPFunction.ToolName)
            {
                GetFeatureCountGPFunction myGetFeatureCountGPFunction = new GetFeatureCountGPFunction();
                myGPName = myGetFeatureCountGPFunction.FullName as IGPName;
                myGPName.Factory = this;
            }
            return myGPName;
        }

        public IEnumGPName GetFunctionNames()
        {
            IArray myNameArray = new EnumGPNameClass();

            GetFeatureCountGPFunction myGetFeatureCountGPFunction = new GetFeatureCountGPFunction();
            IGPName myGPName = myGetFeatureCountGPFunction.FullName as IGPName;
            myGPName.Factory = this;
            myNameArray.Add(myGPName);
            
            return (IEnumGPName)myNameArray;
        }
    }

写完这些代码之后,编译成dll。

在ArcGIS中使用自定义GP

右键点击生成的dll文件,在最上面有个注册按钮,点击注册COM组件。

点击注册后,弹出的界面:

点击注册按钮即可。

接下来打开ArcCatalog工具。

在[My Tooloxes]中新建一个自己的工具集,点击右键,[Add]-[Tool]。弹出选择GP Tool对话框。

弹出的对话框如下:

选择我们自定义的工具,其中的工具的目录、分类名称、工具名称等都是可以在代码定义的时候设置的。点击[OK]按钮。

这样工具就被添加进来了,双击该工具,就可以使用了。

转载自:https://blog.csdn.net/mytudousi/article/details/31388607

You may also like...