Arcgis GP工具

基於Arcgis GP工具的大部分的功能,都在這裏面了

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Geoprocessing;
using ESRI.ArcGIS.Geoprocessor;
using AG.GH.Utility.Common;
using ESRI.ArcGIS.SpatialAnalystTools;
using AG.GH.Utility.Common.Sub;
using ESRI.ArcGIS.DataSourcesRaster;
using System.Data;
using System.Linq;
using ESRI.ArcGIS.ConversionTools;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.ADF;
using ESRI.ArcGIS.DataSourcesFile;
using System.Text.RegularExpressions;
using ESRI.ArcGIS.SpatialAnalyst;
using ESRI.ArcGIS.GeoAnalyst;
using AG.GH.Utility.Tools.Sub;
using AG.COM.SDM.Utility;
using AG.GH.Utility.Data;
using ESRI.ArcGIS.DataManagementTools;
using System.IO;

namespace AG.GH.Utility.Tools
{
    /// <summary>
    /// 2018年9月26日 對部分代碼添加region管理-蔡周峻
    /// 2018年10月15日20:58:33 ShowGPFileMessage
    /// 2018年10月18日10:53:20 陳彪,新建虛函數ClassifyRaster
    /// </summary>
    public interface IGeoAnalysis
    {
        #region 屬性
        ITrackCancel TrackCancel { set; }

        IGeoProcessorEvents GPEvents { set; } 
        #endregion

        #region 裁剪
        void ClipFeature(IFeatureClass inputFeatures, IPolygon clip, IFeatureClass outputClass, string sClause);

        IFeatureClass ClipFeature(IFeatureClass inputFeatures, IPolygon clip, string sClause);

        IFeatureClass ClipFeature(IFeatureClass inputFeatures, List<IPolygon> clipGeometrys, string sClause);

        IFeatureClass ClipFeature(IFeatureClass inputFeatures, IGeometryArray clipGeometrys, string sClause);

        IFeatureClass ClipFeature(IFeatureClass inputFeatures, IFeatureClass clipFeatures, IQueryFilter inputFilter, IQueryFilter clipFilter);

        IFeatureClass ClipFeature(object inputFeatures, object clipFeatures, double tolerance);
        
        #endregion

        #region 擦除
        void Erase(IFeatureClass inputFeatures, IPolygon erase, string sClause);

        IFeatureClass Erase(IFeatureClass inputFeatures, IFeatureClass eraseFeatures, string outputClass);

        IFeatureClass Erase(IFeatureClass inputFeatures, IFeatureClass eraseFeatures, string outputClass, IQueryFilter inputFilter, IQueryFilter eraseFilter);

        IFeatureClass EraseWithArcInfo
            (object inputFeatures, object eraseFeatures, string outputClass, double tolerance); 
        #endregion

        #region 聯合
        IFeatureClass Union(object[] inputObjects,  JoinAttributesType joinType);

        IFeatureClass Union(IFeatureClass inputFeatures, IFeatureClass unionFeatures);

        IFeatureClass Union(IFeatureClass inputFeatures, IFeatureClass unionFeatures,  IQueryFilter inputFilter, IQueryFilter unionFilter); 
        #endregion

        #region 求相交
        IFeatureClass Intersect(object[] inputObjects,JoinAttributesType joinType, string outputType, double tolerance);

        IFeatureClass Intersect(IFeatureClass inputFeatures, IFeatureClass intersecFeatures);

        IFeatureClass Intersect(IFeatureLayer inputFeatures, IFeatureLayer intersecFeatures);

        IFeatureClass Intersect(IFeatureClass inputFeatures, IFeatureClass intersectFeatures, IQueryFilter inputFilter, IQueryFilter intersectFilter); 
        #endregion

        #region 求緩衝
        IFeatureClass Buffer(IFeatureClass inputFeatures, IQueryFilter inputFilter, double radius, bool dissolve);
        #endregion

        /// <summary>
        /// 交集取反
        /// </summary>
        /// <param name="inputFeatures"></param>
        /// <param name="update_features"></param>
        /// <param name="outputClass"></param>
        /// <param name="joinType"></param>
        /// <returns></returns>
        IFeatureClass SymDiffWithArcInfo(object inputFeatures, object update_features, string outputClass, JoinAttributesType joinType);
        IFeatureClass IdentityWithArcInfo(object inputFeatures, object identityFeatures, string outputClass, JoinAttributesType joinType);

        void Release();

        #region 輸出路徑設置
        void SetClipResultPathRandomName();
        void SetUnionResultPathRandomName();
        void SetBufferResultPathRandomName();
        void SetIntersectResultPathRandomName();
        string SetRasterResultPathPathRandomName(); 
        #endregion
    }

   

    

    public class GeoAnalysis : EnvironmentClass, IGeoAnalysis, IDebug, IEnvironment
    {
        private ITrackCancel m_TrackCancel = null;
        private TrackCancelClass2 m_cancelHandler = null;
        private IGeoTopology m_GeoTopology = null;
        private IFeaturesCopy m_FeaturesCopy = null;
        private Geoprocessor m_GP = null;
        private IGeoProcessorEvents m_GPEvents = null;
        private ESRI.ArcGIS.AnalysisTools.Intersect m_IntersectTool = null;
        private ESRI.ArcGIS.AnalysisTools.Buffer m_BufferTool = null;
        private ESRI.ArcGIS.AnalysisTools.Erase m_EraseTool = null;

        #region 屬性
        public ITrackCancel TrackCancel
        {
            set
            {
                m_TrackCancel = value;
            }
        }
        /// <summary>
        /// 裁剪的數據路徑
        /// </summary>
        public string ClipResultPath
        {
            get;
            set;
        }
        /// <summary>
        /// 聯合的數據路徑
        /// </summary>
        public string UnionResultPath
        {
            get;
            set;
        }
        /// <summary>
        /// 緩衝分析的數據保存路徑
        /// </summary>
        public string BufferResultPath
        {
            get;
            set;
        }
        /// <summary>
        /// 相交計算得到的結果的保存路徑
        /// </summary>
        public string IntersectResultPath
        {
            get;
            set;
        }
        /// <summary>
        /// 柵格計算得到的結果的保持的路徑
        /// </summary>
        public string RasterResultPath
        {
            get;
            set;
        }

        public IGeoProcessorEvents GPEvents
        {
            set
            {
                if (m_GPEvents != null)
                    m_GP.UnRegisterGeoProcessorEvents(m_GPEvents);

                if (value != null)
                    m_GP.RegisterGeoProcessorEvents(value);

                m_GPEvents = value;
            }
        }

        #endregion

        #region 構造函數
        public GeoAnalysis(bool initializeGPTool=true)
        {
            if (initializeGPTool)
            {
                m_GP = new Geoprocessor();

                m_FeaturesCopy = new FeaturesCopyClass();
            }
           
            ClipResultPath = AG.COM.SDM.Utility.CommonConstString.STR_TempPath + "\\CATemp.gdb\\Clip";
            UnionResultPath = AG.COM.SDM.Utility.CommonConstString.STR_TempPath + "\\CATemp.gdb\\Uinon";
            BufferResultPath = AG.COM.SDM.Utility.CommonConstString.STR_TempPath + "\\CATemp.gdb\\Buffer";
            IntersectResultPath = AG.COM.SDM.Utility.CommonConstString.STR_TempPath + "\\CATemp.gdb\\Intersect";
            RasterResultPath = AG.COM.SDM.Utility.CommonConstString.STR_TempPath + "\\CATemp.gdb\\Raster";
        }
        public GeoAnalysis(ITrackCancel trackCancel, IGeoProcessorEvents gpEvents)
            : this()
        {
            m_TrackCancel = trackCancel;
            if (gpEvents != null)
                m_GP.RegisterGeoProcessorEvents(gpEvents);

            m_GPEvents = gpEvents;
        }

        public GeoAnalysis(TrackCancelClass2 trackCancel)
            : this(trackCancel, trackCancel.Progressor as IGeoProcessorEvents)
        {
            m_cancelHandler = trackCancel;
        }
        #endregion

        #region IGeoAnalysis 成員
        public void Release()
        {
            m_GP = null;
            m_IntersectTool = null;
        }


        public void Erase(IFeatureClass inputFeatures, IPolygon erase, string sClause)
        {
            if (m_GeoTopology == null)
            {
                m_GeoTopology = new GeoTopology();
                (m_GeoTopology as IDebug).ThrowException = true;
            }

            IFeatureCursor pFeatureCursor = null;
            try
            {
                ISpatialFilter pSpatialFilter = new SpatialFilterClass();
                pSpatialFilter.Geometry = erase;
                pSpatialFilter.GeometryField = inputFeatures.ShapeFieldName;
                pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
                pSpatialFilter.WhereClause = String.IsNullOrEmpty(sClause) ? "" : sClause;

                if (inputFeatures.ShapeType == esriGeometryType.esriGeometryPoint)
                {
                    (inputFeatures as ITable).DeleteSearchedRows(pSpatialFilter);
                    return;
                }

                IFeature pFeature = null;
                pFeatureCursor = inputFeatures.Search(pSpatialFilter, false);
                while ((pFeature = pFeatureCursor.NextFeature()) != null)
                {
                    IGeometry source = pFeature.ShapeCopy;
                    IGeometry output = m_GeoTopology.Erase(source, erase);
                    if (output == null || output.IsEmpty)
                    {
                        pFeature.Delete();
                    }
                    else
                    {
                        pFeature.Shape = output;
                        pFeature.Store();
                    }

                    if (source != null)
                        System.Runtime.InteropServices.Marshal.ReleaseComObject(source);
                }
            }
            catch (Exception err)
            {
                if (m_throwException)
                    throw err;
            }
            finally
            {
                if (pFeatureCursor != null)
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(pFeatureCursor);
            }
        }

        public IFeatureClass Erase(IFeatureClass inputFeatures, IFeatureClass eraseFeatures, string outputClass)
        {
            return Erase(inputFeatures, eraseFeatures, outputClass, null, null);
        }

        public IFeatureClass Erase(IFeatureClass inputFeatures, IFeatureClass eraseFeatures, string outputClass, IQueryFilter inputFilter, IQueryFilter eraseFilter)
        {
            IFeatureCursor pFeatureCursor = null;
            try
            {
                if (eraseFeatures.ShapeType != esriGeometryType.esriGeometryPolygon)
                    throw new Exception("eraseFeatures要素類必須爲Polygon");

                IGeometryDef geometryDef = CommonUtils.CloneGeometryDef(inputFeatures, this.ZFlag, this.MFlag);
                IFeatureClass outputFeaturs = WSExt.CreateSimpleClassFromPath(outputClass, inputFeatures.Fields, geometryDef, base.m_overwriteOutput);
                IEnumInvalidObject pEnumInvalidObject = m_FeaturesCopy.PasteObjects(inputFeatures, outputFeaturs, inputFilter);
                if (pEnumInvalidObject != null && pEnumInvalidObject.Next() != null)
                    throw new Exception("複製要素出錯,存在錯誤的對象");

                IFeature pFeature = null;
                pFeatureCursor = eraseFeatures.Search(eraseFilter, true);
                while ((pFeature = pFeatureCursor.NextFeature()) != null)
                {
                    IPolygon pPolygon = pFeature.ShapeCopy as IPolygon;
                    if (pPolygon == null || pPolygon.IsEmpty) continue;

                    Erase(outputFeaturs, pPolygon, "");
                }

                return outputFeaturs;
            }
            catch (Exception err)
            {
                if (m_throwException)
                    throw err;

                return null;
            }
            finally
            {
                if (pFeatureCursor != null)
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(pFeatureCursor);
            }
        }

