using System; using System.Collections.Generic; using System.Data; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading; using ESRI.ArcGIS.Carto; using ESRI.ArcGIS.DataSourcesFile; using ESRI.ArcGIS.DataSourcesGDB; using ESRI.ArcGIS.esriSystem; using ESRI.ArcGIS.Geodatabase; using ESRI.ArcGIS.Geometry; using ESRI.ArcGIS.Geoprocessing; using ESRI.ArcGIS.Geoprocessor; using Kingo.RuleCheck; /* * Model:拓扑检查规则帮助类 * Description:拓扑检查规则帮助类 * Author:陈德文 * Finished:2021年04月21日 */ namespace Kingo.RuleCheck.CheckHelper { /// /// 拓扑帮助类 /// public class DataCheckTopologyHelper { /// /// /// /// /// /// /// /// public static List CreateTopology(List lstTopologyRule,IWorkspace m_Workspace,List lstFeatureClassTabelName, string objectName= "TDBZSJJ") { double tolerance = 0.0001; IFeatureDataset pFeatDS = null; ISchemaLock schemalock = null; ITopology topology = null; try { if (m_Workspace == null) throw new Exception("获取默认工作空间为空!"); pFeatDS = GetFeatureDatasetByName(m_Workspace, objectName); if (pFeatDS == null) { throw new Exception("当前工程数据中不存在【"+ objectName + "】"); } //--------------------------- //判断当前要素集有没有锁 schemalock = (ISchemaLock)pFeatDS; schemalock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock); //获取拓扑 Topology 是否存在 CheckTopologyExist(m_Workspace, pFeatDS, "TopologyDataCheck"); //开始创建拓扑 topology = CreateTopology(pFeatDS, "TopologyDataCheck", tolerance); if (topology == null) throw new Exception("创建拓扑失败"); //添加要素类到拓扑中 List lstFeatureClass = new List(); foreach (string featureClassName in lstFeatureClassTabelName) { IFeatureClass pFatureClass = (m_Workspace as IFeatureWorkspace).OpenFeatureClass(featureClassName); string inFeatureClassPath = System.IO.Path.Combine((pFatureClass as IDataset).Workspace.PathName, pFatureClass.FeatureDataset.Name, featureClassName); topology.AddClass(pFatureClass, 1, 1, 1, false); lstFeatureClass.Add(pFatureClass); } foreach (ITopologyRule topologyRule in lstTopologyRule) { //把topology对象强制转换到ITopologyRuleContainer对象,然后添加拓扑规则 ITopologyRuleContainer topologyRuleContainer = (ITopologyRuleContainer)topology; if (topologyRuleContainer.get_CanAddRule(topologyRule)) { topologyRuleContainer.AddRule(topologyRule); } else { throw new ArgumentException("无法将指定的规则添加到拓扑中"); } } // 获取验证拓扑的范围并且验证拓扑 IGeoDataset geoDataset = (IGeoDataset)topology; IEnvelope envelope = geoDataset.Extent; ValidateTopology(topology, envelope); List result= FindAllErrorFeatures(topology, envelope, lstFeatureClass); System.Runtime.InteropServices.Marshal.ReleaseComObject(geoDataset); foreach (IFeatureClass item in lstFeatureClass) { System.Runtime.InteropServices.Marshal.FinalReleaseComObject(item); } foreach (ITopologyRule rule in lstTopologyRule) { System.Runtime.InteropServices.Marshal.FinalReleaseComObject(rule); } return result; } catch (Exception ex) { throw new Exception("拓扑检查发生异常:" + ex.Message.ToString()); } finally { if (topology != null) { Marshal.ReleaseComObject(topology); } if (m_Workspace != null && pFeatDS != null) { //获取拓扑 Topology 是否存在,存在则删除 CheckTopologyExist(m_Workspace, pFeatDS, "TopologyDataCheck"); } if (schemalock != null) { schemalock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock); Marshal.ReleaseComObject(schemalock); } if (pFeatDS != null) { Marshal.ReleaseComObject(pFeatDS); } if (m_Workspace != null) { Marshal.ReleaseComObject(m_Workspace); } } } /// /// 判断拓扑是否存在,存在则删除 /// /// 工作空间 /// 要素集 /// 拓扑名称 private static void CheckTopologyExist(IWorkspace m_Workspace, IFeatureDataset pFeatDS, string topologyName) { try { if (m_Workspace == null || pFeatDS == null) { return; } bool bTopExists = (m_Workspace as IWorkspace2).get_NameExists(esriDatasetType.esriDTTopology, topologyName); if (bTopExists) { //删除已存在拓扑 ITopologyContainer topologyContainer = (ITopologyContainer)pFeatDS; if (topologyContainer != null) { ITopology topologyTemp = topologyContainer.get_TopologyByName(topologyName); if (topologyTemp != null) { //删除拓扑 IDataset pDatasetTemp = (IDataset)topologyTemp; pDatasetTemp.Delete(); Marshal.ReleaseComObject(pDatasetTemp); } } } } catch (Exception ex) { throw new Exception("删除拓扑失败:" + ex.Message.ToString()); } } //添加拓扑规则 private void AddRuleToTopology(ITopology topology, esriTopologyRuleType ruleType, String ruleName, IFeatureClass featureClass) { // 创建拓扑规则 ITopologyRule topologyRule = new TopologyRuleClass(); topologyRule.TopologyRuleType = ruleType; topologyRule.Name = ruleName; topologyRule.OriginClassID = featureClass.FeatureClassID; topologyRule.AllOriginSubtypes = true; //把topology对象强制转换到ITopologyRuleContainer对象,然后添加拓扑规则 ITopologyRuleContainer topologyRuleContainer = (ITopologyRuleContainer)topology; if (topologyRuleContainer.get_CanAddRule(topologyRule)) { topologyRuleContainer.AddRule(topologyRule); } else { throw new ArgumentException("无法将指定的规则添加到拓扑中"); } } //添加拓扑规则 private void AddRuleToTopology(ITopology topology, esriTopologyRuleType ruleType, String ruleName, IFeatureClass originClass, int originSubtype, IFeatureClass destinationClass, int destinationSubtype) { // 创建拓扑规则 ITopologyRule topologyRule = new TopologyRuleClass(); topologyRule.TopologyRuleType = ruleType; topologyRule.Name = ruleName; topologyRule.OriginClassID = originClass.FeatureClassID; topologyRule.AllOriginSubtypes = true; topologyRule.OriginSubtype = originSubtype; topologyRule.DestinationClassID = destinationClass.FeatureClassID; topologyRule.AllDestinationSubtypes = true; topologyRule.DestinationSubtype = destinationSubtype; //把topology对象强制转换到ITopologyRuleContainer对象,然后添加拓扑规则 ITopologyRuleContainer topologyRuleContainer = (ITopologyRuleContainer)topology; if (topologyRuleContainer.get_CanAddRule(topologyRule)) { topologyRuleContainer.AddRule(topologyRule); } else { throw new ArgumentException("无法将指定的规则添加到拓扑中"); } } /// /// 创建拓扑 /// /// /// /// /// private static ITopology CreateTopology(IFeatureDataset pFtDs, string pTopologyName, double clusterTolerance = 0) { if (pFtDs == null) return null; ISchemaLock schemaLock = (ISchemaLock)pFtDs; try { schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock); // 创建拓扑 ITopologyContainer2 topologyContainer = (ITopologyContainer2)pFtDs; ITopology topology = topologyContainer.CreateTopology(pTopologyName, clusterTolerance == 0 ? topologyContainer.DefaultClusterTolerance : clusterTolerance, -1, ""); return topology; } catch (Exception ex) { throw new Exception("创建拓扑异常:" + ex.Message.ToString()); } finally { schemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock); } } /// /// 通过名称获取要素集 /// /// /// /// public static IFeatureDataset GetFeatureDatasetByName(IWorkspace workspace, string dsName) { string strFeatureDSName = ""; IFeatureDataset pResultFDS = null; IEnumDataset pEnumDS = workspace.get_Datasets(esriDatasetType.esriDTFeatureDataset); pEnumDS.Reset(); IDataset pDS = pEnumDS.Next(); while (!(pDS == null)) { strFeatureDSName = GetFeatureObjectName(pDS.Name); if (strFeatureDSName.Equals(dsName)) { pResultFDS = (IFeatureDataset)pDS; break; } pDS = pEnumDS.Next(); } System.Runtime.InteropServices.Marshal.ReleaseComObject(pEnumDS); return pResultFDS; } /// /// 去掉".",得到名称缩写 /// /// /// private static string GetFeatureObjectName(string objectName) { int index = objectName.LastIndexOf("."); if (index >= 0) { return objectName.Substring(index + 1); } else { return objectName; } } /// /// 检查建立的拓扑 /// /// /// private static void ValidateTopology(ITopology topology, IEnvelope envelope) { // Get the dirty area within the provided envelope. IPolygon locationPolygon = new Polygon() as IPolygon; ISegmentCollection segmentCollection = (ISegmentCollection)locationPolygon; segmentCollection.SetRectangle(envelope); IPolygon polygon = topology.get_DirtyArea(locationPolygon); // If a dirty area exists, validate the topology. if (!polygon.IsEmpty) { // Define the area to validate and validate the topology. IEnvelope areaToValidate = polygon.Envelope; IEnvelope areaValidated = topology.ValidateTopology(areaToValidate); } System.Runtime.InteropServices.Marshal.ReleaseComObject(locationPolygon); System.Runtime.InteropServices.Marshal.ReleaseComObject(polygon); } /// /// 给定拓扑和查找的范围,返回所有的拓扑错误要素 /// /// /// public static List FindAllErrorFeatures(ITopology topology, IEnvelope searchExtent, List lstFeatureClass) { List lstErrorEnity = new List(); try { //获取坐标系 IErrorFeatureContainer errorFeatureContainer = (IErrorFeatureContainer)topology; IGeoDataset geoDataset = (IGeoDataset)topology; ISpatialReference spatialReference = geoDataset.SpatialReference; ITopologyRuleContainer topologyRuleContainer = (ITopologyRuleContainer)topology; //遍历拓扑规则 IEnumRule enumRule = topologyRuleContainer.Rules; enumRule.Reset(); IRule rule = null; while ((rule = enumRule.Next()) != null) { //获取当前拓扑规则的拓扑错误并遍历 ITopologyRule topologyRule = (ITopologyRule)rule; IEnumTopologyErrorFeature enumTopologyErrorFeature = errorFeatureContainer.get_ErrorFeatures(spatialReference, topologyRule, searchExtent, true, true); ITopologyErrorFeature topologyErrorFeature = null; while ((topologyErrorFeature = enumTopologyErrorFeature.Next()) != null) { RuleEntity ruleEntity = new RuleEntity(); ruleEntity.ErrorId = topologyErrorFeature.OriginOID.ToString(); if (topologyErrorFeature.OriginOID <= 0) { if (topologyErrorFeature == null || (topologyErrorFeature as IFeature).ShapeCopy.IsEmpty) { continue; } IGeometryCollection geometryCollection = (topologyErrorFeature as IFeature).ShapeCopy as IGeometryCollection; if (geometryCollection == null) { continue; } //StringBuilder coords = new StringBuilder(); //for (int i = 0; i < geometryCollection.GeometryCount; i++) //{ // IGeometry geometry = geometryCollection.get_Geometry(i); // IPointCollection pointCollection = geometry as IPointCollection; // if (pointCollection != null) // { // for (int j = 0; j < pointCollection.PointCount; j++) // { // coords.Append(pointCollection.get_Point(j).X + "," + pointCollection.get_Point(j).Y + ";"); // } // coords.Append("|"); // } //} //coords.Clear(); //coords = null; } lstErrorEnity.Add(ruleEntity); GC.Collect(); System.Runtime.InteropServices.Marshal.ReleaseComObject(topologyErrorFeature); } } return lstErrorEnity; } catch (Exception ex) { throw ex; } finally { //强制回收 GC.Collect(); GC.WaitForFullGCComplete(); } } public static void CreateMdbfile(string strMdbFileName) { if (!File.Exists(strMdbFileName)) { string mdbfileName = System.IO.Path.GetFileNameWithoutExtension(strMdbFileName); //test string fileName = System.IO.Path.GetFileName(strMdbFileName);//返回文件名 test.mdb string fileDirectory = System.IO.Path.GetDirectoryName(strMdbFileName);//返回文件目录 f://temp if (mdbfileName == "") return; IWorkspaceFactory workspaceFactory = new AccessWorkspaceFactory(); IWorkspaceName workspaceName = workspaceFactory.Create(fileDirectory, mdbfileName, null, 0); IName name = workspaceName as IName; IWorkspace workspace = (IWorkspace)name.Open(); IFeatureWorkspace pFeWs = workspace as IFeatureWorkspace; Marshal.ReleaseComObject(workspaceFactory); Marshal.ReleaseComObject(workspaceName); } else { //MessageBox.Show("文件夹下已存在该mdb文件,请先删除"); } } } }