主要有添加構建拓撲,拓撲中添加要素,添加規則,輸出拓撲錯誤的功能。


使用:


TopologyChecker topocheck = new TopologyChecker(mainlogyDataSet);//傳入要處理的要素數據集
            topocheck.PUB_TopoBuild("testTopo2");//構建拓撲的名字
            topocheck.PUB_AddFeatureClass(null);//將該要素中全部要素都加入拓撲
            //添加規則
            topocheck.PUB_AddRuleToTopology(TopologyChecker.TopoErroType.點要素之間不相交, (topocheck.PUB_GetAllFeatureClass())[2], (topocheck.PUB_GetAllFeatureClass())[0]);
            //獲取生成的拓撲圖層並添加
            axMapControl1.Map.AddLayer(topocheck.PUB_GetTopoLayer());
            axMapControl1.ActiveView.Refresh();



類代碼:注意修改命名空間


using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geoprocessor;
using ESRI.ArcGIS.DataManagementTools;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace EngineWindowsApplication1
{
    class TopologyChecker//功能:構建拓撲,拓撲檢測
    {

        Geoprocessor GP_Tool = new Geoprocessor();//GP運行工具
        ITopology Topology;//生成的拓撲
        IFeatureDataset FeatureDataset_Main;//拓撲所屬的要素數據集
        List<IFeatureClass> LI_FeatureClass = new List<IFeatureClass>();//要素數據集所包含的所有要素類
        List<string> LI_AllErrorInfo = new List<string>();//記錄所有錯誤信息
        ITopologyLayer L_TopoLayer;//記錄拓撲的圖層

        #region 輔助函數
        
        /// <summary>
        /// 獲取拓撲圖層
        /// </summary>
        /// <returns>拓撲圖層Ilayer</returns>
        public ILayer PUB_GetTopoLayer()
        {
            if (L_TopoLayer == null)
            {
                L_TopoLayer = new TopologyLayerClass();
                L_TopoLayer.Topology = Topology;
            }
            return L_TopoLayer as ILayer;
        }

        /// <summary>
        /// 構造拓撲檢驗類
        /// </summary>
        /// <param name="IN_MainlogyDataSet">輸入的要素數據集</param>
        public TopologyChecker(IFeatureDataset IN_MainlogyDataSet)
        {
            FeatureDataset_Main = IN_MainlogyDataSet;
            if (LI_FeatureClass.Count != 0)
                LI_FeatureClass.Clear();
            PUB_GetAllFeatureClass();//獲取數據集中所有包含的要素類
        }

        /// <summary>
        /// 獲取數據集中所有包含的要素類
        /// </summary>
        /// <returns>返回數據集中所有包含的要素類 List<IFeatureClass></returns>
        public List<IFeatureClass> PUB_GetAllFeatureClass()
        {
            if (LI_FeatureClass.Count == 0)
            {
                IFeatureClassContainer Temp_FeatureClassContainer = (IFeatureClassContainer)FeatureDataset_Main;
                IEnumFeatureClass Temp_EnumFeatureClass = Temp_FeatureClassContainer.Classes;
                IFeatureClass Temp_FeatureClass = Temp_EnumFeatureClass.Next();

                while (Temp_FeatureClass != null)
                {
                    LI_FeatureClass.Add(Temp_FeatureClass);
                    Temp_FeatureClass = Temp_EnumFeatureClass.Next();
                }
                if (LI_FeatureClass.Count == 0)
                {
                    MessageBox.Show("空數據集!");
                }
            }

            return LI_FeatureClass;
        }
        #endregion

        #region 構建拓撲

        /// <summary>
        /// 在數據集中構建拓撲(GP方法)
        /// </summary>
        /// <param name="IN_TopoName">要生成拓撲的名稱</param>
        /// <param name="IN_Tolerance">拓撲容差,可選,默認0.001</param>
        public void PUB_TopoBuildWithGP(string IN_TopoName, double IN_Tolerance = 0.001)
        {
            IWorkspace FeatureWorkSpace = FeatureDataset_Main.Workspace;
            ITopologyWorkspace TopoWorkSpace = FeatureWorkSpace as ITopologyWorkspace;
            try//若不存在同名拓撲則添加
            {
                Topology = TopoWorkSpace.OpenTopology(IN_TopoName);
                MessageBox.Show("已存在該拓撲,無法添加!");
            }
            catch
            {
                CreateTopology Topotool = new CreateTopology();//拓撲GP工具
                Topotool.in_dataset = FeatureDataset_Main; ;
                Topotool.out_name = IN_TopoName;
                Topotool.in_cluster_tolerance = IN_Tolerance;
                try
                {
                    GP_Tool.Execute(Topotool, null);
                    Topology = TopoWorkSpace.OpenTopology(IN_TopoName);
                }
                catch (COMException comExc)
                {
                    MessageBox.Show(String.Format("拓撲創建出錯: {0} 描述: {1}", comExc.ErrorCode, comExc.Message));
                }
            }
        }


        /// <summary>
        /// 在數據集中構建拓撲
        /// </summary>
        /// <param name="IN_TopoName">要生成拓撲的名稱</param>
        /// <param name="IN_Tolerance">拓撲容差,可選,默認0.001</param>
        public void PUB_TopoBuild(string IN_TopoName, double IN_Tolerance = 0.001)
        {
            ITopologyContainer topologyContainer = (ITopologyContainer)FeatureDataset_Main;
            try//若不存在同名拓撲則添加
            {
                Topology = topologyContainer.get_TopologyByName(IN_TopoName);
                MessageBox.Show("已存在該拓撲,無法添加!");
            }
            catch
            {
                try
                {
                    Topology = topologyContainer.CreateTopology(IN_TopoName, IN_Tolerance, -1, "");
                }
                catch (COMException comExc)
                {
                    MessageBox.Show(String.Format("拓撲創建出錯: {0} 描述: {1}", comExc.ErrorCode, comExc.Message));
                }
            }
        }

        #endregion

        #region 添加要素類

        /// <summary>
        /// 添加特定要素類到拓撲中(GP方法)
        /// </summary>
        /// <param name="IN_TopologyClass">要添加的要素類的集合。輸入null為該數據集下所有要素類</param>
        /// <param name="IN_XYRank">XY等級,默認為1。可選。</param>
        /// <param name="IN_ZRank">Z等級,默認為1。可選。</param>
        public void PUB_AddFeatureClassWithGP(List<IFeatureClass> IN_TopologyClass, int IN_XYRank = 1, int IN_ZRank = 1)
        {
            if (Topology != null)
            {
                AddFeatureClassToTopology Temp_AddClassToTopo = new AddFeatureClassToTopology();
                Temp_AddClassToTopo.in_topology = Topology;
                Temp_AddClassToTopo.xy_rank = IN_XYRank;
                Temp_AddClassToTopo.z_rank = IN_ZRank;
                if (IN_TopologyClass == null)
                {
                    IN_TopologyClass = LI_FeatureClass;
                }
                foreach (IFeatureClass EachFeatureCLS in IN_TopologyClass)
                {
                    if (LI_FeatureClass.Contains(EachFeatureCLS))
                    {
                        Temp_AddClassToTopo.in_featureclass = EachFeatureCLS;
                        try
                        {
                            GP_Tool.Execute(Temp_AddClassToTopo, null);
                        }
                        catch (COMException comExc)
                        {
                            MessageBox.Show(String.Format(((FeatureClass)EachFeatureCLS).Name + ":添加失敗。 描述: {0}", comExc.Message));
                        }
                    }
                    else
                    {
                        MessageBox.Show("該要素類不屬於目標要素集,無法添加!");
                    }
                }
            }
            else
            {
                MessageBox.Show("請先構建拓撲");
            }
        }


        /// <summary>
        /// 添加特定要素類到拓撲中
        /// </summary>
        /// <param name="IN_TopologyClass">要添加的要素類的集合。輸入null為該數據集下所有要素類</param>
        /// <param name="IN_XYRank">XY等級,默認為1。可選。</param>
        /// <param name="IN_ZRank">Z等級,默認為1。可選。</param>
        /// <param name="IN_Weight">權重,默認為5。可選。</param>
        public void PUB_AddFeatureClass(List<IFeatureClass> IN_TopologyClass, int IN_XYRank = 1, int IN_ZRank = 1, double IN_Weight = 5)
        {
            if (Topology != null)
            {
                if (IN_TopologyClass == null)
                {
                    IN_TopologyClass = LI_FeatureClass;
                }
                foreach (IFeatureClass EachFeatureCLS in IN_TopologyClass)//逐項添加所選的要素類
                {
                    if (LI_FeatureClass.Contains(EachFeatureCLS))//只有相同要素數據集中的要素可以被添加
                    {
                        try
                        {
                            Topology.AddClass(EachFeatureCLS as IClass, IN_Weight, IN_XYRank, IN_ZRank, false);
                        }
                        catch (COMException comExc)
                        {
                            MessageBox.Show(String.Format(((FeatureClass)EachFeatureCLS).Name + ":添加失敗。 描述: {0}", comExc.Message));
                        }
                    }
                    else
                    {
                        MessageBox.Show("該要素類不屬於目標要素集,無法添加!");
                    }
                }
            }
            else
            {
                MessageBox.Show("請先構建拓撲");
            }
        }
        #endregion

        #region 添加規則並檢驗
        //GP法拓撲驗證
        private void PRV_ValidateTopologyWithGP()
        {
            try
            {
                ValidateTopology Temp_Validate = new ValidateTopology(Topology);
                GP_Tool.Execute(Temp_Validate, null);
            }
            catch
            {
                MessageBox.Show("無法完成檢測!");
            }
        }

        /// <summary>
        /// 單要素規則
        /// </summary>
        /// <param name="IN_RuleType">要添加的規則</param>
        /// <param name="IN_FeatureClass">添加規則的要素類</param>
        public void PUB_AddRuleToTopology(TopoErroType IN_RuleType, IFeatureClass IN_FeatureClass)
        {
            if (Topology != null)
            {
                ITopologyRule Temp_TopologyRule = new TopologyRuleClass();
                //設定參數
                Temp_TopologyRule.TopologyRuleType = PRV_ConvertTopologyRuleType(IN_RuleType);
                Temp_TopologyRule.Name = IN_RuleType.ToString();
                Temp_TopologyRule.OriginClassID = IN_FeatureClass.FeatureClassID;
                Temp_TopologyRule.AllOriginSubtypes = true;
                PRV_AddRuleTool(Temp_TopologyRule);
            }
            else
            {
                MessageBox.Show("請先構建拓撲");
            }
        }

        /// <summary>
        /// 雙要素規則
        /// </summary>
        /// <param name="IN_RuleType">要添加的雙要素規則</param>
        /// <param name="IN_FeatureClassA">第一個要素</param>
        /// <param name="IN_FeatureClassB">第二個要素</param>
        public void PUB_AddRuleToTopology(TopoErroType IN_RuleType, IFeatureClass IN_FeatureClassA, IFeatureClass IN_FeatureClassB)
        {
            if (Topology != null)
            {
                ITopologyRule Temp_TopologyRule = new TopologyRuleClass();
                //設定參數
                Temp_TopologyRule.TopologyRuleType = PRV_ConvertTopologyRuleType(IN_RuleType);
                Temp_TopologyRule.Name = IN_RuleType.ToString();
                Temp_TopologyRule.OriginClassID = IN_FeatureClassA.FeatureClassID;
                Temp_TopologyRule.DestinationClassID = IN_FeatureClassB.FeatureClassID;
                Temp_TopologyRule.AllOriginSubtypes = true;
                Temp_TopologyRule.AllDestinationSubtypes = true;
                PRV_AddRuleTool(Temp_TopologyRule);
            }
            else
            {
                MessageBox.Show("請先構建拓撲");
            }
    
        }

        //規則添加工具
        private void PRV_AddRuleTool(ITopologyRule IN_TopologyRule)
        {
             ITopologyRuleContainer Temp_TopologyRuleContainer = (ITopologyRuleContainer)Topology;//構建容器
                try
                {
                    Temp_TopologyRuleContainer.get_CanAddRule(IN_TopologyRule);//不能添加的話直接報錯
                    try
                    {
                        Temp_TopologyRuleContainer.DeleteRule(IN_TopologyRule);//刪除已存在的規則後再添加
                        Temp_TopologyRuleContainer.AddRule(IN_TopologyRule);//規則存在的話直接報錯
                    }
                    catch
                    {
                        Temp_TopologyRuleContainer.AddRule(IN_TopologyRule);
                    }
                }
                catch
                {
                    MessageBox.Show("不支持添加");
                }
                PRV_ValidateTopologyWithGP();//添加完成後自動檢驗
                PUB_GetTopoLayer();//存儲創建的拓撲圖層
                PRV_GetError(IN_TopologyRule);//輸出錯誤
        }
    
        //獲取錯誤信息
        private void PRV_GetError(ITopologyRule IN_TopologyRule)
        {
            if (Topology != null)
            {
                IEnvelope Temp_Envolope = (this.Topology as IGeoDataset).Extent;
                IErrorFeatureContainer Temp_ErrorContainer = Topology as IErrorFeatureContainer;
                //獲取所有信息
                IEnumTopologyErrorFeature Temp_EnumErrorFeature = Temp_ErrorContainer.get_ErrorFeatures(((IGeoDataset)FeatureDataset_Main).SpatialReference, IN_TopologyRule, Temp_Envolope, true, true);
                ITopologyErrorFeature Temp_ErrorFeature = Temp_EnumErrorFeature.Next();
                while (Temp_ErrorFeature != null)
                {
                    IFeature Temp_Feature = Temp_ErrorFeature as IFeature;
                    string Temp_ErrorInfo;
                    if (Temp_ErrorFeature.DestinationClassID != 0)//檢測是否是雙要素規則
                    {
                        Temp_ErrorInfo = Temp_ErrorFeature.OriginOID + "," + Temp_ErrorFeature.DestinationOID;
                    }
                    else
                        Temp_ErrorInfo = Temp_ErrorFeature.OriginOID.ToString();
                    LI_AllErrorInfo.Add(Temp_ErrorInfo);//將錯誤信息加入List
                    MessageBox.Show("錯誤:" + PRV_RecorverTopologyRuleType((int)(Temp_ErrorFeature.TopologyRuleType)) + "\r\n錯誤ID:" + Temp_ErrorInfo);
                    Temp_ErrorFeature = Temp_EnumErrorFeature.Next();
                }
            }
            else
            {
                MessageBox.Show("請先構建拓撲");
            }
        }

        /// <summary>
        /// 提取所有拓撲錯誤信息
        /// </summary>
        /// <returns>錯誤信息集合</returns>
        public List<string> PUB_GetErrorInfo()
        {
            return LI_AllErrorInfo;
        }

        #region 規則翻譯

        //根據錯誤的中文描述轉換成esri拓撲枚舉
        private esriTopologyRuleType PRV_ConvertTopologyRuleType(TopoErroType IN_TopoRuleType)
        {
            esriTopologyRuleType Temp_TopoRuleType;
            switch (IN_TopoRuleType)
            {
                case TopoErroType.面要素之間無空隙:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaNoGaps;
                    break;
                case TopoErroType.任何規則:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTAny;
                    break;
                case TopoErroType.要素大於最小容差:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTFeatureLargerThanClusterTolerance;
                    break;
                case TopoErroType.面要素間無重疊:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaNoOverlap;
                    break;
                case TopoErroType.第二個圖層面要素必須被第一個圖層任一面要素覆蓋:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaCoveredByAreaClass;
                    break;
                case TopoErroType.面要素必須只包含一個點要素:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaContainOnePoint;
                    break;
                case TopoErroType.兩圖層面要素必須互相覆蓋:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaAreaCoverEachOther;
                    break;
                case TopoErroType.第一個圖層面要素必須被第一個圖層任一面要素包含:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaCoveredByArea;
                    break;
                case TopoErroType.圖層間面要素不能相互覆蓋:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaNoOverlapArea;
                    break;
                case TopoErroType.線要素必須跟面圖層邊界的一部分或全部重疊:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineCoveredByAreaBoundary;
                    break;
                case TopoErroType.點要素必須落在面要素邊界上:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTPointCoveredByAreaBoundary;
                    break;
                case TopoErroType.點要素必須落在面要素內:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTPointProperlyInsideArea;
                    break;
                case TopoErroType.線要素間不能有相互重疊部分:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoOverlap;
                    break;
                case TopoErroType.線要素之間不能相交:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoIntersection;
                    break;
                case TopoErroType.線要素不允許有懸掛點:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoDangles;
                    break;
                case TopoErroType.線要素不允許有假節點:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoPseudos;
                    break;
                case TopoErroType.第一個圖層線要素應被第二個線圖層線要素覆蓋:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineCoveredByLineClass;
                    break;
                case TopoErroType.第一個圖層線要素不被第二個線圖層線要素覆蓋:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoOverlapLine;
                    break;
                case TopoErroType.點要素應被線要素覆蓋:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTPointCoveredByLine;
                    break;
                case TopoErroType.點要素應在線要素的端點上:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTPointCoveredByLineEndpoint;
                    break;
                case TopoErroType.面要素邊界必須被線要素覆蓋:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaBoundaryCoveredByLine;
                    break;
                case TopoErroType.面要素的邊界必須被另一面要素邊界覆蓋:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaBoundaryCoveredByAreaBoundary;
                    break;
                case TopoErroType.線要素不能自重疊:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoSelfOverlap;
                    break;
                case TopoErroType.線要素不能自相交:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoSelfIntersect;
                    break;
                case TopoErroType.線要素間不能重疊和相交:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoIntersectOrInteriorTouch;
                    break;
                case TopoErroType.線要素端點必須被點要素覆蓋:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineEndpointCoveredByPoint;
                    break;
                case TopoErroType.面要素內必須包含至少一個點要素:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaContainPoint;
                    break;
                case TopoErroType.線不能是多段:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoMultipart;
                    break;
                case TopoErroType.點要素之間不相交:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTPointDisjoint;
                    break;
                case TopoErroType.線要素必須不相交:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoIntersectLine;
                    break;
                case TopoErroType.線必須不相交或內部接觸:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoIntersectOrInteriorTouchLine;
                    break;
                default:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTAny;//將此規則賦予拓撲會直接報錯
                    break;
            }
            return Temp_TopoRuleType;
        }

        public enum TopoErroType
        {
            任何規則=-1,
            要素大於最小容差 = 0,
            面要素之間無空隙 = 1,
            面要素間無重疊 = 3,
            第二個圖層面要素必須被第一個圖層任一面要素覆蓋 = 4,
            兩圖層面要素必須互相覆蓋 = 5,
            第一個圖層面要素必須被第一個圖層任一面要素包含 = 7,
            圖層間面要素不能相互覆蓋 = 8,
            線要素必須跟面圖層邊界的一部分或全部重疊 = 10,
            線要素必須在面內=11,
            點要素必須落在面要素邊界上 = 13,
            點要素必須落在面要素內 = 15,
            面要素必須只包含一個點要素=16,
            線要素間不能有相互重疊部分 = 19,
            線要素之間不能相交 = 20,
            線要素不允許有懸掛點 = 21,
            線要素不允許有假節點 = 22,
            第一個圖層線要素應被第二個線圖層線要素覆蓋 = 26,
            第一個圖層線要素不被第二個線圖層線要素覆蓋 = 28,
            點要素應被線要素覆蓋 = 29,
            點要素應在線要素的端點上 = 31,
            點要素之間不相交=34,
            點要素重合點要素=35,
            面要素邊界必須被線要素覆蓋 = 37,
            面要素的邊界必須被另一面要素邊界覆蓋 = 38,
            線要素不能自重疊 = 39,
            線要素不能自相交 = 40,
            線要素間不能重疊和相交 = 41,
            線要素端點必須被點要素覆蓋 = 42,
            面要素內必須包含至少一個點要素 = 43,
            線不能是多段 = 44,
            線要素必須不相交=45,
            線必須不相交或內部接觸=46
        };

        //根據錯誤ID獲取對應描述
        private string PRV_RecorverTopologyRuleType(int IN_TopoType)
        {
            //根據枚舉值獲取枚舉名
            string Temp_ErrorDiscripe=Enum.GetName(typeof(TopoErroType), IN_TopoType);
            if (Temp_ErrorDiscripe == null)
                return (IN_TopoType.ToString());//若規則不在列表內則直接返回規則號
            else
                return Temp_ErrorDiscripe;
        }
        #endregion

        #endregion
       
    }
}