        public IFeatureClass EraseWithArcInfo(object inputFeatures, object eraseFeatures, string outputClass, double tolerance)
        {
            SetGPEnvironment();
            try
            {
                if (m_EraseTool == null) m_EraseTool = new ESRI.ArcGIS.AnalysisTools.Erase();

                m_EraseTool.in_features = inputFeatures;
                m_EraseTool.erase_features = eraseFeatures;
                m_EraseTool.out_feature_class = outputClass;

                if (tolerance > 0.0)
                {
                    m_EraseTool.cluster_tolerance = tolerance;
                }

                IGeoProcessorResult gpResult =
                       m_GP.Execute(m_EraseTool as IGPProcess, m_TrackCancel) as IGeoProcessorResult;

                return DecodeResultClass(gpResult);
            }
            catch (Exception err) { LogGPMessage(); if (m_throwException) throw err; return null; }
        }
        public IFeatureClass IdentityWithArcInfo(object inputFeatures, object identityFeatures, string outputClass, JoinAttributesType joinType)
        {
            SetGPEnvironment();
            try
            {
                ESRI.ArcGIS.AnalysisTools.Identity tIdentity = null;
                tIdentity = new ESRI.ArcGIS.AnalysisTools.Identity();
                tIdentity.in_features = inputFeatures;
                tIdentity.identity_features = identityFeatures;
                tIdentity.out_feature_class = outputClass;
                tIdentity.join_attributes = joinType.ToString();

                IGeoProcessorResult gpResult =
                       m_GP.Execute(tIdentity as IGPProcess, m_TrackCancel) as IGeoProcessorResult;

                return DecodeResultClass(gpResult);
            }
            catch (Exception err) { LogGPMessage(); if (m_throwException) throw err; return null; }
        }

        public IFeatureClass SymDiffWithArcInfo(object inputFeatures, object update_features, string outputClass, JoinAttributesType joinType)
        {
            SetGPEnvironment();
            try
            {
                ESRI.ArcGIS.AnalysisTools.SymDiff tSymDiff = null;
                tSymDiff = new ESRI.ArcGIS.AnalysisTools.SymDiff();
                tSymDiff.in_features = inputFeatures;
                tSymDiff.update_features = update_features;
                tSymDiff.out_feature_class = outputClass;
                tSymDiff.join_attributes = joinType.ToString();

                IGeoProcessorResult gpResult =
                       m_GP.Execute(tSymDiff as IGPProcess, m_TrackCancel) as IGeoProcessorResult;

                return DecodeResultClass(gpResult);
            }
            catch (Exception err) { LogGPMessage(); if (m_throwException) throw err; return null; }
        }

        void JoinAttributes(string preFix, IFields inputFields, IRow identityRow, IRowBuffer pRowBuffer)
        {
            try
            {
                for (int i = 0; i < identityRow.Fields.FieldCount; i++)
                {
                    IField pField = identityRow.Fields.get_Field(i);

                    if (pField.Type == esriFieldType.esriFieldTypeGeometry
                        || pField.Type == esriFieldType.esriFieldTypeOID
                        || pField.Name.ToUpper().Contains("SHAPE_")
                        || pField.Name.ToUpper().Contains("SHAPE.")) continue;


                    int checkIndex = inputFields.FindField(pField.Name);
                    string sFieldName = checkIndex > -1 ? preFix + pField.Name : pField.Name;

                    int index = pRowBuffer.Fields.FindField(sFieldName);

                    IField pBufferField = pRowBuffer.Fields.get_Field(index);
                    if (pBufferField.Type != pField.Type || pBufferField.Editable == false) continue;

                    object value = identityRow.get_Value(i);
                    if (value == null) continue;

                    pRowBuffer.set_Value(index, value);
                }
            }
            catch (Exception err) { }
        }

        #endregion

        #region 疊加分析-相交(Intersect)
        public IFeatureClass Intersect(IFeatureLayer inputFeatures, IFeatureLayer intersecFeatures)
        {
            return this.Intersect(inputFeatures.FeatureClass, intersecFeatures.FeatureClass);
        }

        public IFeatureClass Intersect(object[] inputObjects, JoinAttributesType joinType, string outputType, double tolerance)
        {
            SetGPEnvironment();
            try
            {
                IGpValueTableObject gpValueTable = new GpValueTableObjectClass();
                gpValueTable.SetColumns(2);

                object row = null;
                object rank = null;
                for (int i = 0; i < inputObjects.Length; i++)
                {
                    object value = inputObjects[i];

                    rank = i + 1;

                    if (value is IFeatureClass)
                    {
                        row = ApplyQueryFilter(value as IFeatureClass, null);
                    }
                    else
                    {
                        row = value;
                    }

                    gpValueTable.AddRow(ref row);
                    gpValueTable.SetValue(i, 1, ref rank);
                }

                if (m_IntersectTool == null) m_IntersectTool = new ESRI.ArcGIS.AnalysisTools.Intersect();

                m_IntersectTool.in_features = gpValueTable;
                m_IntersectTool.join_attributes = joinType.ToString();
                m_IntersectTool.out_feature_class = IntersectResultPath;

                m_IntersectTool.output_type = outputType;

                if (tolerance > 0.0)
                {
                    m_IntersectTool.cluster_tolerance = tolerance;
                }

                IGeoProcessorResult gpResult =
                    m_GP.Execute(m_IntersectTool as IGPProcess, m_TrackCancel) as IGeoProcessorResult;

                return DecodeResultClass(gpResult);
            }
            catch (Exception err)
            {
                var gpError = LogGPMessage();
                throw new Exception(gpError);
            }
        }

        public IFeatureClass Intersect(IFeatureClass inputFeatures, IFeatureClass intersectFeatures)
        {
            return Intersect(inputFeatures, intersectFeatures, null, null);
        }

        public IFeatureClass Intersect(IFeatureClass inputFeatures, IFeatureClass intersectFeatures, IQueryFilter inputFilter, IQueryFilter intersectFilter)
        {
            var row1 = ApplyQueryFilter(inputFeatures, inputFilter);

            var row2 = ApplyQueryFilter(intersectFeatures, intersectFilter);

            return Intersect(new object[] { row1, row2 }, JoinAttributesType.ALL, "INPUT", 0.0);
        }
        #endregion

        #region 疊加分析-聯合(Union)
        public IFeatureClass Union(object[] inputObjects, JoinAttributesType joinType)
        {
            SetGPEnvironment();
            try
            {
                IGpValueTableObject gpValueTable = new GpValueTableObjectClass();
                gpValueTable.SetColumns(2);

                object row = null;
                object rank = null;
                for (int i = 0; i < inputObjects.Length; i++)
                {
                    object value = inputObjects[i];

                    rank = i + 1;

                    if (value is IFeatureClass)
                    {
                        row = ApplyQueryFilter(value as IFeatureClass, null);
                    }
                    else
                    {
                        row = value;
                    }

                    gpValueTable.AddRow(ref row);
                    gpValueTable.SetValue(i, 1, ref rank);
                }

                var m_UnionTool = new ESRI.ArcGIS.AnalysisTools.Union();

                m_UnionTool.in_features = gpValueTable;
                m_UnionTool.join_attributes = joinType.ToString();
                m_UnionTool.out_feature_class = UnionResultPath;

                var gpResult =m_GP.Execute(m_UnionTool as IGPProcess, m_TrackCancel) as IGeoProcessorResult;

                return DecodeResultClass(gpResult);
            }
            catch (Exception err) { LogGPMessage(); if (m_throwException) throw err; return null; }
        }

        public IFeatureClass Union(IFeatureClass inputFeatures, IFeatureClass unionFeatures)
        {
            return Union(inputFeatures, unionFeatures, null, null);
        }

        public IFeatureClass Union(IFeatureClass inputFeatures, IFeatureClass unionFeatures, IQueryFilter inputFilter, IQueryFilter unionFilter)
        {
            object row1 = ApplyQueryFilter(inputFeatures, inputFilter);

            object row2 = ApplyQueryFilter(unionFeatures, unionFilter);

            return Union(new object[] { row1, row2 }, JoinAttributesType.ALL);
        }


        #endregion

        #region 裁剪(Clip)
        public void ClipFeature(IFeatureClass inputFeatures, IPolygon clip, IFeatureClass outputFeatures, string whereClause)
        {
            if (m_GeoTopology == null)
            {
                m_GeoTopology = new GeoTopology();
                (m_GeoTopology as IDebug).ThrowException = true;
            }


            IWorkspaceEdit wsEdit = null;
            IFeatureCursor inputCursor = null;
            IFeatureCursor outputCursor = null;
            try
            {
                bool isPointClass = inputFeatures.ShapeType == esriGeometryType.esriGeometryPoint;
                ISpatialFilter pSpatialFilter = new SpatialFilterClass();
                pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
                pSpatialFilter.GeometryField = inputFeatures.ShapeFieldName;
                pSpatialFilter.WhereClause = String.IsNullOrEmpty(whereClause) ? "" : whereClause;
                pSpatialFilter.Geometry = clip;

                if (m_cancelHandler != null)
                {
                    m_cancelHandler.SetCircleRun(inputFeatures.FeatureCount(pSpatialFilter));
                    m_cancelHandler.SetWaitingMessage("Clip運算....");
                }
                clip.SpatialReference = (inputFeatures as IGeoDataset).SpatialReference;

                inputCursor = inputFeatures.Search(pSpatialFilter, true);

                wsEdit = (outputFeatures as IDataset).Workspace as IWorkspaceEdit;
                wsEdit.StartEditing(true);
                wsEdit.StartEditOperation();

                outputCursor = outputFeatures.Insert(true);

                int shapeIndex = outputFeatures.Fields.FindField(outputFeatures.ShapeFieldName);
                IGeometryDef geometryDef = outputFeatures.Fields.get_Field(shapeIndex).GeometryDef;
                bool hasZ = geometryDef.HasZ;
                bool hasM = geometryDef.HasM;

                int indexZ = inputCursor.FindField("ELEV");

                int count = 0;
                IGeometry outGeometry = null;
                IFeature sourceFeature = null;
                IFeatureBuffer targetFeature = null;

                while ((sourceFeature = inputCursor.NextFeature()) != null)
                {
                    if (m_TrackCancel != null && !m_TrackCancel.Continue()) break;

                    IGeometry inGeometry = sourceFeature.ShapeCopy;
                    if (inGeometry == null || inGeometry.IsEmpty) continue;

                    targetFeature = outputFeatures.CreateFeatureBuffer();

                    //包含判斷,提升效率
                    IRelationalOperator pRelationalOp = inGeometry as IRelationalOperator;
                    if (clip.SpatialReference != inGeometry.SpatialReference)
                    {
                        clip.SpatialReference = inGeometry.SpatialReference;
                    }
                    if (pRelationalOp.Within(clip))
                    {
                        outGeometry = inGeometry;
                    }
                    else
                    {
                        outGeometry = isPointClass ? inGeometry : m_GeoTopology.Interset(inGeometry, clip);
                    }

                    // IGeometry outGeometry = isPointClass ? inGeometry : m_GeoTopology.Interset(inGeometry, clip);

                    if (outGeometry == null || outGeometry.IsEmpty)
                        continue;

                    m_FeaturesCopy.CopyPropertry(sourceFeature as IRow, targetFeature as IRowBuffer, false);

                    if (!hasZ && m_ZFlag == FlagEnum.Disabled)
                    {
                        m_GeoTopology.DropZ(outGeometry);
                    }

                    if (m_MFlag == FlagEnum.Disabled)
                    {
                        m_GeoTopology.DropM(outGeometry);
                    }

                    if (hasZ)
                    {
                        IZAware pZAware = outGeometry as IZAware;
                        pZAware.ZAware = true;

                        if (outGeometry.GeometryType == esriGeometryType.esriGeometryPoint)
                        {
                            double z = 0.0;
                            if (indexZ > -1)
                            {
                                object oZ = sourceFeature.get_Value(indexZ);
                                if (oZ != null && !DBNull.Value.Equals(oZ))
                                {
                                    string sZ = oZ.ToString();
                                    double.TryParse(sZ, out z);
                                }
                            }

                            (outGeometry as IPoint).Z = z;
                        }
                        else
                        {
                            IZ2 pZ = outGeometry as IZ2;
                            pZ.SetConstantZ(0);
                        }
                    }

                    targetFeature.Shape = outGeometry;

                    outputCursor.InsertFeature(targetFeature);

                    count++;
                    if (count == 2000)
                    {
                        outputCursor.Flush();
                        count = 0;
                    }

                    if (m_cancelHandler != null)
                        m_cancelHandler.StepCircle();

                    if (inGeometry != null)
                        CommonUtils.CloseObject(inGeometry);
                }

                if (count > 0)
                {
                    outputCursor.Flush();
                }

                wsEdit.StopEditOperation();
                wsEdit.StopEditing(true);
            }
            catch (Exception err)
            {
                if (wsEdit != null && wsEdit.IsBeingEdited())
                {
                    wsEdit.AbortEditOperation();
                    wsEdit.StopEditing(false);
                }

                if (m_throwException)
                    throw err;
            }
            finally
            {
                if (inputCursor != null)
                    CommonUtils.CloseObject(inputCursor);
                if (outputCursor != null)
                    CommonUtils.CloseObject(outputCursor);
            }
        }
        
