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.esriSystem; using ESRI.ArcGIS.Geodatabase; using ESRI.ArcGIS.Geometry; namespace Kingo.PluginServiceInterface.Helper { /// /// 拓扑帮助类 /// public class DataCheckTopologyHelper { /// /// 返回true表示面图层内存在重叠 /// /// /// /// /// /// public static bool 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); bool b = 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 b; } 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 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 bool FindAllErrorFeatures(ITopology topology, IEnvelope searchExtent, List lstFeatureClass) { 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) { 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; } } GC.Collect(); System.Runtime.InteropServices.Marshal.ReleaseComObject(topologyErrorFeature); return true; } } return false; } catch (Exception ex) { throw ex; } finally { //强制回收 GC.Collect(); GC.WaitForFullGCComplete(); } } } }