using ESRI.ArcGIS.DataSourcesGDB; using ESRI.ArcGIS.Geodatabase; using ESRI.ArcGIS.Geometry; using KGIS.Framework.AE.ExtensionMethod; using KGIS.Framework.Maps; using KGIS.Framework.Utils; using Kingo.PluginServiceInterface; using System; using System.Collections.Generic; using System.Runtime.InteropServices; namespace Kingo.Plugin.DataCheck { public class JCCZCDYDDataCheck : IDataCheck { public event CheckDataPr DataCheckComplate; List dataCheckResults = null; public string IDataCheckName { get => "JCCZCDYDDataCheck"; } public void FeatureCheck(object pParm) { JCDLTB_Topology(); DataCheckComplate?.Invoke(dataCheckResults, pParm as CheckParametr); } public void FeatureClassCheck(object pParm) { JCDLTB_Topology(); DataCheckComplate?.Invoke(dataCheckResults, pParm as CheckParametr); } private void JCDLTB_Topology() { try { dataCheckResults = new List(); ProjectInfo projectInfo = (MapsManager.Instance.MapService.GetProjectInfo() as ProjectInfo); IFeatureWorkspace featureWorkspace = null; IEnvelope envelope = null; ITopology topology = null; checkTopologyError(projectInfo.ProjDir + "\\PrjDB.gdb", "基础数据", "JC_CZCDYD", "TopologyCheck_CZCDYD", ref featureWorkspace, ref envelope); topology = OpenTopologyFromFeatureWorkspace(featureWorkspace, "基础数据", "TopologyCheck_CZCDYD"); FindAllErrorFeatures(topology, envelope); } catch (Exception ex) { LogAPI.Debug($"基础地类图斑拓扑检查异常:{ex.Message}"); throw ex; } } /// /// 检查要素层中存在的拓扑错误 /// /// 工作空间名称 /// 数据集名称 /// 要素类名称 /// 拓扑要素层名,拓扑检查结果记录在该层中 public void checkTopologyError(string wsPath, string dsPath, string feaPath, string topologyName, ref IFeatureWorkspace featureWorkspace, ref IEnvelope envelope) { // Open the workspace and the required datasets. Type factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.AccessWorkspaceFactory"); //ESRI.ArcGIS.DataSourcesGDB IWorkspaceFactory workspaceFactory = new FileGDBWorkspaceFactoryClass(); //new AccessWorkspaceFactory(); //1. 打开数据集文件 IWorkspace workspace = workspaceFactory.OpenFromFile(wsPath, 0); featureWorkspace = (IFeatureWorkspace)workspace; //2. 打开数据集文件 IFeatureDataset featureDataset = featureWorkspace.OpenFeatureDataset(dsPath); //3. 向拓扑集中添加要素层 IFeatureClass LRDLlayer = featureWorkspace.OpenFeatureClass(feaPath); //4. 设置拓扑处理对数据集的独占权限 ISchemaLock schemaLock = (ISchemaLock)featureDataset;//注意此时不能使用ArcGIS再打开这个数据集 IWorkspaceFactory2 ipWsFactory = new FileGDBWorkspaceFactoryClass(); //关闭资源锁定 IWorkspaceFactoryLockControl ipWsFactoryLock; ipWsFactoryLock = (IWorkspaceFactoryLockControl)ipWsFactory; if (ipWsFactoryLock.SchemaLockingEnabled) { ipWsFactoryLock.DisableSchemaLocking(); } try { schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock); //5. 拓扑处理 //5.1 创建拓扑容器 ITopologyContainer2 topologyContainer = featureDataset as ITopologyContainer2; //5.2 向拓扑容器中添加拓扑结果层 //判断当前命名的拓扑是否存在,如果存在,删除 bool bTopExists = (featureDataset.Workspace as IWorkspace2).get_NameExists(esriDatasetType.esriDTTopology, topologyName); if (bTopExists) { ITopology topologyTemp = topologyContainer.get_TopologyByName(topologyName); //删除拓扑 IDataset pDatasetTemp = (IDataset)topologyTemp; pDatasetTemp.Delete(); Marshal.ReleaseComObject(pDatasetTemp); } ITopology2 topology = topologyContainer.CreateTopology(topologyName, topologyContainer.DefaultClusterTolerance, -1, "") as ITopology2; //5.3 添加参与拓扑运算的数据层 topology.AddClass(LRDLlayer, 5, 1, 1, false); //5.4 添加拓扑规则 AddRuleToTopology(topology, esriTopologyRuleType.esriTRTAreaNoOverlap, "面与面不重叠", LRDLlayer); //AddRuleToTopology(topology, esriTopologyRuleType.esriTRTAreaNoGaps, "面之间不存在间隙", LRDLlayer); //5.5 拓扑验证 IGeoDataset geoDataset = (IGeoDataset)topology; envelope = geoDataset.Extent; ValidateTopology(topology, envelope); } catch (COMException comExc) { throw new Exception(String.Format("Error creating topology: {0} Message: {1}", comExc.ErrorCode, comExc.Message), comExc); } finally { schemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock); } //MessageBox.Show("拓扑检查完毕", "提示信息"); } /// /// 增加拓扑规则 /// /// 拓扑集 /// 拓扑规则 /// 规则名称 /// 要素类 public void AddRuleToTopology(ITopology topology, esriTopologyRuleType ruleType, String ruleName, IFeatureClass featureClass) { // Create a topology rule. ITopologyRule topologyRule = new TopologyRuleClass(); topologyRule.TopologyRuleType = ruleType; topologyRule.Name = ruleName; topologyRule.OriginClassID = featureClass.FeatureClassID; topologyRule.AllOriginSubtypes = true; // Cast the topology to the ITopologyRuleContainer interface and add the rule. ITopologyRuleContainer topologyRuleContainer = (ITopologyRuleContainer)topology; if (topologyRuleContainer.get_CanAddRule(topologyRule)) { topologyRuleContainer.AddRule(topologyRule); } else { throw new ArgumentException("无法将指定的规则添加到拓扑中."); } } //拓扑有效性检查 public void ValidateTopology(ITopology topology, IEnvelope envelope) { // Get the dirty area within the provided envelope. IPolygon locationPolygon = new PolygonClass(); 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); } } //打开拓扑 public ITopology OpenTopologyFromFeatureWorkspace(IFeatureWorkspace featureWorkspace, String featureDatasetName, String topologyName) { //打开数据集 IFeatureDataset featureDataset = featureWorkspace.OpenFeatureDataset(featureDatasetName); //获取拓扑容器 ITopologyContainer topologyContainer = (ITopologyContainer)featureDataset; //打开拓扑 ITopology topology = topologyContainer.get_TopologyByName(topologyName); return topology; } //给定拓扑和查找的范围,返回所有的拓扑错误要素 public void FindAllErrorFeatures(ITopology topology, IEnvelope searchExtent) { //获取坐标系 IErrorFeatureContainer errorFeatureContainer = (IErrorFeatureContainer)topology; IGeoDataset geoDataset = (IGeoDataset)topology; ISpatialReference spatialReference = geoDataset.SpatialReference; ITopologyRuleContainer topologyRuleContainer = (ITopologyRuleContainer)topology; //遍历拓扑规则 IEnumRule enumRule = topologyRuleContainer.Rules; enumRule.Reset(); ESRI.ArcGIS.Geodatabase.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) { IFeature pFeature = topologyErrorFeature as IFeature; if (pFeature != null) { dataCheckResults.Add(new CheckResult() { ErrorDesc = "要素存在拓扑错误!", Synopsis = "要素存在拓扑错误!", ErrorCode = "200500", ErrorLayer = IDataCheckName, ObjectID = pFeature.OID, ErrorType = EnumErrorType.错误, ErrorArea = pFeature.ShapeCopy.ToJson() }); } } } try { IDataset pDatasetTemp = (IDataset)topology; pDatasetTemp.Delete(); Marshal.ReleaseComObject(pDatasetTemp); } catch { } } } }