        public IFeatureClass ClipFeature(IFeatureClass inputFeature, IPolygon clip, string whereClause)
        {
            IFeatureClass outputFeatures = null;
            try
            {
                IGeometryDef geometryDef = CommonUtils.CloneGeometryDef(inputFeature, this.ZFlag, this.MFlag);
                outputFeatures = WSExt.CreateSimpleClassFromPath(ClipResultPath, inputFeature.Fields, geometryDef, m_overwriteOutput);
                ClipFeature(inputFeature, clip, outputFeatures, whereClause);
            }
            catch (Exception err)
            {
                if (m_throwException)
                    throw err;
            }
            return outputFeatures;
        }

        public IFeatureClass ClipFeature(IFeatureClass inputFeatures, List<IPolygon> clipGeometrys,  string whereClause)
        {
            IFeatureClass outputFeaures = ClipFeature(inputFeatures, clipGeometrys[0], whereClause);
            for (int i = 1; i < clipGeometrys.Count; i++)
            {
                ClipFeature(inputFeatures, clipGeometrys[i], outputFeaures, whereClause);
            }
            return outputFeaures;
        }

        public IFeatureClass ClipFeature(IFeatureClass inputFeatures, IGeometryArray clipGeometrys, string whereClause)
        {
            if (clipGeometrys == null || clipGeometrys.Count < 1) 
                return null;
            IFeatureClass outputFeaures = ClipFeature(inputFeatures, clipGeometrys.get_Element(0) as IPolygon, whereClause);
            for (int i = 1; i < clipGeometrys.Count; i++)
            {
                ClipFeature(inputFeatures, clipGeometrys.get_Element(i) as IPolygon, outputFeaures, whereClause);
            }
            return outputFeaures;
        }

        public IFeatureClass ClipFeature(IFeatureClass inputFeatures, IFeatureClass clipFeatures,  IQueryFilter inputFilter, IQueryFilter clipFilter)
        {
            object in_Features = ApplyQueryFilter(inputFeatures, inputFilter);
            object clip_Features = ApplyQueryFilter(clipFeatures, clipFilter);

            return ClipFeature(in_Features, clip_Features, 0.001);
        }

        public IFeatureClass ClipFeature(object inputFeatures, object clipFeatures, double tolerance)
        {
            SetGPEnvironment();
            try
            {
                var m_ClipTool = new ESRI.ArcGIS.AnalysisTools.Clip();

                m_ClipTool.in_features = inputFeatures;
                m_ClipTool.clip_features = clipFeatures;
                m_ClipTool.out_feature_class = ClipResultPath;

                if (tolerance > 0.0)
                {
                    m_ClipTool.cluster_tolerance = tolerance;
                }

                IGeoProcessorResult gpResult =
                       m_GP.Execute(m_ClipTool as IGPProcess, m_TrackCancel) as IGeoProcessorResult;

                return DecodeResultClass(gpResult);
            }
            catch (Exception err)
            {
                LogGPMessage();
                if (m_throwException)
                    throw err;
                return null;
            }
        }
        #endregion

        #region 緩衝(Buffer)
        public IFeatureClass Buffer(IFeatureClass inputFeatures, IQueryFilter inputFilter, double radius, bool dissolve)
        {
            SetGPEnvironment();
            try
            {
                if (m_BufferTool == null)
                    m_BufferTool = new ESRI.ArcGIS.AnalysisTools.Buffer();

                m_BufferTool.in_features = ApplyQueryFilter(inputFeatures, inputFilter);
                m_BufferTool.out_feature_class = BufferResultPath;
                m_BufferTool.dissolve_option = dissolve ? "ALL" : "NONE";
                m_BufferTool.buffer_distance_or_field = radius + " Meters";

                IGeoProcessorResult gpResult =
                    m_GP.Execute(m_BufferTool as IGPProcess, m_TrackCancel) as IGeoProcessorResult;

                return DecodeResultClass(gpResult);
            }
            catch (Exception err)
            {
                LogGPMessage();
                if (m_throwException)
                    throw err;
                return null;
            }
        }
        /// <summary>
        /// 空間數據的緩衝分析
        /// </summary>
        /// <param name="inputFeatures"></param>
        /// <param name="inputFilter"></param>
        /// <param name="radiusWithUnit">Meters</param>
        /// <param name="dissolveOption">ALL NONE LIST</param>
        /// <returns></returns>
        public IFeatureClass Buffer(IFeatureClass inputFeatures, IQueryFilter inputFilter, string radiusWithUnit, string dissolveOption = "ALL")
        {
            SetGPEnvironment();
            try
            {
                if (m_BufferTool == null)
                    m_BufferTool = new ESRI.ArcGIS.AnalysisTools.Buffer();

                m_BufferTool.in_features = ApplyQueryFilter(inputFeatures, inputFilter);
                m_BufferTool.out_feature_class = BufferResultPath;
                m_BufferTool.dissolve_option = dissolveOption;
                m_BufferTool.buffer_distance_or_field = radiusWithUnit;

                IGeoProcessorResult gpResult =
                    m_GP.Execute(m_BufferTool as IGPProcess, m_TrackCancel) as IGeoProcessorResult;

                return DecodeResultClass(gpResult);
            }
            catch (Exception err)
            {
                LogGPMessage();
                if (m_throwException)
                    throw err;
                return null;
            }
        }
        #endregion

        #region 分割(Slice)
        /// <summary>
        /// 分割, 即將待重分類的柵格數據的值域進行n等分
        /// 每一段的柵格像元值, 由舊值從小到大變爲1、2、3...的順序自然數值
        /// </summary>
        /// <param name="layer">待重分類的柵格圖層</param>
        /// <param name="sliceNum">待分割的段數,默認5段</param>
        /// <param name="type">分割類型,默認等間距分割</param>
        /// <returns></returns>
        public IRasterLayer Slice(IRasterLayer layer, int sliceNum, esriGeoAnalysisSliceEnum type = esriGeoAnalysisSliceEnum.esriGeoAnalysisSliceEqualInterval)
        {
            IReclassOp reclassOp = new RasterReclassOpClass();
            IRasterAnalysisEnvironment rasterAnalysisEnvironment = reclassOp as IRasterAnalysisEnvironment;
            rasterAnalysisEnvironment.SetExtent(esriRasterEnvSettingEnum.esriRasterEnvValue, (layer.Raster as IGeoDataset).Extent, null);
            rasterAnalysisEnvironment.OutSpatialReference = (layer.Raster as IGeoDataset).SpatialReference;
            IRaster rasterResult = reclassOp.Slice(layer.Raster as IGeoDataset, type, sliceNum) as IRaster;
            IRasterLayer rlyr = new RasterLayerClass();
            rlyr.CreateFromRaster(rasterResult);
            return rlyr;
        }
        /// <summary>
        /// 分割, 即將待重分類的柵格數據的值域進行n等分
        /// 每一段的柵格像元值, 由舊值從小到大變爲1、2、3...的順序自然數值
        /// </summary>
        /// <param name="inputRaster">待重分類的IRaster</param>
        /// <param name="sliceNum">待分割的段數,默認5段</param>
        /// <param name="type">分割類型,默認等間距分割</param>
        /// <returns></returns>
        public IRasterLayer Slice(IRaster inputRaster, int sliceNum, esriGeoAnalysisSliceEnum type = esriGeoAnalysisSliceEnum.esriGeoAnalysisSliceEqualInterval)
        {
            IReclassOp reclassOp = new RasterReclassOpClass();
            // 環境設置
            IRasterAnalysisEnvironment rasterAnalysisEnvironment = reclassOp as IRasterAnalysisEnvironment;
            rasterAnalysisEnvironment.SetExtent(esriRasterEnvSettingEnum.esriRasterEnvValue, (inputRaster as IGeoDataset).Extent, null);
            rasterAnalysisEnvironment.OutSpatialReference = (inputRaster as IGeoDataset).SpatialReference;

            IRaster rasterResult = reclassOp.Slice(inputRaster as IGeoDataset, type, sliceNum) as IRaster;
            IRasterLayer rlyr = new RasterLayerClass();
            rlyr.CreateFromRaster(rasterResult);
            return rlyr;
        }
        #endregion

        #region 空間連接
        public IFeatureClass SpatialJoins(IFeatureClass inputFeatures, IFeatureClass joinsFeatures, SpatialJoinOperation operation)
        {
            return SpatialJoins(inputFeatures, joinsFeatures, operation, MatchOption.INTERSECT);
        }
        public IFeatureClass SpatialJoins(IFeatureClass inputFeatures, IFeatureClass joinsFeatures, SpatialJoinOperation operation,MatchOption type)
        {
            SetGPEnvironment();
            try
            {
                var m_SpatialJoinsTool = new ESRI.ArcGIS.AnalysisTools.SpatialJoin();
                m_SpatialJoinsTool.target_features = inputFeatures;
                m_SpatialJoinsTool.join_features = joinsFeatures;
                m_SpatialJoinsTool.join_operation = operation.ToString();
                m_SpatialJoinsTool.match_option = type.ToString();
                var gpResult = m_GP.Execute(m_SpatialJoinsTool as IGPProcess, m_TrackCancel) as IGeoProcessorResult;

                return DecodeResultClass(gpResult);
            }
            catch(Exception err)
            {
                LogGPMessage(); if (m_throwException) throw err; return null;
            }
        }
        #endregion

        #region 地圖代數
        /// <summary>
        /// 傳入RasterLayer列表,傳入表達式,計算結果
        /// </summary>
        /// <param name="param">IRasterLayer列表</param>
        /// <param name="expression">表達式</param>
        /// <returns>返回計算結果柵格圖層</returns>
        public IRasterLayer RasterCalculator(List<IRasterLayer> param, string expression, IFeatureLayer maskLayer = null)
        {
            // 使用IMapAlgebraOp
            IMapAlgebraOp mapAlgebraOp = new RasterMapAlgebraOpClass();
            for (int i = 1; i <= param.Count; i++)
            {
                // 綁定柵格數據與名稱
                mapAlgebraOp.BindRaster(
                    param[i - 1].Raster as IGeoDataset,
                    "raster" + i.ToString());
            }

            if (maskLayer != null)
            {
                IRasterAnalysisEnvironment rasterAnalysisEnvironment = mapAlgebraOp as IRasterAnalysisEnvironment;
                rasterAnalysisEnvironment.SetExtent(esriRasterEnvSettingEnum.esriRasterEnvValue, (maskLayer as IGeoDataset).Extent, null);
                rasterAnalysisEnvironment.Mask = maskLayer.FeatureClass as IGeoDataset;
            }
           
            // 創建並返回柵格圖層
            IRasterLayer rasterLayer = new RasterLayerClass();
            rasterLayer.CreateFromRaster(mapAlgebraOp.Execute(expression) as IRaster);
            return rasterLayer;
        }
        public IRasterLayer RasterCalculator(List<IRasterLayer> param, RasterConditionCreator expression)
        {
            return RasterCalculator(param, expression.Result);
        }
        #endregion

