using ESRI.ArcGIS.Carto; using ESRI.ArcGIS.DataSourcesGDB; using ESRI.ArcGIS.Geodatabase; using ESRI.ArcGIS.Geometry; using ESRI.ArcGIS.Geoprocessing; using ESRI.ArcGIS.Geoprocessor; using KGIS.Framework.AE; using KGIS.Framework.AE.Enum; using KGIS.Framework.AE.ExtensionMethod; using KGIS.Framework.AE.GPHelper; using KGIS.Framework.Maps; using KGIS.Framework.Utils; using Kingo.PluginServiceInterface; using System; using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; using System.Threading; namespace Kingo.Plugin.DataCheck { public class JCDLTBDataCheck : IDataCheck { public event CheckDataPr DataCheckComplate; List dataCheckResults = null; public string IDataCheckName { get => "JCDLTBDataCheck"; } public void FeatureCheck(object pParm) { FeatureClassCheck(pParm); } public void FeatureClassCheck(object pParm) { dataCheckResults = new List(); string topologyName = "TopologyCheck_DLTB"; JCDLTB_Topology(topologyName); //DLTBRangeDatacheck(topologyName); //Thread.Sleep(3000); (pParm as CheckParametr).CheckResults = dataCheckResults; DataCheckComplate?.Invoke(dataCheckResults, pParm as CheckParametr); } private ProjectInfo projectInfo = (MapsManager.Instance.MapService.GetProjectInfo() as ProjectInfo); private void JCDLTB_Topology(string topologyName) { IFeatureWorkspace featureWorkspace = null; IEnvelope envelope = null; try { checkTopologyError(topologyName, ref featureWorkspace, ref envelope); FindAllErrorFeatures(topologyName, envelope); } catch (Exception ex) { LogAPI.Debug($"基础地类图斑拓扑检查异常:{ex.Message}"); throw ex; } } /// /// 检查要素层中存在的拓扑错误 /// /// 工作空间名称 /// 数据集名称 /// 要素类名称 /// 拓扑要素层名,拓扑检查结果记录在该层中 public void checkTopologyError(string topologyName, ref IFeatureWorkspace featureWorkspace, ref IEnvelope envelope) { IFeatureLayer JCFC = MapsManager.Instance.MapService.GetFeatureLayerByLayerName("地类图斑"); //1. 打开数据集文件 IWorkspace workspace = (JCFC.FeatureClass as FeatureClass).Workspace; featureWorkspace = (IFeatureWorkspace)workspace; //2. 打开数据集文件 IFeatureDataset featureDataset = JCFC.FeatureClass.FeatureDataset; //3. 向拓扑集中添加要素层 IFeatureClass LRDLlayer = JCFC.FeatureClass; //4. 设置拓扑处理对数据集的独占权限 ISchemaLock schemaLock = (ISchemaLock)featureDataset; IWorkspaceFactory2 ipWsFactory = new FileGDBWorkspaceFactoryClass(); ITopologyContainer2 topologyContainer = featureDataset as ITopologyContainer2; //判断拓扑是否存在 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); } //关闭资源锁定 IWorkspaceFactoryLockControl ipWsFactoryLock; ipWsFactoryLock = (IWorkspaceFactoryLockControl)ipWsFactory; if (ipWsFactoryLock.SchemaLockingEnabled) { ipWsFactoryLock.DisableSchemaLocking(); } try { schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock); //5. 拓扑处理 //5.1 创建拓扑容器 //5.2 向拓扑容器中添加拓扑结果层 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, null); AddRuleToTopology(topology, esriTopologyRuleType.esriTRTAreaNoGaps, "图层内部面和面之间不允许存在缝隙", LRDLlayer, null); //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); } } /// /// 增加拓扑规则 /// /// 拓扑集 /// 拓扑规则 /// 规则名称 /// 要素类 public void AddRuleToTopology(ITopology topology, esriTopologyRuleType ruleType, String ruleName, IFeatureClass featureClass, IFeatureClass destinationClass) { ITopologyRule topologyRule = new TopologyRuleClass(); topologyRule.TopologyRuleType = ruleType; topologyRule.Name = ruleName; topologyRule.OriginClassID = featureClass.FeatureClassID; topologyRule.AllOriginSubtypes = true; if (destinationClass != null) { topologyRule.DestinationClassID = destinationClass.FeatureClassID; topologyRule.AllDestinationSubtypes = true; } ITopologyRuleContainer topologyRuleContainer = (ITopologyRuleContainer)topology; if (topologyRuleContainer.get_CanAddRule(topologyRule)) { topologyRuleContainer.AddRule(topologyRule); } else { throw new ArgumentException(string.Format("不能添加{0}规则到拓扑里面,请检查此规则是否正确。", ruleName)); } } //拓扑有效性检查 public void ValidateTopology(ITopology topology, IEnvelope envelope) { IPolygon locationPolygon = new PolygonClass(); ISegmentCollection segmentCollection = (ISegmentCollection)locationPolygon; segmentCollection.SetRectangle(envelope); IPolygon polygon = topology.get_DirtyArea(locationPolygon); IEnvelope areaToValidate = polygon.Envelope; IEnvelope areaValidated = topology.ValidateTopology(areaToValidate); } //给定拓扑和查找的范围,返回所有的拓扑错误要素 public void FindAllErrorFeatures(string topologyName, IEnvelope searchExtent) { IFeatureLayer JCFC = MapsManager.Instance.MapService.GetFeatureLayerByLayerName("地类图斑"); IFeatureDataset featureDataset = JCFC.FeatureClass.FeatureDataset; ITopologyContainer topologyContainer = (ITopologyContainer)featureDataset; ITopology topology = topologyContainer.get_TopologyByName(topologyName); //获取坐标系 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; var count = 0; 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) { if (topologyRule.Name == "图层内部面和面之间不允许存在缝隙" && count == 0) { count++; continue; } dataCheckResults.Add(new CheckResult() { ErrorDesc = topologyRule.Name == "图层内部面和面之间不允许重叠" ? $"{topologyRule.Name}【{topologyErrorFeature.OriginOID}/{topologyErrorFeature.DestinationOID}】" : topologyRule.Name, Synopsis = topologyRule.Name, ErrorCode = "2001000300000014", ErrorLayer = IDataCheckName, ObjectID = topologyRule.Name == "图层内部面和面之间不允许重叠" ? topologyErrorFeature.OriginOID : pFeature.OID, ErrorType = EnumErrorType.错误, ErrorCategory = "Graphic", ErrorArea = pFeature.Shape.ToJson() }); } } } try { IDataset pDatasetTemp = (IDataset)topology; pDatasetTemp.Delete(); Marshal.ReleaseComObject(pDatasetTemp); } catch { } } /// /// 基础地类图斑与基础行政区范围检查 /// private void DLTBRangeDatacheck(string topologyName) { GPParamClass gPParamClass = new GPParamClass(); ITopology2 topology = null; IFeatureLayer featureLayer = null; IEnvelope envelope = null; IWorkspaceFactory pFtWsFct = null; try { IFeatureLayer Fc_JCDLTB = MapsManager.Instance.MapService.GetFeatureLayerByLayerName("地类图斑"); IFeatureLayer Fc_JCCJDCQ = MapsManager.Instance.MapService.GetFeatureLayerByLayerName("村级调查区"); string gdbFolder = Directory.GetCurrentDirectory() + "\\Temp\\JCDLTBTempFile"; if (!Directory.Exists(gdbFolder)) Directory.CreateDirectory(gdbFolder); try { DelectDirect(gdbFolder); } catch { } pFtWsFct = new FileGDBWorkspaceFactory(); string path = System.IO.Path.Combine(gdbFolder, Guid.NewGuid().ToString()); pFtWsFct.Create(path, "TempGDB", null, 0); string TempfilePath = System.IO.Path.Combine(path, "TempGDB.gdb");//临时数据存放路径 IWorkspaceAPI wsAPI = new WorkspaceAPI(TempfilePath, WorkspaceTypeEnum.GDBFile); IFeatureClassAPI DLTBAPI = wsAPI.CreateFeatureClass("DLTB", (Fc_JCDLTB.FeatureClass as IGeoDataset).SpatialReference, Fc_JCDLTB.FeatureClass.Fields); IFeatureClassAPI fcAPI = new FeatureClassAPI(Fc_JCDLTB.FeatureClass); fcAPI.FcToFc(DLTBAPI.FeatureClass, null, false); IFeatureDataset featureDataset = Fc_JCDLTB.FeatureClass.FeatureDataset; ITopologyContainer2 topologyContainer = featureDataset as ITopologyContainer2; //判断拓扑是否存在 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); } gPParamClass = new GPParamClass() { FirstFeatureLayer = Fc_JCDLTB, OutFeatureClassPath = TempfilePath + "\\JCDLTB_Dissolve", IsGetOutPutFeature = true, ListDissolveFiledName = new List() { "ZLDWDM", "ZLDWMC" }, }; GeoprocessorHelper.DissolveAnalysis(gPParamClass, ref featureLayer); ISchemaLock schemaLock = (ISchemaLock)featureDataset;//注意此时不能使用ArcGIS再打开这个数据集 IWorkspaceFactory2 ipWsFactory = new FileGDBWorkspaceFactoryClass(); IWorkspaceFactoryLockControl ipWsFactoryLock = (IWorkspaceFactoryLockControl)ipWsFactory; if (ipWsFactoryLock.SchemaLockingEnabled) { ipWsFactoryLock.DisableSchemaLocking(); } try { schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock); topology = topologyContainer.CreateTopology(topologyName, topologyContainer.DefaultClusterTolerance, -1, "") as ITopology2; //拓扑规则 必须添加同一个数据集中的数据 topology.AddClass(featureLayer.FeatureClass, 5, 1, 1, false); topology.AddClass(Fc_JCCJDCQ.FeatureClass, 5, 1, 1, false); AddRuleToTopology(topology, esriTopologyRuleType.esriTRTAreaAreaCoverEachOther, "基础地类图斑同一坐落必须与基础村级调查区完全重合", Fc_JCCJDCQ.FeatureClass, featureLayer.FeatureClass); 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); } FindAllErrorFeatures(topologyName, envelope); } catch (Exception ex) { LogAPI.Debug($"基础地类图斑拓扑检查异常:{ex.Message}"); throw ex; } finally { } } #region DelectDirect private static void DelectDirect(string srcPath) { try { DirectoryInfo dir = new DirectoryInfo(srcPath); FileSystemInfo[] fileinfo = dir.GetFileSystemInfos(); //返回目录中所有文件和子目录 foreach (FileSystemInfo i in fileinfo) { if (i is DirectoryInfo) //判断是否文件夹 { DirectoryInfo subdir = new DirectoryInfo(i.FullName); subdir.Delete(true); //删除子目录和文件 } else { File.Delete(i.FullName); //删除指定文件 } } } catch (Exception e) { throw; } } #endregion } }