主要有添加構建拓撲,拓撲中添加要素,添加規則,輸出拓撲錯誤的功能。
使用:
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
}
}
本文章為轉載內容,我們尊重原作者對文章享有的著作權。如有內容錯誤或侵權問題,歡迎原作者聯繫我們進行內容更正或刪除文章。