        #region 柵格-相減
        /// <summary>
        /// 保存的路徑默認是RasterResultPath
        /// </summary>
        /// <param name="baseMapLayer"></param>
        /// <param name="toCutLayer"></param>
        /// <param name="radio"></param>
        public bool RasterSubtract(RasterLayer baseMapLayer, RasterLayer toCutLayer, double radio)
        {
            try
            {
                SetGPEnvironment();
     
                RasterCalculator RC = new RasterCalculator();
                RC.expression = "\"" + baseMapLayer.FilePath +
                    "\" - Con(IsNull(\"" + toCutLayer.FilePath + "\"),0,1)*" + radio;
                GDBHelper gdbHelper = new GDBHelper(RasterResultPath, true);
                gdbHelper.DeleteRasterLayer();
                gdbHelper.Close();

                RC.output_raster = RasterResultPath;

                m_GP.Execute(RC, null);
                return true;
            }
            catch (Exception ex)
            {
                object sev = null;
                string str2=m_GP.GetMessages(ref sev);
                throw new Exception(str2);
            }
        }

       
        /// <summary>
        /// 柵格計算器,在這裏會刪掉原來的數據
        /// </summary>
        /// <param name="baseMapLayer">用於定義範圍</param>
        /// <param name="toCutLayers"></param>
        /// <param name="radios"></param>
        /// <returns></returns>
        public bool RasterCalculatorExcutor(IRasterLayer baseMapLayer, string expression)
        {
            try
            {
                SetGPEnvironment();
                DeleteExistRasterLayer(RasterResultPath);

                RasterCalculator RC = new RasterCalculator();
                RC.expression = expression;

                RC.output_raster = RasterResultPath;

                m_GP.Execute(RC, null);
                return true;
            }
            catch (Exception ex)
            {
                object sev = null;
                string str2 = m_GP.GetMessages(ref sev);
                throw new Exception(str2);
            }
        }
        /// <summary>
        /// 這個是單值的
        /// </summary>
        /// <param name="baseMapLayer"></param>
        /// <param name="toCutLayers">要裁剪的圖層</param>
        /// <param name="radios">圖層約減的比例</param>
        /// <returns></returns>
        public string GetRasterSubtractExpression(RasterLayer baseMapLayer, List<RasterLayer> toCutLayers, List<double> radios)
        {
            string expression = "\"" + baseMapLayer.FilePath + "\"";
            for (var i = 0; i < toCutLayers.Count; i++)
            {
                expression += "- Con(IsNull(\"" + toCutLayers[i].FilePath + "\"),0,1)*" + radios[i];
            }
            return expression;
        }
        /// <summary>
        /// radioStep的值是從大到小,比如15,8,2
        /// raidoValue是對應的,比如0.4,0.6,0.8
        /// 也就是>15的值是0.4
        /// 最後的值是1
        /// </summary>
        /// <param name="toCutLayer"></param>
        /// <param name="radioStep"></param>
        /// <param name="raidoValue"></param>
        /// <param name="globalRadio"></param>
        /// <returns></returns>
        public string GetRasterSubtractExpression(RasterLayer toCutLayer, double[] radioStep, double[] raidoValue, double globalRadio,bool reverseValue=false,string nullValueExpress="0")
        {
            StringBuilder sb=new StringBuilder();
            sb.Append("Con(IsNull(\"" + toCutLayer.FilePath + "\")," + nullValueExpress + ",");
            for (var i = 0; i < radioStep.Length; i++)
            {
                sb.Append("Con(\"" + toCutLayer.FilePath + "\">" + radioStep[i] + "," + (reverseValue == false ? raidoValue[i] : 1 - raidoValue[i]) + ",");
                if (i == radioStep.Length - 1)
                    sb.Append(reverseValue == false ? "1" : "0");
            }
            for (var i = 0; i < radioStep.Length; i++)
            {
                sb.Append(")");
            }
            sb.Append("*" + globalRadio);
            sb.Append(")");
            return sb.ToString();
        }
        /// <summary>
        /// 獲得減的算法。
        /// </summary>
        /// <param name="toCutLayer"></param>
        /// <param name="globalRadio"></param>
        /// <param name="reverseValue"></param>
        /// <param name="nullValueExpress"></param>
        /// <returns></returns>
        public string GetRasterSubtractExpression(RasterLayer toCutLayer, double globalRadio, bool reverseValue = false, string nullValueExpress = "0")
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("Con(IsNull(\"" + toCutLayer.FilePath + "\")," + nullValueExpress + ",");
            if (reverseValue == false)
                sb.Append("\"" + toCutLayer.FilePath + "\"");
            else
                sb.Append("(100-\"" + toCutLayer.FilePath + "\")");
            sb.Append(")*" + globalRadio);
            return sb.ToString();
        }
        /// <summary>
        /// 獲得分級的表達式
        /// </summary>
        /// <param name="toCutLayer"></param>
        /// <param name="radioStep"></param>
        /// <param name="raidoValue"></param>
        /// <param name="reverseValue"></param>
        /// <returns></returns>
        public string GetRasterClassifyExpression(RasterLayer toCutLayer, double[] radioStep, double[] raidoValue, bool reverseValue = false)
        {
            return GetRasterClassifyExpression(toCutLayer.FilePath, radioStep, raidoValue, reverseValue);
        }
        /// <summary>
        /// 獲得分級的表達式
        /// </summary>
        /// <param name="toCutLayer"></param>
        /// <param name="radioStep"></param>
        /// <param name="raidoValue"></param>
        /// <param name="reverseValue"></param>
        /// <returns></returns>
        public string GetRasterClassifyExpression(string layerFilePath, double[] radioStep, double[] raidoValue, bool reverseValue=false)
        {
            StringBuilder sb = new StringBuilder();
            for (var i = 0; i < radioStep.Length; i++)
            {
                sb.Append("Con(\"" + layerFilePath + "\">" + radioStep[i] + "," + (reverseValue == false ? raidoValue[i] : 1 - raidoValue[i]) + ",");
                if (i == radioStep.Length - 1)
                    sb.Append(reverseValue == false ? raidoValue[raidoValue.Length - 1] : raidoValue[0]);
            }
            for (var i = 0; i < radioStep.Length; i++)
            {
                sb.Append(")");
            }
            return sb.ToString();
        }
        /// <summary>
        /// 二值切割
        /// </summary>
        /// <param name="layerFilePath"></param>
        /// <param name="splitValue"></param>
        /// <param name="bigValueExpression"></param>
        /// <param name="lessValueExpression"></param>
        /// <returns></returns>
        public string GetRasterClassifyExpression(string layerFilePath, double splitValue, string bigValueExpression,string lessValueExpression)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("Con(\"" + layerFilePath + "\">" + splitValue + "," + bigValueExpression + ","+lessValueExpression+")");
            return sb.ToString();
        }
        /// <summary>
        /// 空非空切割
        /// </summary>
        /// <param name="layerFilePath"></param>
        /// <param name="notNullExpression"></param>
        /// <param name="nulExpression"></param>
        /// <returns></returns>
        public string GetRasterNotNullExpression(string layerFilePath, string notNullExpression, string nulExpression)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("Con(IsNull(\"" + layerFilePath + "\")" + "," + nulExpression + "," + notNullExpression + ")");
            return sb.ToString();
        }
        #endregion

        #region 柵格-裁剪
        /// <summary>
        /// 用要素圖層裁剪柵格圖層
        /// </summary>
        /// <param name="rasterLayer"></param>
        /// <param name="featureLayer"></param>
        /// <param name="outPutPath"></param>
        /// <returns></returns>
        public IRasterLayer RasterClip(IRasterLayer rasterLayer, IFeatureLayer featureLayer, string outPutPath)
        {
            m_GP.OverwriteOutput = true;
            IEnvelope envelope = (featureLayer.FeatureClass as IGeoDataset).Extent;

            var rectangle = envelope.XMin + " " + envelope.YMin + " " + envelope.XMax + " " + envelope.YMax;
            Clip clip = new Clip();
            clip.in_raster = rasterLayer;
            clip.rectangle = rectangle;
            clip.out_raster = outPutPath;
            clip.in_template_dataset = featureLayer;
            clip.clipping_geometry = "ClippingGeometry";
            clip.maintain_clipping_extent = "MAINTAIN_EXTENT";

            m_GP.Execute(clip, this.m_cancelHandler);

            IRasterLayer resultLayer = RasterHelper.GetRasterLayer(outPutPath);
            return resultLayer;

        }
        #endregion

        #region 柵格-數據運算
        /// <summary>
        /// 乘冪運算
        /// </summary>
        /// <param name="rasterLayer">需要計算的柵格圖層</param>
        /// <param name="index">底數</param>
        /// <returns></returns>
        public IRasterLayer CaculatorPow(IRasterLayer rasterLayer, double index)
        {
            IMathOp mathOp = new RasterMathOpsClass();
            var geoDataset = mathOp.Power(rasterLayer.Raster as IGeoDataset, index);
            IRasterLayer layer = new RasterLayerClass();
            layer.CreateFromRaster(geoDataset as IRaster);
            return layer;
        }
        public IRasterLayer Abs(IRasterLayer rasterLayer)
        {
            IMathOp mathOp = new RasterMathOpsClass();
            var geoDataset = mathOp.Abs(rasterLayer.Raster as IGeoDataset);
            IRasterLayer layer = new RasterLayerClass();
            layer.CreateFromRaster(geoDataset as IRaster);
            return layer;
        }

        /// <summary>
        /// 條件判斷Nodata柵格,是Nodata返回1,不是則返回0
        /// </summary>
        /// <param name="rasterLayer"></param>
        /// <returns></returns>
        public IRasterLayer GetNullRaster(IRasterLayer rasterLayer)
        {
            ILogicalOp logicalOp = new RasterMathOpsClass();
            IGeoDataset geoDataset = logicalOp.IsNull(rasterLayer.Raster as IGeoDataset);
            IRasterLayer resultlayer = new RasterLayerClass();
            resultlayer.CreateFromRaster(geoDataset as IRaster);
            return resultlayer;
        }
        #endregion

        #region 柵格-矢量轉柵格
        public string Rasterify(IFeatureLayer featureLayer, string value_field, string outpath, string cell_assignment, string priority_field, double cellsize, bool useFeatureToRaster = false)
        {
            SetGPEnvironment();
            m_GP.OverwriteOutput = true;
            if (useFeatureToRaster)
            {
                try
                {
                    var gp = new FeatureToRaster();
                    gp.in_features = featureLayer.FeatureClass;
                    gp.out_raster = outpath;
                    gp.field = value_field;
                    gp.cell_size = cellsize;

                    DeleteExistRasterLayer(outpath);

                    var result = m_GP.Execute(gp, this.m_cancelHandler);
                    return outpath;
                }
                catch (Exception ex)
                {
                    object sev = null;
                    string str2 = m_GP.GetMessages(ref sev);
                    throw new Exception(str2);
                }
            }
            else
            {
                try
                {
                    var gp = new PolygonToRaster();
                    gp.in_features = featureLayer;
                    gp.value_field = value_field;
                    gp.out_rasterdataset = outpath;
                    gp.cell_assignment = cell_assignment;
                    gp.priority_field = priority_field;
                    gp.cellsize = cellsize;

                    DeleteExistRasterLayer(outpath);

                    var result = m_GP.Execute(gp, this.m_cancelHandler);
                    return outpath;
                }
                catch (Exception ex)
                {
                    object sev = null;
                    string str2 = m_GP.GetMessages(ref sev);
                    throw new Exception(str2);
                }
            }
        }

        /// <summary>
        /// 使用原生接口進行柵格化
        /// </summary>
        /// <param name="featureLayer">要素圖層</param>
        /// <param name="valueField">柵格化字段名稱</param>
        /// <param name="outputRasterFolderPath">輸出tif文件全路徑</param>
        /// <param name="cellSize">可選參數|與座標系有關。像元分辨率,默認30</param>
        /// <returns></returns>
        public IRasterLayer Rasterify(IFeatureLayer featureLayer, string valueField,  double cellSize = 30)
        {
            IConversionOp conversionOp = new RasterConversionOpClass();
            IFeatureClassDescriptor descriptor = new FeatureClassDescriptorClass();
            descriptor.Create(featureLayer.FeatureClass, null, valueField);

            IGeoDataset geoDataset = descriptor as IGeoDataset;

            IWorkspaceFactory factoryClass = new RasterWorkspaceFactoryClass();
            string outputRasterFolderPath = AG.COM.SDM.Utility.CommonConstString.STR_TempPath + "\\" + "Rasterify\\";
            if(Directory.Exists(outputRasterFolderPath)==false)
            {
                Directory.CreateDirectory(outputRasterFolderPath);
            }
            IWorkspace workspace = factoryClass.OpenFromFile(outputRasterFolderPath, 0);

            IRasterAnalysisEnvironment rasterAnalysisEnvironment = conversionOp as IRasterAnalysisEnvironment;
            rasterAnalysisEnvironment.SetCellSize(esriRasterEnvSettingEnum.esriRasterEnvValue, cellSize);
            rasterAnalysisEnvironment.SetExtent(esriRasterEnvSettingEnum.esriRasterEnvValue, geoDataset.Extent, null);

            string fileName = featureLayer.Name + "柵格";
            int index = 0;
            while (true)
            {
                if (File.Exists(System.IO.Path.Combine(outputRasterFolderPath, fileName+".tif")))
                {
                    fileName = featureLayer.Name + "柵格" + (index++);
                }
                else
                {
                    break;
                }
            }
            

            IRasterDataset resultDataset = conversionOp.ToRasterDataset(geoDataset, "TIFF", workspace, fileName);
            IRasterLayer resultLayer = new RasterLayerClass();
            resultLayer.CreateFromDataset(resultDataset);

            return resultLayer;
        }
        #endregion

        #region 柵格-重分類
        private string ClassifyRasterWithRamap(string rasterLayerPath, string remap,  string resultPath = null,string fieldName = "VALUE")
        {
            try
            {
                resultPath = resultPath == null ? RasterResultPath + "_reclassify" : resultPath;
                DeleteExistRasterLayer(resultPath);

                Reclassify reclassify = new Reclassify(rasterLayerPath, "", null, null);
                reclassify.missing_values = "NODATA";
                reclassify.out_raster = resultPath;
                reclassify.reclass_field = fieldName;
                if(string.IsNullOrEmpty(remap)==false)
                    reclassify.remap = remap;

                var result = m_GP.Execute(reclassify, m_TrackCancel);
                return resultPath;
            }
            catch (Exception ex)
            {
                object sev = null;
                string str2 = m_GP.GetMessages(ref sev);
                throw new Exception(str2);
            }
        }
        public string ClassifyRaster(IRasterLayer rasterLayer, int classCount = 5, bool trimZero = true, string resultPath = null)
        {
            double max, min;
            CommonUtils.GetRasterHelper().GetRasterMinMaxValue(rasterLayer, out max, out min);
            string remap = "";
            if (trimZero)
            {
                remap = min + " 0 0";
                double step = max / (classCount - 1);
                for (var i = 1; i < classCount; i++)
                {
                    remap += ";";
                    remap += (step * (i - 1)) + " " + (step * i) + " " + i;
                }
            }
            else
            {
                double step = (max - min) / classCount;
                for (var i = 0; i < classCount; i++)
                {
                    if (i != 0)
                        remap += ";";
                    remap += (step * i + min) + " " + (step * (i + 1) + min) + " " + i;
                }
            }
            return ClassifyRasterWithRamap(rasterLayer.FilePath, remap, resultPath);
        }
        public string ClassifyRaster(string rasterLayerPath, int classCount = 5, bool trimZero = true, string resultPath = null)
        {
            var rasterLayer = GDBHelper.GetRasterLayer(rasterLayerPath, true);
            return ClassifyRaster(rasterLayer, classCount, trimZero, resultPath);
        }
        /// <summary>
        /// rasterLayerPath 柵格的路徑
        /// fieldsMatch=[{"草地":30},{"林地":50}]
        /// </summary>
        /// <param name="rasterLayerPath"></param>
        /// <param name="fieldsMatch"></param>
        /// <param name="resultPath"></param>
        /// <returns></returns>
        public string ClassifyRaster(string rasterLayerPath, Dictionary<string, int> fieldsMatch, string resultPath = null,string fieldName="VALUE")
        {
            StringBuilder sb = new StringBuilder();
            foreach (string key in fieldsMatch.Keys)
            {
                if (sb.Length != 0)
                    sb.Append(";");
                sb.Append(key + " " + fieldsMatch[key]);
            }
            return ClassifyRasterWithRamap(rasterLayerPath, sb.ToString(), resultPath, fieldName);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="outpath"></param>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        public string ClassifyRaster(string rasterLayerPath, string remap, string resultPath = null, string fieldName = "VALUE")
        {
            return ClassifyRasterWithRamap(rasterLayerPath, remap, resultPath, fieldName);
        }
        #endregion

        #region 柵格-重分類-原生接口
        /// <summary>
        /// 重分類方法
        /// </summary>
        /// <param name="layer"></param>
        /// <param name="reclassifySubRanges"></param>
        public IRasterLayer ReclassifyByRemap(IRasterLayer layer, List<ReclassifySubRange> reclassifySubRanges)
        {
            double statisticsMinimum;
            double statisticsMaximum;
            Common.CommonUtils.GetRasterHelper().GetRasterMinMaxValue(layer.Raster, out statisticsMinimum, out statisticsMaximum);

            INumberRemap numberRemap = new NumberRemapClass();
            IRasterLayer resultLayer = new RasterLayerClass();

            if (statisticsMinimum > reclassifySubRanges[0].StartValue || statisticsMaximum < reclassifySubRanges[reclassifySubRanges.Count].EndValue)
            {
                // 重新調整重分類子範圍列表
                int newStartSubRangeIndex = 0;
                int newEndSubRangeIndex = reclassifySubRanges.Count;
                for (int i = 0; i < reclassifySubRanges.Count; i++)
                {
                    if (statisticsMinimum < reclassifySubRanges[i].StartValue)
                    {
                        newStartSubRangeIndex = i - 1;
                        break;
                    }
                    else
                        continue;
                }
                for (int i = 0; i < reclassifySubRanges.Count; i++)
                {
                    if (statisticsMaximum < reclassifySubRanges[i].EndValue)
                    {
                        newEndSubRangeIndex = i;
                        break;
                    }
                    else
                        continue;
                }
                List<ReclassifySubRange> newReclassifySubRange = reclassifySubRanges.GetRange(newStartSubRangeIndex, newEndSubRangeIndex - newStartSubRangeIndex + 1);
                for (int i = 0; i < newReclassifySubRange.Count; i++)
                {
                    numberRemap.MapRange(newReclassifySubRange[i].StartValue, newReclassifySubRange[i].EndValue, newReclassifySubRange[i].ReclassifyValue);
                }
                IReclassOp reclassOp = new RasterReclassOpClass();
                IRaster resultRaster = reclassOp.ReclassByRemap(layer as IGeoDataset, numberRemap as IRemap, false) as IRaster;

                resultLayer.CreateFromRaster(resultRaster);
            }
            else
            {
                for (int i = 0; i < reclassifySubRanges.Count; i++)
                {
                    numberRemap.MapRange(reclassifySubRanges[i].StartValue, reclassifySubRanges[i].EndValue, reclassifySubRanges[i].ReclassifyValue);
                }
                IReclassOp reclassOp = new RasterReclassOpClass();
                IRaster resultRaster = reclassOp.ReclassByRemap(layer.Raster as IGeoDataset, numberRemap as IRemap, false) as IRaster;

                resultLayer.CreateFromRaster(resultRaster);
            }
            return resultLayer;
        }
       
        #endregion

        #region 柵格-由要素圖層裁剪
        /// <summary>
        /// 由要素圖層裁剪柵格[未測試]
        /// </summary>
        public IRasterLayer ClipByFeatureLayer(IRasterLayer inputLayer, IFeatureLayer maskLayer, string outputRasterPath)
        {
            if (maskLayer == null)
            {
                return inputLayer;
            }
            SetGPEnvironment();
            m_GP.OverwriteOutput = true;

            ExtractByMask extract = new ExtractByMask() {
                in_mask_data = maskLayer, in_raster = inputLayer, out_raster = outputRasterPath
            };

            m_GP.Execute(extract, this.m_cancelHandler);
            IRasterLayer resultLayer = RasterHelper.GetRasterLayer(outputRasterPath);
            return resultLayer;
        }
        #endregion

        #region 柵格-求空間並集
        /// <summary>
        /// 獲得並集的表達式
        /// </summary>
        /// <param name="layer1Expression"></param>
        /// <param name="layer2Expression"></param>
        /// <returns></returns>
        public string GetRasterUnionExpression(string layer1Expression,string layer2Expression)
        {
            string exrepssion = "Con((" + layer1Expression + "+" + layer2Expression + ")>0,1,0)";
            return exrepssion;
        }
        #endregion

        #region 柵格-局域統計-求和
        public string BlockStatisticsRaster(string rasterFilePath, string neighborhoodMeth = "RECTANGLE", int width = 3, string statisticsType = "SUM", string resultPath=null)
        {
            try
            {
                SetGPEnvironment();
                resultPath = resultPath == null ? RasterResultPath + "_blockSts" : resultPath;

                BlockStatistics bs = new BlockStatistics(rasterFilePath, resultPath);
                bs.neighborhood = neighborhoodMeth + " " + width + "  " + width + "  CELL";
                bs.statistics_type = statisticsType;

                m_GP.Execute(bs, this.m_TrackCancel);

                return resultPath;
            }
            catch (Exception err)
            {
                object sev = null;
                string str2 = m_GP.GetMessages(ref sev);
                throw new Exception(str2);
            }
        }
        public IRasterLayer ComputeFocalStatistics(IRasterLayer param, esriGeoAnalysisStatisticsEnum type, int nbrSize = 3)
        {
            IRasterNeighborhood nbrhood = new RasterNeighborhoodClass();
            if (nbrSize == 3)
                nbrhood.SetDefault();
            else
                nbrhood.SetRectangle((double)nbrSize, (double)nbrSize, esriGeoAnalysisUnitsEnum.esriUnitsCells);
            IRasterLayer result = new RasterLayerClass();
            result.CreateFromRaster(new RasterNeighborhoodOpClass().FocalStatistics(param.Raster as IGeoDataset, type, nbrhood, true) as IRaster);
            return result;
        }
        #endregion

        #region 柵格-直方圖統計
        /// <summary>
        /// 根據區域生成統計表
        /// </summary>
        /// <param name="in_zone_Layer">包含區域的圖層</param>
        /// <param name="in_value_raster">要統計的柵格</param>
        /// <param name="zoneField">要統計的區域字段</param>
        /// <param name="tableName"></param>
        /// <returns></returns>
        public  DataTable ZonalHistogram(IFeatureLayer in_zone_Layer, IRasterLayer in_value_raster, string zoneField, string GDBPath,string tableName)
        {
            m_GP.OverwriteOutput = true;

            ZonalHistogram zonalHistogram = new ZonalHistogram();
            zonalHistogram.in_zone_data = in_zone_Layer;
            zonalHistogram.zone_field = zoneField;
            zonalHistogram.in_value_raster = in_value_raster;
            zonalHistogram.out_table = GDBPath + "\\" + tableName;
            m_GP.Execute(zonalHistogram, null);

            var gdbHelper = new GDBHelper(GDBPath);
            gdbHelper.Open();
            IFeatureWorkspace featureWorkspace = gdbHelper.WorkSpace;
            ITable table = featureWorkspace.OpenTable(tableName);
            DataTable dataTable = MyDataConverter.ConvertToDataTable(table);
            gdbHelper.Close();
            return dataTable;
        }
        #endregion

        #region 柵格-分區統計
        /// <summary>
        /// 按區域統計柵格信息
        /// </summary>
        /// <param name="in_zone_Layer"></param>
        /// <param name="in_value_raster"></param>
        /// <param name="zoneField"></param>
        /// <param name="GDBPath"></param>
        /// <param name="tableName"></param>
        /// <returns></returns>
        public DataTable ZonalStatisticsAsTable(IFeatureLayer in_zone_Layer, IRasterLayer in_value_raster, string zoneField, string GDBPath, string tableName)
        {
            m_GP.OverwriteOutput = true;

            ZonalStatisticsAsTable zonalStatistics = new ZonalStatisticsAsTable();
            zonalStatistics.in_zone_data = in_zone_Layer;
            zonalStatistics.zone_field = zoneField;
            zonalStatistics.in_value_raster = in_value_raster;
            zonalStatistics.out_table = GDBPath + "\\"+tableName;
            m_GP.Execute(zonalStatistics, m_TrackCancel);

            var gdbHelper = new GDBHelper(GDBPath);
            gdbHelper.Open();
            IFeatureWorkspace featureWorkspace = gdbHelper.WorkSpace;
            ITable table = featureWorkspace.OpenTable(tableName);
            DataTable dataTable = MyDataConverter.ConvertToDataTable(table);
            gdbHelper.Close();
            return dataTable;
        } 
        #endregion
        #region 柵格-求衆數
        public IRasterLayer ComputerCellStatistics(string rasterLayerDir,List<string> rasterLayerNames,string resultFileName,string statisticsType="MAJORITY")
        {
            try
            {
                m_GP.OverwriteOutput = true;
                m_GP.SetEnvironmentValue("workspace", rasterLayerDir);
                m_GP.SetEnvironmentValue("extent", System.IO.Path.Combine(rasterLayerDir, rasterLayerNames[0]));
                m_GP.SetEnvironmentValue("cellsize", 30);


                var cellStatistics = new CellStatistics();
                cellStatistics.in_rasters_or_constants = String.Join(";", rasterLayerNames.ToArray());
                cellStatistics.out_raster = resultFileName;
                cellStatistics.statistics_type = statisticsType;
                cellStatistics.ignore_nodata = "DATA";

                m_GP.RegisterGeoProcessorEvents(this.m_TrackCancel.Progressor as IGeoProcessorEvents);
                m_GP.Execute(cellStatistics, this.m_TrackCancel);

                var layer = RasterHelper.GetRasterLayer((string)(cellStatistics.out_raster));
                return layer;
            }
            catch (Exception)
            {
                object sev = null;
                string str2 = m_GP.GetMessages(ref sev);
                throw new Exception(str2);
            }
        }
        #endregion

        #region 柵格-填窪
        public void Fill(RasterLayer baseMapLayer,double z=double.Epsilon)
        {
            try
            {
                SetGPEnvironment();
                ESRI.ArcGIS.SpatialAnalystTools.Fill fill = new Fill();
                fill.in_surface_raster = baseMapLayer;
                fill.out_surface_raster = RasterResultPath;
                if (z > double.Epsilon)
                    fill.z_limit = z;
                m_GP.Execute(fill, null);
            }
            catch (Exception ex)
            {
                object sev = null;
                string str2 = m_GP.GetMessages(ref sev);
                throw new Exception(str2);
            }          
        }
        #endregion

        #region 柵格-坡向
        /// <summary>
        /// 柵格/DEM轉坡向圖
        /// </summary>
        public void RasterGetAspect(IRasterLayer baseMapLayer, bool autoSetRender = false)
        {
            try
            {
                 if (m_cancelHandler != null)
                 {
                     m_cancelHandler.SetWaitingMessage("正在計算坡向...");
                 }
                 SetGPEnvironment();
                 var tAspect = new Aspect();
                 tAspect.in_raster = baseMapLayer;
                 tAspect.out_raster = RasterResultPath;
                 m_GP.Execute(tAspect, null);            
            }
            catch (Exception)
            {
                object sev = null;
                string str2 = m_GP.GetMessages(ref sev);
                throw new Exception(str2);
            }           
        }
        #endregion

        #region 柵格-坡度
        /// <summary>
        /// 柵格/DEM轉坡度圖
        /// </summary>
        public void ComputeSlope(IRasterLayer baseMapLayer,string saveFileName, string  measurement="DEGREE",float zFactorScale=1)
        {
            try
            {
                 if (m_cancelHandler != null)
                 {
                     m_cancelHandler.SetWaitingMessage("正在計算坡度...");
                 }
                 SetGPEnvironment();
                 ESRI.ArcGIS.SpatialAnalystTools.Slope tSlope = new Slope();
                 tSlope.in_raster = baseMapLayer;
                 tSlope.out_raster = saveFileName;
                 tSlope.output_measurement = measurement;
                 tSlope.z_factor = zFactorScale;
                 m_GP.Execute(tSlope, null); 
            }
            catch (Exception)
            {
                object sev = null;
                string str2 = m_GP.GetMessages(ref sev);
                throw new Exception(str2);
            }        
        }
        public void ComputeSlope(IRasterLayer baseMapLayer, string saveFileName, bool  isDegree, float zFactorScale = 1)
        {
            ComputeSlope(baseMapLayer, saveFileName, isDegree ? "DEGREE" : "PERCENT_RISE", zFactorScale);
        }
        #endregion

        #region 柵格-距離
        public IRasterLayer ComputeEucDistance(IRasterLayer roadLayer,string file)
        {
            try
            {
                var compute = new ESRI.ArcGIS.SpatialAnalystTools.EucDistance();
                compute.in_source_data = roadLayer;
                compute.out_distance_raster = file;
                m_GP.Execute(compute, this.m_cancelHandler);
                IRasterLayer layer = new RasterLayerClass();
                layer.CreateFromFilePath(file);
                return layer;
            }
            catch (Exception)
            {
                object sev = null;
                string str2 = m_GP.GetMessages(ref sev);
                throw new Exception(str2);
            }
        }
        #endregion

        #region 柵格-整型
        /// <summary>
        /// 柵格轉整型(柵格的值是浮點型時無法轉出面)
        /// </summary>
        public void RasterValueToInt(object pInputRaster)
        {
            try
            {
                if (m_cancelHandler != null)
                {
                    m_cancelHandler.SetWaitingMessage("浮點型柵格轉爲整形...");
                }
                SetGPEnvironment();
                ESRI.ArcGIS.SpatialAnalystTools.Int tInt = new Int();
                tInt.in_raster_or_constant = pInputRaster;
                tInt.out_raster = RasterResultPath;
                m_GP.Execute(tInt, null); 
            }
            catch (Exception)
            {
                object sev = null;
                string str2 = m_GP.GetMessages(ref sev);
                throw new Exception(str2);
            }          
        } 
        #endregion

        #region 柵格-轉面
         /// <summary>
        /// 柵格轉要素面
        /// </summary>
        public IFeatureClass RasterConvertFeaPolygon(IRasterLayer baseMapLayer)
        {                                 
            try
            {
                SetGPEnvironment();
                if (m_cancelHandler != null)
                {
                    m_cancelHandler.SetWaitingMessage("柵格轉要素面...");
                }
                ESRI.ArcGIS.ConversionTools.RasterToPolygon tRasterToPolygon = new RasterToPolygon();

                tRasterToPolygon.in_raster = baseMapLayer;
                tRasterToPolygon.raster_field = "VALUE";
                tRasterToPolygon.out_polygon_features = RasterResultPath;
                tRasterToPolygon.simplify = "SIMPLIFY";
                IGeoProcessorResult gpResult =
                    m_GP.Execute(tRasterToPolygon as IGPProcess, m_TrackCancel) as IGeoProcessorResult;
                return DecodeResultClass(gpResult);
            }
            catch (Exception err) { LogGPMessage(); if (m_throwException) throw err; return null; }
        }
        #endregion

        #region 插值-IDW
        /// <summary>
        /// 反距離權重(IDW)插值 不檢查要素類及其他數據的質量,請在調用前做好異常處理
        /// </summary>
        /// <param name="layer">待插值的點要素圖層</param>
        /// <param name="regionLayer">插值範圍區域圖層</param>
        /// <param name="interpolationFieldName">待插值字段</param>
        /// <param name="power">可選參數|反距離的階數,默認2階,1~12階可選</param>
        /// <param name="cellSize">可選參數|插值結果柵格的像元分辨率, 默認30</param>
        /// <param name="searchRadiusPointCount">可選參數|插值時搜索的半徑點數, 默認12個</param>
        public IRasterLayer IDW(IFeatureLayer layer, IFeatureLayer regionLayer,string interpolationFieldName,int power = 2,float cellSize = 30,int searchRadiusPointCount = 12)
        {
            return IDW(layer.FeatureClass, regionLayer, interpolationFieldName, power, cellSize, searchRadiusPointCount);
        }
        public IRasterLayer IDW(IFeatureClass featureClass, IFeatureLayer regionLayer, string interpolationFieldName, int power = 2, float cellSize = 30, int searchRadiusPointCount = 12)
        {
            IInterpolationOp _interpolationOp = new RasterInterpolationOpClass();
            // 設置要素類描述對象
            IFeatureClassDescriptor featureClassDescriptor = new FeatureClassDescriptorClass();
            featureClassDescriptor.Create(featureClass, null, interpolationFieldName);
            // 設置搜索半徑點數
            IRasterRadius rasterRadius = new RasterRadiusClass();
            rasterRadius.SetVariable(searchRadiusPointCount, null);
            // 設置柵格分析環境
            IRasterAnalysisEnvironment rasterAnalysisEnvironment = _interpolationOp as IRasterAnalysisEnvironment;
            rasterAnalysisEnvironment.SetCellSize(esriRasterEnvSettingEnum.esriRasterEnvValue, cellSize as object);
            rasterAnalysisEnvironment.SetExtent(esriRasterEnvSettingEnum.esriRasterEnvValue, (regionLayer.FeatureClass as IGeoDataset).Extent as object, null);
            rasterAnalysisEnvironment.Mask = regionLayer.FeatureClass as IGeoDataset;
            // 執行分析
            IGeoDataset geoDataset = _interpolationOp.IDW(featureClassDescriptor as IGeoDataset, power, rasterRadius, null);
            IRasterLayer resultLayer = new RasterLayerClass();
            resultLayer.CreateFromRaster(geoDataset as IRaster);

            return resultLayer;
        }
        #endregion

        #region 插值-趨勢面
        /// <summary>
        /// 趨勢面插值 默認使用最鄰近插值,階數默認4階
        /// </summary>
        /// <param name="layer">待插值要素圖層</param>
        /// <param name="regionLayer">插值範圍圖層</param>
        /// <param name="interpolationFieldName">待插值的字段名</param>
        /// <param name="trendType">可選參數|迴歸方法, 默認執行多項式迴歸</param>
        /// <param name="order">可選參數|階數,1~12階可選,默認3階,越高越平滑但是耗時越長</param>        
        /// <param name="cellSize">可選參數|插值結果柵格的像元分辨率, 默認30</param>
        public IRasterLayer Trend(IFeatureLayer layer,IFeatureLayer regionLayer,string interpolationFieldName,esriGeoAnalysisTrendEnum trendType= esriGeoAnalysisTrendEnum.esriGeoAnalysisLinearTrend,int order = 4,double cellSize = 30)
        {
            IInterpolationOp _interpolationOp = new RasterInterpolationOpClass();
            // 設置要素類描述對象
            IFeatureClassDescriptor featureClassDescriptor = new FeatureClassDescriptorClass();
            featureClassDescriptor.Create(layer.FeatureClass, null, interpolationFieldName);

            // 設置柵格分析環境
            IRasterAnalysisEnvironment rasterAnalysisEnvironment = _interpolationOp as IRasterAnalysisEnvironment;
            rasterAnalysisEnvironment.SetCellSize(esriRasterEnvSettingEnum.esriRasterEnvValue, cellSize as object);
            rasterAnalysisEnvironment.SetExtent(esriRasterEnvSettingEnum.esriRasterEnvValue, (regionLayer.FeatureClass as IGeoDataset).Extent as object, null);
            rasterAnalysisEnvironment.Mask = regionLayer.FeatureClass as IGeoDataset;

            IRaster result = _interpolationOp.Trend(
                featureClassDescriptor as IGeoDataset,
                trendType, order) as IRaster;
            IRasterLayer resultLayer = new RasterLayerClass();
            resultLayer.CreateFromRaster(result);

            return resultLayer;
        }
        #endregion

        #region 選擇對象
        private FeatureLayerClass ApplyQueryFilter(IFeatureClass pFeatureClass, IQueryFilter pQueryFilter)
        {
            FeatureLayerClass pFeatureLayer = new FeatureLayerClass();
            pFeatureLayer.Name = pFeatureClass.AliasName;
            pFeatureLayer.FeatureClass = pFeatureClass;
            if (pQueryFilter != null)
            {
                IFeatureSelection pFeatureSelection = pFeatureLayer as IFeatureSelection;
                pFeatureSelection.SelectFeatures(pQueryFilter, esriSelectionResultEnum.esriSelectionResultNew, false);
            }
            return pFeatureLayer;
        }
        #endregion

        #region 複製圖層
        /// <summary>
        /// 通過原路徑複製圖層到目標路徑
        /// </summary>
        /// <param name="sourceLayerPath"></param>
        /// <param name="targetLayerPath"></param>
        public bool CopyLayer(string sourceLayerPath,string targetLayerPath)
        {
            SetGPEnvironment();
          
            try
            {               
                if (!ReleaseLock(sourceLayerPath))
                {
                    MessageBox.Show("嘗試關閉資源鎖定時異常");
                    return false;
                }
                else
                {
                    var copyLayerTool = new ESRI.ArcGIS.DataManagementTools.Copy(sourceLayerPath, targetLayerPath);
                    m_GP.Execute(copyLayerTool, m_TrackCancel);
                    return true;
                }
            }
            catch (Exception err)
            {
                object sev = null;
                string str2 = m_GP.GetMessages(ref sev);
                throw new Exception(str2);
            }
        }
        #endregion

        #region 刪除圖層
        public bool DeleteLayer(string targetLayerPath)
        {
            SetGPEnvironment();
            try
            {               
                if (!ReleaseLock(targetLayerPath))
                {
                    return false;
                }
                else
                {
                    var deleteLayer = new ESRI.ArcGIS.DataManagementTools.Delete(targetLayerPath);
                    m_GP.Execute(deleteLayer, m_TrackCancel);
                    return true;
                }
            }
            catch (Exception)
            {
                object sev = null;
                string str2 = m_GP.GetMessages(ref sev);
                throw new Exception(str2);
            }
        }
        #endregion

        #region 設置GP的環境變量
        /// <summary>
        /// 設置GP的環境變量
        /// </summary>
        private void SetGPEnvironment()
        {
            object obj = null;
            if (m_GP == null) return;

            m_GP.ClearMessages();
            m_GP.OverwriteOutput = base.OverwriteOutput;

            obj = m_GP.GetEnvironmentValue("OutputZFlag");
            m_GP.SetEnvironmentValue("OutputZFlag", base.ZFlag.ToString());

            obj = m_GP.GetEnvironmentValue("OutputMFlag");
            m_GP.SetEnvironmentValue("OutputMFlag", base.MFlag.ToString());
        }
        /// <summary>
        /// 設置GP工具的分析範圍
        /// </summary>
        /// <param name="layer"></param>
        public void SetGPEnvironment(IRasterLayer layer)
        {
            SetGPEnvironment();

            m_GP.SetEnvironmentValue("Extent", layer.FilePath);          
        }
    
        /// <summary>
        /// 設置GP工具的工作環境
        /// </summary>
        /// <param name="filePath"></param>
        public void SetGPWorkspace(string filePath)
        {
            m_GP.SetEnvironmentValue("workspace", filePath);
        }
        /// <summary>
        /// 設置研究的範圍
        /// </summary>
        /// <param name="layerExtent"></param>
        public void SetGPMask(IRasterLayer layer)
        {
            m_GP.SetEnvironmentValue("Mask", layer.FilePath);
        }

        private void DeleteExistRasterLayer(string filePath)
        {
            GDBHelper gdbHelper = new GDBHelper(filePath, true);
            gdbHelper.DeleteRasterLayer();
            gdbHelper.Close();
        }
        /// <summary>
        /// 顯示GP的消息
        /// </summary>
        /// <param name="gp"></param>
        /// <param name="showMessageBox"></param>
        /// <returns></returns>
        public static string ShowGPFileMessage(Geoprocessor gp,bool showMessageBox=true)
        {
            object sev = null;
            string str2 = gp.GetMessages(ref sev);
            if (showMessageBox)
            {
                if(str2!=null)
                    MessageBox.Show(str2);
                else
                    MessageBox.Show("處理出錯.ESRI沒有告訴我原因,沒人知道");
            }
            return str2;
        }
        #endregion

        #region 其他
        private static int m_cellNo = 0;
        public void SetClipResultPathRandomName()
        {
            string randomName = DateTime.Now.ToString("hhmmss") + (m_cellNo++);
            ClipResultPath = AG.COM.SDM.Utility.CommonConstString.STR_TempPath + "\\CATemp.gdb\\CATemp_Clip" + randomName;
        }

        public void SetUnionResultPathRandomName()
        {
            string randomName = DateTime.Now.ToString("hhmmss") + (m_cellNo++);
            UnionResultPath = AG.COM.SDM.Utility.CommonConstString.STR_TempPath + "\\CATemp.gdb\\Uinon" + randomName;
        }
 
        public void SetBufferResultPathRandomName()
        {
            string randomName = DateTime.Now.ToString("hhmmss") + (m_cellNo++);
            BufferResultPath = AG.COM.SDM.Utility.CommonConstString.STR_TempPath + "\\CATemp.gdb\\Buffer" + randomName;
        }

        public void SetIntersectResultPathRandomName()
        {
            string randomName = DateTime.Now.ToString("hhmmss") + (m_cellNo++);
            IntersectResultPath = AG.COM.SDM.Utility.CommonConstString.STR_TempPath + "\\CATemp.gdb\\Intersect" + randomName;
        }
        /// <summary>
        /// 設置柵格的隨機名稱
        /// </summary>
        /// <returns></returns>
        public string SetRasterResultPathPathRandomName()
        {
            string randomName = DateTime.Now.ToString("HHmmss") + (m_cellNo++);
            RasterResultPath = AG.COM.SDM.Utility.CommonConstString.STR_TempPath + "\\CATemp.gdb\\Raster" + randomName;
            return RasterResultPath;
        }

        void ExampleUsingValueTables(Geoprocessor GP)
        {

            // Create a value table with two columns.
            IGpValueTableObject vtobject = new GpValueTableObjectClass();
            vtobject.SetColumns(2);

            // Iterate the enumeration of feature classes and add them to the value table.
            // In this case, the inputs and ranks are being set for Intersect.
            GP.SetEnvironmentValue("workspace", @"C:\GP\PortlandOR.gdb");
            IGpEnumList fcColl = GP.ListFeatureClasses("*", "POLYLINE", "");
            string inputfeatures = fcColl.Next();
            object row = "";

            while (inputfeatures != "")
            {

                if (inputfeatures == "streets")
                {

                    row = inputfeatures + " 1";
                    vtobject.AddRow(ref row);

                }
                else
                {

                    row = inputfeatures + " 2";
                    vtobject.AddRow(ref row);

                }

                inputfeatures = fcColl.Next();

            }

            IVariantArray pVarArray = new VarArrayClass();
            pVarArray.Add(vtobject);
            pVarArray.Add("C:\\Gp\\PortlandOR.gdb\\streets_bike");

            // Execute the Intersect tool.
            GP.Execute("intersect_analysis", pVarArray, null);

        }
        private string LogGPMessage()
        {
            StringBuilder builder = new StringBuilder();
            if (m_GP != null)
            {
                for (int i = 0; i < m_GP.MessageCount; i++)
                {
                    builder.Append(m_GP.GetMessage(i));
                }

                m_GP.ClearMessages();
            }
            return builder.ToString();
        }

        IFeatureClass DecodeResultClass(IGeoProcessorResult gpResult)
        {
            IQueryFilter pQueryFilter = null;
            IFeatureClass pFeatureClass = null;
            IGPUtilities gpUtilities = new GPUtilitiesClass();
            gpUtilities.DecodeFeatureLayer(gpResult.GetOutput(0), out pFeatureClass, out pQueryFilter);
            return pFeatureClass;
        }

        ILayer DecodeResultILayer(IGeoProcessorResult gpResult)
        {
            ILayer layer = null;
            IGPUtilities gpUtilities = new GPUtilitiesClass();
            if (gpUtilities.Exists(gpResult.GetOutput(0)))
                layer = gpUtilities.DecodeLayer(gpResult.GetOutput(0));
            return layer;
        }
        #endregion

        #region 釋放
        /// <summary>
        /// 釋放方案鎖
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        private bool ReleaseLock(string path)
        {
            IWorkspaceFactory2 ipWsFactory = null;
            IWorkspaceFactoryLockControl ipWsFactoryLock = null;
            IWorkspace ipWorkspace = null;
            string layername = string.Empty;
            string fileworkspace = string.Empty;
            try
            {
                bool isscuceed= AnalysisPath(path, ref fileworkspace, ref layername);
                if (isscuceed == false) return false;
                string extension = System.IO.Path.GetExtension(fileworkspace);
                switch (extension)
                {
                    case ".gdb":
                        ipWsFactory = new FileGDBWorkspaceFactoryClass();
                        break;
                    case ".shp":
                        ipWsFactory = new ShapefileWorkspaceFactoryClass();
                        break;
                    case ".mdb":
                        ipWsFactory = new AccessWorkspaceFactoryClass();
                        break;
                    default:
                        break;
                }
                //獲取資源鎖定  
                ipWsFactoryLock = (IWorkspaceFactoryLockControl)ipWsFactory;

                if (ipWsFactoryLock.SchemaLockingEnabled)
                {
                    ipWsFactoryLock.DisableSchemaLocking();
                }
                String strConn = "DATABASE=" + fileworkspace;
                ipWorkspace = ipWsFactory.OpenFromString(strConn, 0);
                ReleaseLayer(ipWorkspace, layername);
                return true;
            }
            catch
            {
                return false;
            }
            finally
            {
                CommonUtils.CloseComObject(ipWorkspace);
                CommonUtils.CloseComObject(ipWsFactory);
                CommonUtils.CloseComObject(ipWsFactoryLock);
            }
        }

        private bool AnalysisPath(string path,ref string workSpacePath,ref string layerName)
        {
            try
            {
                if (String.IsNullOrEmpty(path))
                    return false;
                if (Regex.Match(path, @"\S*.shp").ToString() != "")
                {
                    workSpacePath = Regex.Match(path, @"\S*.shp").ToString();
                    layerName = path.Substring(path.LastIndexOf("\\") + 1);
                    layerName = layerName.Replace(".shp","");
                }
                else if (Regex.Match(path, @"\S*.gdb").ToString() != "")
                {
                    workSpacePath = Regex.Match(path, @"\S*.gdb").ToString();
                    layerName = path.Substring(path.LastIndexOf("\\") + 1);
                }
                else if (Regex.Match(path, @"\S*.mdb").ToString() != "")
                {
                    workSpacePath = Regex.Match(path, @"\S*.mdb").ToString();
                    layerName = path.Substring(path.LastIndexOf("\\") + 1);
                }
                return true;
            }
            catch (Exception)
            {
                return false;
            }          
        }

        private bool ReleaseLayer(IWorkspace ipWorkSpace,string layerName)
        {

            if (ReleaseIFeatureClass(ipWorkSpace, layerName))
            {
                return true;
            }
            else if (ReleaseIRaster(ipWorkSpace, layerName))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private bool ReleaseIFeatureClass(IWorkspace ipWorkspace, string layerName)
        {
            //如果是矢量數據
            IFeatureWorkspace featureWorkSpace = null;
            IFeatureClass pFeatureClass = null;
            try
            {
                featureWorkSpace = ipWorkspace as IFeatureWorkspace;
                pFeatureClass = featureWorkSpace.OpenFeatureClass(layerName);
                return true;
            }
            catch (Exception)
            {
                return false;
            }
            finally
            {              
                CommonUtils.CloseComObject(pFeatureClass);
                CommonUtils.CloseComObject(featureWorkSpace);
            }

        }

        private bool ReleaseIRaster(IWorkspace ipWorkSpace, string layerName)
        {
            //如果是柵格數據
            IRasterWorkspace pRasterWorkspace = null;
            IRasterDataset pRasterDataset = null;
            try
            {
                pRasterWorkspace = ipWorkSpace as IRasterWorkspace;
                pRasterDataset = pRasterWorkspace.OpenRasterDataset(layerName);
                return true;

            }
            catch (Exception)
            {
                return false;
            }
            finally
            {
                CommonUtils.CloseComObject(pRasterDataset);
                CommonUtils.CloseComObject(pRasterWorkspace);              
            }
        }
        #endregion
    }
    public interface IGeoTopology
    {
        void DropZ(IGeometry geo);

        void DropM(IGeometry geo);

        IGeometry Union(IGeometry source, IGeometry other);

        IGeometry Union<T>(List<T> lst) where T : IGeometry;

        IGeometry Union(IGeometryArray geoArray);

        IGeometry Union(IEnumGeometry geoEnum);

        IGeometry Erase(IGeometry source, IGeometry byother);

        IGeometry Interset(IGeometry source, IGeometry other);

        IGeometry SymmetricDifference(IGeometry source, IGeometry other);

        void Simplify(IGeometry target);
    }
    public class GeoTopology : EnvironmentClass, IGeoTopology
    {
        void Prepare(IGeometry source, IGeometry other, ref IGeometry pClone1, ref IGeometry pClone2)
        {
            pClone1 = (source as IClone).Clone() as IGeometry;
            pClone2 = (other as IClone).Clone() as IGeometry;

            if (pClone1.SpatialReference != pClone2.SpatialReference)
            {
                if (pClone1.SpatialReference == null
                    || String.IsNullOrEmpty(pClone1.SpatialReference.Name)
                    || pClone1.SpatialReference.Name.ToUpper().Contains("UNKNOW"))
                {
                    pClone1.SpatialReference = pClone2.SpatialReference;
                }
                else
                {
                    pClone2.SpatialReference = pClone1.SpatialReference;
                }
            }

            ITopologicalOperator2 pToplogicalOperator1 = pClone1 as ITopologicalOperator2;
            pToplogicalOperator1.IsKnownSimple_2 = false;
            try
            {
                pToplogicalOperator1.Simplify();
            }
            catch { }
            pClone1.SnapToSpatialReference();

            ITopologicalOperator2 pToplogicalOperator2 = pClone2 as ITopologicalOperator2;
            pToplogicalOperator2.IsKnownSimple_2 = false;
            pToplogicalOperator2.Simplify();

            pClone2.SnapToSpatialReference();
        }

        #region IGeoTopology 成員

        public void DropZ(IGeometry geo)
        {
            IZAware pZAware = geo as IZAware;
            if (pZAware == null) return;

            if (pZAware.ZAware)
            {
                pZAware.DropZs();
                pZAware.ZAware = false;
            }
        }

        public void DropM(IGeometry geo)
        {
            IMAware pMAware = geo as IMAware;
            if (pMAware == null) return;

            if (pMAware.MAware)
            {
                pMAware.DropMs();
                pMAware.MAware = false;
            }
        }

        public IGeometry Union(IGeometry source, IGeometry other)
        {
            IGeometry pClone1 = null;
            IGeometry pClone2 = null;
            IGeometry output = null;
            try
            {
                Prepare(source, other, ref pClone1, ref pClone2);

                ITopologicalOperator2 pToplogicalOperator1 = pClone1 as ITopologicalOperator2;

                output = pToplogicalOperator1.Union(pClone2);
            }
            catch (Exception err) { output = null; if (m_throwException) throw err; }
            finally
            {
                if (pClone1 != null)
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(pClone1);
                if (pClone2 != null)
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(pClone2);
            }
            return output;
        }

        public IGeometry Union<T>(List<T> lst) where T : IGeometry
        {
            try
            {
                if (lst == null || lst.Count < 1) return null;

                if (lst.Count == 1) return lst[0];

                object missing = Type.Missing;
                ITopologicalOperator2 temp = null;
                IGeometryCollection geoEnum = new GeometryBagClass();
                for (int i = 0; i < lst.Count; i++)
                {
                    temp = lst[i] as ITopologicalOperator2;
                    if (!temp.IsKnownSimple) temp.Simplify();
                    geoEnum.AddGeometry(temp as IGeometry, ref missing, ref missing);
                }

                return Union(geoEnum as IEnumGeometry);
            }
            catch (Exception err) { if (m_throwException) throw err;  return null; }
        }

        public IGeometry Union(IGeometryArray geoArray)
        {
            try
            {
                if (geoArray == null || geoArray.Count < 1) return null;
                if (geoArray.Count == 1) return geoArray.get_Element(0);

                object missing = Type.Missing;
                ITopologicalOperator2 temp = null;
                IGeometryCollection geoEnum = new GeometryBagClass();
                for (int i = 0; i < geoArray.Count; i++)
                {
                    temp = geoArray.get_Element(i) as ITopologicalOperator2;
                    if (!temp.IsKnownSimple) temp.Simplify(); //確保每個圖形Simple化(假如Polygon的面積爲負,則返回永遠是Empty圖形)
                    geoEnum.AddGeometry(temp as IGeometry, ref missing, ref missing);
                }

                return Union(geoEnum as IEnumGeometry);
            }
            catch (Exception err) { if (m_throwException) throw err; return null; }
        }

        public IGeometry Union(IEnumGeometry geoEnum)
        {
            try
            {
                if (geoEnum == null || geoEnum.Count < 1) return null;

                IGeometry geo = null;

                geoEnum.Reset();
                IGeometry src = geoEnum.Next();
                geoEnum.Reset();
                if (geoEnum.Count == 1) return src;

                switch (src.GeometryType)
                {
                    case esriGeometryType.esriGeometryPolygon:
                        geo = new PolygonClass();
                        break;
                    case esriGeometryType.esriGeometryPolyline:
                        geo = new PolylineClass();
                        break;
                    case esriGeometryType.esriGeometryPoint:
                        geo = new PointClass();
                        break;
                    default:
                        throw new Exception("不支持類型" + src.GeometryType.ToString());
                }

                ITopologicalOperator2 unionTopo = geo as ITopologicalOperator2;
                unionTopo.ConstructUnion(geoEnum as IEnumGeometry);
                return geo;
            }
            catch (Exception err) { if (m_throwException) throw err;  return null; }
        }

        public IGeometry Erase(IGeometry source, IGeometry byother)
        {
            IGeometry pClone1 = null;
            IGeometry pClone2 = null;
            IGeometry output = null;
            try
            {
                Prepare(source, byother, ref pClone1, ref pClone2);
                ITopologicalOperator2 pToplogicalOperator1 = pClone1 as ITopologicalOperator2;
                output = pToplogicalOperator1.Difference(pClone2);
            }
            catch (Exception err) { output = null; if (m_throwException) throw err;  }
            finally
            {
                if (pClone1 != null)
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(pClone1);
                if (pClone2 != null)
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(pClone2);
            }
            return output;
        }

        public IGeometry Interset(IGeometry source, IGeometry other)
        {
            IGeometry pClone1 = null;
            IGeometry pClone2 = null;
            IGeometry output = null;
            try
            {
                Prepare(source, other, ref pClone1, ref pClone2);
                ITopologicalOperator2 pToplogicalOperator1 = pClone1 as ITopologicalOperator2;
                int dimension = Math.Min((int)pClone1.Dimension, (int)pClone2.Dimension);
                output = pToplogicalOperator1.Intersect(pClone2, (esriGeometryDimension)dimension);
            }
            catch (Exception err) { output = null; if (m_throwException) throw err;  }
            finally
            {
                if (pClone1 != null)
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(pClone1);
                if (pClone2 != null)
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(pClone2);
            }
            return output;
        }

        public IGeometry SymmetricDifference(IGeometry source, IGeometry other)
        {
            IGeometry pClone1 = null;
            IGeometry pClone2 = null;
            IGeometry output = null;
            try
            {
                Prepare(source, other, ref pClone1, ref pClone2);
                ITopologicalOperator2 pToplogicalOperator1 = pClone1 as ITopologicalOperator2;
                output = pToplogicalOperator1.SymmetricDifference(pClone2);
            }
            catch (Exception err) { output = null; if (m_throwException) throw err;  }
            finally
            {
                if (pClone1 != null)
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(pClone1);
                if (pClone2 != null)
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(pClone2);
            }
            return output;
        }

        public void Simplify(IGeometry target)
        {
            /*拓撲簡單化
             * 點:無操作;
             * 多點:去除重複點
             * 線:Planarize操作,在交點處打斷,去除重複的
             * 面:去除重複,生成島洞
             * 詳請見幫助文件
             **/

            if (target == null || target.IsEmpty) return;

            ITopologicalOperator2 pTopologicalOperator = target as ITopologicalOperator2;
            if (pTopologicalOperator == null) return;

            pTopologicalOperator.IsKnownSimple_2 = false;
            pTopologicalOperator.Simplify();
        }

        #endregion
    }

    public enum JoinAttributesType
    {
        NO_FID,
        ONLY_FID,
        ALL
    }

    public enum SpatialJoinOperation
    {
        JOIN_ONE_TO_ONE,
        JOIN_ONE_TO_MANY
    }

    public enum MatchOption
    {
        INTERSECT,
        CONTAINS,
        WITHIN
    }

    public interface IProgressStyleSetup
    {
        ProgressBarStyle BarStyle { get; set; }
    }

    public interface IEnumInvalidDataset
    {
        void Reset();
        IInvalidDatasetInfo Next();
    }
    public interface IClassNameChecker
    {
        /// <summary>
        /// 目標工作空間
        /// </summary>
        IWorkspace ValidateWorkspace { set; }

        /// <summary>
        ///  重寫要素類
        /// </summary>
        /// <param name="cName"></param>
        /// <returns></returns>
        bool Overwrite(string cName);

        /// <summary>
        /// 檢查名稱是否已存在
        /// </summary>
        /// <param name="cName"></param>
        /// <returns></returns>
        bool NameIsExist(string cName);

        /// <summary>
        /// 驗證名稱字符是否符合
        /// </summary>
        /// <param name="cName"></param>
        /// <param name="fixedName"></param>
        /// <param name="errMsg"></param>
        /// <returns></returns>
        bool Validate(string cName, out string fixedName, out string errMsg);


        /// <summary>
        /// 自動修正名稱
        /// </summary>
        /// <param name="cName"></param>
        /// <returns></returns>
        string AutoRevise(string cName);

        /// <summary>
        ///  自動修正名稱
        /// </summary>
        /// <param name="names"></param>
        /// <returns></returns>
        string[] AutoRevise(string[] names);

    }

    public class InvalidDatasetInfoClass : IInvalidDatasetInfo
    {
        private IEnumInvalidObject m_EnumInvalidObject = null;
        private string m_ErrorDescription = "";
        private string m_InvalidName = "";

        #region 構造函數
        public InvalidDatasetInfoClass(string err, string name)
        {
            m_ErrorDescription = err;
            m_InvalidName = name;
        }

        public InvalidDatasetInfoClass
            (string err, string name, IEnumInvalidObject pEnumInvalidObject)
            : this(err, name)
        {
            m_EnumInvalidObject = pEnumInvalidObject;
        } 
        #endregion

        #region IInvalidDataInfo 成員

        public string ErrorDescription
        {
            get { return m_ErrorDescription; }
        }

        public string InvalidName
        {
            get { return m_InvalidName; }
        }

        public IEnumInvalidObject EnumInvalidObject
        {
            get { return m_EnumInvalidObject; }
        }

        #endregion
    }

    public class ClassNameChecker : IClassNameChecker
    {
        private IWorkspace m_ValidateWS = null;

        #region IClassNameChecker 成員

        public IWorkspace ValidateWorkspace
        {
            set { m_ValidateWS = value; }
        }

        public bool Overwrite(string cName)
        {
            if (m_ValidateWS == null) return false;

            try
            {
                if (NameIsExist(cName))
                {
                    IFeatureClass pFeatureClass = (m_ValidateWS as IFeatureWorkspace).OpenFeatureClass(cName);
                    (pFeatureClass as IDataset).Delete();
                }
                return true;
            }
            catch (Exception err) { throw new Exception("覆蓋要素類錯誤", err); }
        }

        public bool NameIsExist(string cName)
        {
            if (m_ValidateWS == null || String.IsNullOrEmpty(cName)) return false;

            try
            {
                return (m_ValidateWS as IFeatureWorkspace).OpenFeatureClass(cName) != null;
            }
            catch { return false; }

            //return (m_ValidateWS as IWorkspace2).get_NameExists (esriDatasetType .esriDTFeatureClass ,cName );
        }

        public string AutoRevise(string cName)
        {
            if (m_ValidateWS == null || String.IsNullOrEmpty(cName)) return null;

            try
            {
                string errMsg = "";
                string fixedName = "";
                Validate(cName, out fixedName, out errMsg);

                int count = 0;
                string temp = fixedName;
                while (NameIsExist(temp))
                {
                    count++;
                    temp = fixedName + "_" + count;
                }
                return temp;

            }
            catch (Exception err) { throw new Exception("自動修正要素類名稱錯誤", err); }
        }

        public string[] AutoRevise(string[] names)
        {
            if (names == null || names.Length < 1) return null;

            string[] outnames = new string[names.Length];

            for (int i = 0; i < names.Length; i++)
            {
                outnames[i] = AutoRevise(names[i]);
            }

            return outnames;
        }

        public bool Validate(string cName, out string fixedName, out string errMsg)
        {
            fixedName = ""; errMsg = "";
            if (m_ValidateWS == null || String.IsNullOrEmpty(cName)) return false;

            IFieldChecker pFieldChecker = new FieldCheckerClass();
            pFieldChecker.ValidateWorkspace = m_ValidateWS;
            int errType = pFieldChecker.ValidateTableName(cName, out fixedName);

            switch (errType)
            {
                case 1:
                    errMsg = "Table name is a SQL reserved word.";
                    break;
                case 2:
                    errMsg = "Table name contains an Invalid Character.";
                    break;
                case 4:
                    errMsg = "Table name has an invalid starting character.";
                    break;
                default:
                    errMsg = "";
                    break;
            }

            return errType == 0;
        }

        #endregion
    }

    public class InvalidObjectInfoClass : IInvalidObjectInfo
    {
        private string m_ErrorDescription = "";
        private int m_InvalidObjectID = -1;

        #region 構造函數
        public InvalidObjectInfoClass(string err, int id)
        {
            m_ErrorDescription = err;
            m_InvalidObjectID = id;
        } 
        #endregion

        #region IInvalidObjectInfo 成員

        public string ErrorDescription
        {
            get { return m_ErrorDescription; }
        }

        public int InvalidObjectID
        {
            get { return m_InvalidObjectID; }
        }

        #endregion
    }

    
}
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               

 

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