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 KGIS.Framework.AE; using KGIS.Framework.AE.Enum; using KGIS.Framework.AE.ExtensionMethod; using KGIS.Framework.AE.GPHelper; using KGIS.Framework.DBOperator; using KGIS.Framework.Maps; using KGIS.Framework.Utils; using KGIS.Framework.Utils.ExtensionMethod; using Kingo.PluginServiceInterface; using Kingo.PluginServiceInterface.Model; using System; using System.Collections.Generic; using System.Data; using System.Data.SQLite; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace KDataCheck { public class DataCheckHelper { List sqlList = null; public void ZLDataCheck(IDGParameter pParam) { IRDBHelper rdbHelper = null; IRDBHelper rdbHelp = null; try { bool isFirstDataCheck = true; string mOutLocation = pParam.OutLocation; var mOutLocation_GDBName = string.Empty; string mPrjDbPath = pParam.PrjDbPath; string dbPath = pParam.TempdbPath; string strParm = string.Empty; DBLayerSourceHelper mLayerSource = OpenDB(pParam.PrjInfo, pParam.CheckType == "BGDB"); if (mLayerSource == null) return; ESRI.ArcGIS.Geometry.ISpatialReference sp = (mLayerSource.BgTbLayer.FeatureClass as IGeoDataset).SpatialReference; ESRI.ArcGIS.Geometry.IPRJSpatialReferenceGEN gen1 = (ESRI.ArcGIS.Geometry.IPRJSpatialReferenceGEN)sp; string str1; int int1; #region 规则筛选 rdbHelper = RDBFactory.CreateDbHelper("Data Source=" + mPrjDbPath, DatabaseType.SQLite); string Sqlwhere = " where 1=2 "; if (pParam.CheckType == "BGDB") { Sqlwhere = " where BGIsSelect=true and BGLayerName NOTNULL "; mOutLocation_GDBName = mOutLocation + "\\BGDBCheckResult.gdb"; } else if (pParam.CheckType == "ZLDB") { Sqlwhere = " where ZLIsSelect=true and BGLayerName ISNULL AND RuleType='图形拓扑' "; mOutLocation_GDBName = mOutLocation + "\\ZLDBCheckResult.gdb"; } DataTable dataTable = rdbHelper.ExecuteDatatable("tab", $" SELECT * from CheckingRule {Sqlwhere} ", true); if (dataTable == null || dataTable.Rows.Count == 0) return; foreach (DataRow row in dataTable.Rows) { string sql = row["ImplementSQL"].ToTrim(); if (isFirstDataCheck == true && !row["ImplementSQL"].ToTrim().ToLower().Contains("select") && !string.IsNullOrEmpty(row["ImplementSQL"].ToTrim()) && !row["ImplementSQL"].ToTrim().Contains("SameGraphic") && !row["ImplementSQL"].ToTrim().Contains("SameBSM") && !row["ImplementSQL"].ToTrim().Contains("LMFWGXKD") && !row["ImplementSQL"].ToTrim().Contains("SameGDPDJB") && !row["ImplementSQL"].ToTrim().Contains("Topology_JCDLTB") && !row["ImplementSQL"].ToTrim().Contains("LineNoDangles") && !row["ImplementSQL"].ToTrim().Contains("CheckGraphic") && !row["ImplementSQL"].ToTrim().Contains("Irregular") && !row["ImplementSQL"].ToTrim().Contains("Localslenderness") && !row["ImplementSQL"].ToTrim().Contains("NodeDensity") && !row["ImplementSQL"].ToTrim().Contains("SameAttribute")) { isFirstDataCheck = false; gen1.ExportSpatialReferenceToPRJ(out str1, out int1); if (pParam.CheckType == "ZLDB") { IVariantArray parameters = new VarArrayClass(); parameters.Add(pParam.PrjInfo.ZLDatabase); parameters.Add(mOutLocation); parameters.Add("ZLDBCheckResult"); parameters.Add(dbPath); parameters.Add(mLayerSource.GxTbLayer); parameters.Add(pParam.CheckType); strParm = KGIS.Framework.AE.GeoDBAPI.SerialzedPersist(parameters); } else if (pParam.CheckType == "BGDB") { IVariantArray parameters = new VarArrayClass(); parameters.Add(mLayerSource.JcTbLayer);//基础地类图斑 parameters.Add(mLayerSource.BgTbLayer);//变更图斑 parameters.Add("1=1");//过滤条件 parameters.Add(mOutLocation);//输出路径 parameters.Add("BGDBCheckResult");//输出GDB名称 parameters.Add(dbPath);//输出DB路径 parameters.Add("10");//最小面积 parameters.Add(str1);//坐标系 parameters.Add(pParam.CheckType); strParm = KGIS.Framework.AE.GeoDBAPI.SerialzedPersist(parameters); } if (string.IsNullOrEmpty(strParm)) { Console.WriteLine("参数为空!"); return; } GPHelper.Instance.ExeGPForProces(strParm, pParam.CheckType); break; } } sqlList = new List(); string LayerName = string.Empty; //变更图斑图层名称 string Alias = string.Empty;//别名 rdbHelp = RDBFactory.CreateDbHelper("Data Source=" + dbPath, DatabaseType.SQLite); var ImplementSQL = string.Empty; var RuleCode = string.Empty; var RuleType = string.Empty; var RuleName = string.Empty; foreach (DataRow row in dataTable.Rows) { if (sqlList.Count > 10000) { InsertSQLiteData(mPrjDbPath, sqlList); sqlList.Clear(); } ImplementSQL = row["ImplementSQL"].ToTrim();//执行语句 RuleCode = row["RuleCode"].ToTrim();//规则编码 RuleType = row["RuleType"].ToTrim();//规则类别 RuleName = row["RuleName"].ToTrim();//规则名称 try { if (pParam.CheckType == "BGDB" || pParam.CheckType == "JCDB") { LayerName = row["BGLayerName"].ToTrim().Split('_')[0]; Alias = row["BGLayerName"].ToTrim().Split('_')[1]; } else if (pParam.CheckType == "ZLDB") { LayerName = row["ZLLayerName"].ToTrim().Split('_')[0]; Alias = row["ZLLayerName"].ToTrim().Split('_')[1]; } switch (ImplementSQL) { #region Topology case "Topology"://相互重叠 GetTopologySqlite(mOutLocation_GDBName, rdbHelp, LayerName, RuleCode, RuleName, RuleType, pParam.CheckType == "ZLDB" ? pParam.PrjInfo.ZLDatabase : pParam.PrjInfo.BGDatabase); break; #endregion #region Union case "Union"://碎多边形 //sqlList.AddRange(GetUnionResult(DLTBBG, JC_DLTB, RuleCode, TempfilePath)); GetUnionSqlite(mOutLocation_GDBName, RuleCode, RuleName, RuleType); break; #endregion #region Topology_JCDLTB case "Topology_JCDLTB": break; #endregion #region CheckGraphic case "CheckGraphic"://自相交-多部件 CheckGraphic(RuleCode, RuleName, LayerName, pParam.CheckType == "ZLDB" ? pParam.PrjInfo.ZLDatabase : pParam.PrjInfo.BGDatabase); break; #endregion #region Irregular case "Irregular"://地类图斑更新层内不存在不规则图斑(除地类1001、1002、1006、1009、1107、1109外,其余地类满足面积/周长<0.2,并且有一个角度小于20) Irregular(RuleCode, RuleName, LayerName, pParam.CheckType == "ZLDB" ? pParam.PrjInfo.ZLDatabase : pParam.PrjInfo.BGDatabase); break; #endregion #region Localslenderness case "Localslenderness"://地类图斑更新层要素所有角度均应大于10度,同时不存在局部狭长图形 Localslenderness(RuleCode, RuleName, LayerName, pParam.CheckType == "ZLDB" ? pParam.PrjInfo.ZLDatabase : pParam.PrjInfo.BGDatabase); break; #endregion #region NodeDensity case "NodeDensity"://地类图斑更新层平均节点密度大于1米小于70米 NodeDensity(RuleCode, RuleName, LayerName, pParam.CheckType == "ZLDB" ? pParam.PrjInfo.ZLDatabase : pParam.PrjInfo.BGDatabase); break; #endregion #region SameAttribute case "SameAttribute"://村级调查区更新层ZLDWDM、MSSM相同的多个调查区空间不能相邻 break; #endregion case "SameGraphic": break; case "SameBSM": break; case "LMFWGXKD": break; case "SameGDPDJB": break; case "LineNoDangles": break; #region default default: break; #endregion } } catch (Exception ex) { continue; } } #endregion InsertSQLiteData(mPrjDbPath, sqlList); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } finally { if (rdbHelper != null && rdbHelper.State != System.Data.ConnectionState.Closed) rdbHelper.DisConnect(); if (rdbHelp != null && rdbHelp.State != System.Data.ConnectionState.Closed) rdbHelp.DisConnect(); } } private void GetTopologySqlite(string mOutLocation_GDBName, IRDBHelper rdbHelper, string LayerName, string RuleCode, string RuleName, string RuleType, string ZLBasePath) { try { IWorkspaceAPI workspaceAPI = new WorkspaceAPI(mOutLocation_GDBName, WorkspaceTypeEnum.GDBFile); List featureClasses = workspaceAPI.GetAllFeatureClass(esriDatasetType.esriDTAny); if (featureClasses == null) return; IFeatureClass findFeatureClass = featureClasses.FirstOrDefault(a => a.AliasName == LayerName); if (findFeatureClass == null) { findFeatureClass = featureClasses.FirstOrDefault(a => a.AliasName == "JCDLTB"); if (LayerName != "DLTB" || findFeatureClass == null) { //从ZLGDB文件中获取 GetTopology(ZLBasePath, LayerName, RuleCode, RuleName); return; } } int currentClassID = 0; foreach (IFeatureClass featureClasse in featureClasses) { if (featureClasse.AliasName == LayerName) { currentClassID = featureClasse.FeatureClassID; break; } else if (LayerName == "DLTB" && featureClasse.AliasName == "JCDLTB") { currentClassID = featureClasse.FeatureClassID; break; } } var dltbbg = new WorkspaceAPI(ZLBasePath, WorkspaceTypeEnum.GDBFile).OpenFeatureClass(LayerName); var bsm = dltbbg.FeatureClass.FindField("BSM"); IFeatureClass featureClass = featureClasses[0]; IFeatureDataset featureDataset = featureClass.FeatureDataset; ITopologyContainer topologyContainer = (ITopologyContainer)featureDataset; ITopology topology = topologyContainer.get_TopologyByName("Dataset_Topo"); 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; IEnvelope searchExtent = geoDataset.Extent; while ((rule = enumRule.Next()) != null) { //获取当前拓扑规则的拓扑错误并遍历 ITopologyRule topologyRule = (ITopologyRule)rule; if (LayerName == "DLTB") { if (topologyRule.TopologyRuleType != esriTopologyRuleType.esriTRTAreaNoOverlap && topologyRule.TopologyRuleType != esriTopologyRuleType.esriTRTAreaNoGaps) continue; } else if (topologyRule.TopologyRuleType != esriTopologyRuleType.esriTRTAreaNoOverlap) continue; IEnumTopologyErrorFeature enumTopologyErrorFeature = errorFeatureContainer.get_ErrorFeatures(spatialReference, topologyRule, searchExtent, true, true); ITopologyErrorFeature topologyErrorFeature = null; while ((topologyErrorFeature = enumTopologyErrorFeature.Next()) != null) { if (topologyErrorFeature.OriginClassID != currentClassID) continue; IFeature pFeature = topologyErrorFeature as IFeature; if (pFeature != null && !pFeature.Shape.IsEmpty) { //sqlList.Add($"INSERT INTO DataCheckResults(OBJECTID, BSM, ErrorLayer, ErrorCode, ErrorName,RuleType,ErrorArea,RepairfilePath) " + // $"VALUES ('{topologyErrorFeature.DestinationOID}', '{SearchBSM(rdbHelper, LayerName, topologyErrorFeature.DestinationOID.ToString())}', '{LayerName}', '{RuleCode}', '{RuleName}','{RuleType}','{pFeature.Shape.ToJson()}','{mOutLocation_GDBName}');"); sqlList.Add($"INSERT INTO DataCheckResults(OBJECTID, BSM, ErrorLayer, ErrorCode, ErrorName,RuleType,ErrorArea,RepairfilePath) " + $"VALUES ('{topologyErrorFeature.DestinationOID}', '{dltbbg.GetFeature(topologyErrorFeature.OriginOID).Value[bsm].ToString()}-{dltbbg.GetFeature(topologyErrorFeature.DestinationOID).Value[bsm].ToString()}', '{LayerName}', '{RuleCode}', '{RuleName}','{RuleType}','{pFeature.Shape.ToJson()}','{mOutLocation_GDBName}');"); } } } } catch (Exception ex) { LogAPI.Debug("数据检查时发生异常,异常信息如下:"); LogAPI.Debug(ex); return; } } private void GetTopology(string TempfilePath, string LayerName, string ErrorCode, string ErrorName) { IEnvelope envelope = null; string topologyName = $"TopologyCheck_{LayerName}"; try { IWorkspaceAPI workspaceAPI = new WorkspaceAPI(TempfilePath, WorkspaceTypeEnum.GDBFile); var featureClassAPI = workspaceAPI.OpenFeatureClass(LayerName); TopologyVerification(topologyName, featureClassAPI.FeatureClass, esriTopologyRuleType.esriTRTAreaNoOverlap, ref envelope); FindAllError(topologyName, envelope, featureClassAPI.FeatureClass, LayerName, ErrorCode, ErrorName, TempfilePath); } catch (Exception ex) { throw ex; } } private void TopologyVerification(string topologyName, IFeatureClass featureClass, esriTopologyRuleType esriTopologyRuleType, ref IEnvelope envelope) { //1. 打开数据集文件 IWorkspace workspace = (featureClass as FeatureClass).Workspace; //2. 打开数据集文件 IFeatureDataset featureDataset = featureClass.FeatureDataset; //3. 向拓扑集中添加要素层 IFeatureClass LRDLlayer = 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(); } ITopology2 topology = null; try { schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock); //5. 拓扑处理 //5.1 创建拓扑容器 //5.2 向拓扑容器中添加拓扑结果层 topology = topologyContainer.CreateTopology(topologyName, topologyContainer.DefaultClusterTolerance, -1, "") as ITopology2; //5.3 添加参与拓扑运算的数据层 topology.AddClass(LRDLlayer, 5, 1, 1, false); //5.4 添加拓扑规则 string ruleName = "图层内部面和面之间不允许重叠"; AddRuleToTopology(topology, esriTopologyRuleType, ruleName, LRDLlayer, null); //AddRuleToTopology(topology, esriTopologyRuleType.esriTRTAreaNoOverlap, "图层内部面和面之间不允许重叠", LRDLlayer, null); //5.5 拓扑验证 IGeoDataset geoDataset = (IGeoDataset)topology; envelope = geoDataset.Extent; ValidateTopology(topology, envelope); } catch (COMException comExc) { if (topology != null) { IDataset pDatasetTemp = (IDataset)topology; pDatasetTemp.Delete(); } 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 FindAllError(string topologyName, IEnvelope searchExtent, IFeatureClass featureClass, string ErrorLayer, string ErrorCode, string ErrorName, string path) { IFeatureDataset featureDataset = 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; List bsmlist = new List(); var count = 0; var dltbbg = new WorkspaceAPI(path, WorkspaceTypeEnum.GDBFile).OpenFeatureClass(ErrorLayer); var bsm = featureClass.FindField("BSM"); 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; } if (pFeature != null && !pFeature.Shape.IsEmpty) { sqlList.Add($"INSERT INTO DataCheckResults(OBJECTID, BSM, ErrorLayer, ErrorCode, ErrorName,RuleType,ErrorArea,RepairfilePath) " + $"VALUES ('{topologyErrorFeature.DestinationOID}', '{dltbbg.GetFeature(topologyErrorFeature.OriginOID).Value[bsm].ToString()}-{dltbbg.GetFeature(topologyErrorFeature.DestinationOID).Value[bsm].ToString()}', '{ErrorLayer}', '{ErrorCode}', '{ErrorName}','{"图形拓扑"}','{pFeature.Shape.ToJson()}','{path}');"); } } } } try { IDataset pDatasetTemp = (IDataset)topology; pDatasetTemp.Delete(); Marshal.ReleaseComObject(pDatasetTemp); } catch { } } private void GetUnionSqlite(string mOutLocation_GDBName, string RuleCode, string RuleName, string RuleType) { IFeature pfeature = null; IFeatureCursor pCursor = null; try { IWorkspaceAPI workspaceUnionAPI = new WorkspaceAPI(mOutLocation_GDBName, WorkspaceTypeEnum.GDBFile); IFeatureClassAPI featureUnionClass = workspaceUnionAPI.OpenFeatureClass("DLTBBG_Err"); pCursor = featureUnionClass.FeatureClass.Search(null, true); int FID_DLTBBG = featureUnionClass.FeatureClass.FindField("FID_DLTBBG"); int BSM_DLTBBG = featureUnionClass.FeatureClass.FindField("BSM"); int FID_JCDLTB = featureUnionClass.FeatureClass.FindField("FID_JCDLTB"); int BSM_JCDLTB = featureUnionClass.FeatureClass.FindField("BSM_1"); while ((pfeature = pCursor.NextFeature()) != null) { //if (pfeature.Value[FID_DLTBBG].ToString() != "-1") //{ sqlList.Add($"INSERT INTO DataCheckResults(OBJECTID, BSM, ErrorLayer, ErrorCode, ErrorName,RuleType,ErrorArea,RepairfilePath,MultipartOID)" + $" VALUES ('{pfeature.Value[FID_DLTBBG]}', '{pfeature.Value[BSM_DLTBBG]}', 'DLTBBG', '{RuleCode}', '{RuleName}', '{RuleType}', '{pfeature.Shape.ToJson()}','{mOutLocation_GDBName}','{pfeature.OID}');"); //} //else //{ // sqlList.Add($"INSERT INTO DataCheckResults(OBJECTID, BSM, ErrorLayer, ErrorCode, ErrorName,RuleType,ErrorArea,RepairfilePath,MultipartOID)" + // $" VALUES ('{pfeature.Value[BSM_DLTBBG]}', '{pfeature.Value[BSM_JCDLTB]}', 'DLTB', '{RuleCode}', '{RuleName}', '{RuleType}', '{pfeature.Shape.ToJson()}','{mOutLocation_GDBName}','{pfeature.OID}');"); //} } } catch (Exception ex) { LogAPI.Debug("数据检查时发生异常,异常信息如下:"); LogAPI.Debug(ex); return; } finally { if (pfeature != null) Marshal.ReleaseComObject(pfeature); if (pCursor != null) Marshal.ReleaseComObject(pCursor); GC.Collect(); } } #region private private DBLayerSourceHelper OpenDB(ProjectInfo pPrjarm, bool isBGCheck) { DBLayerSourceHelper result = new DBLayerSourceHelper(); try { LayerCfg layerInfo = null; if (pPrjarm != null && !string.IsNullOrWhiteSpace(pPrjarm.TempData)) { byte[] contentArray = Convert.FromBase64String(pPrjarm.TempData); string LayerCfg = System.Text.Encoding.Default.GetString(contentArray); layerInfo = KGIS.Framework.Utils.SerializeAPI.DeserializeToObject(LayerCfg); } if (layerInfo == null) { throw new Exception("Err:获取图层信息失败!"); } //FileInfo fileInfo = new FileInfo(parm.PrjInfo.BGDatabase); string PathBgDB = pPrjarm.BGDatabase;// Path.Combine(, "BGDB" + ".gdb"); string PathZLDB = pPrjarm.ZLDatabase; string PathNMDB = pPrjarm.NMDatabase;// System.IO.Path.Combine(fileInfo.DirectoryName, "NMDB" + ".gdb"); result.BgWsAPI = new WorkspaceAPI(PathBgDB, WorkspaceTypeEnum.GDBFile); if (result.BgWsAPI.CurrentWorkspace == null) { Console.WriteLine("打开变更数据库失败!"); return result; } result.ZlWsAPI = new WorkspaceAPI(PathZLDB, WorkspaceTypeEnum.GDBFile); if (!isBGCheck && result.ZlWsAPI.CurrentWorkspace == null) { Console.WriteLine("打开增量数据库失败!"); return result; } result.NmWsAPI = new WorkspaceAPI(PathNMDB, WorkspaceTypeEnum.GDBFile); LayerCfg JCLayerInfo = layerInfo.Layers.FirstOrDefault(f => f.LayerName == "年初数据"); if (JCLayerInfo == null) { throw new Exception("Err:获取年初数据库失败!"); } List NcList = JCLayerInfo.GetAllItem(); //if (parm.ExeDLTB) //{ LayerCfg _JcTBLayerInfo = NcList.FirstOrDefault(f => f.LayerName == "地类图斑"); result.JcTbLayer = result.OpenLayer(_JcTBLayerInfo); if (result.JcTbLayer == null) { throw new Exception("Err:获取年初地类图斑数据失败!"); } LayerCfg _JcPdtLayerInfo = NcList.FirstOrDefault(f => f.LayerName == "坡度图"); result.JcPdtLayer = result.OpenLayer(_JcPdtLayerInfo); if (result.JcPdtLayer == null) { //throw new Exception("Err:获取年初坡度图数据失败!"); } result.BgTbLayer = result.OpenLayer(result.BgWsAPI, "DLTBBG"); result.GxTbLayer = result.OpenLayer(result.ZlWsAPI, "DLTBGX"); //} return result; } catch (Exception ex) { throw ex; } } public void InsertSQLiteData(string dbPath, List sqlList) { try { using (SQLiteConnection conn = new SQLiteConnection("Data Source=" + dbPath)) { conn.Open(); using (SQLiteTransaction pTrans = conn.BeginTransaction()) { using (SQLiteCommand cmd = new SQLiteCommand(conn)) { for (int i = 0; i < sqlList.Count(); i++) { cmd.CommandText = sqlList[i]; cmd.ExecuteNonQuery(); } pTrans.Commit(); } } conn.Close(); } } catch (Exception ex) { LogAPI.Debug("写入检查列表时发生异常,异常信息如下:"); LogAPI.Debug(ex); return; } } #endregion #region 地类图斑更新层平均节点密度大于1米小于70米 private void NodeDensity(string Check_RuleCode, string Check_RuleName, string Check_LayerName, string Temppath) { IFeature pfeature = null; IFeatureCursor pCursor = null; try { IWorkspaceAPI workspaceAPI = new WorkspaceAPI(Temppath, WorkspaceTypeEnum.GDBFile); var featureClass = workspaceAPI.OpenFeatureClass(Check_LayerName); pCursor = featureClass.FeatureClass.Search(null, true); int iBSM = featureClass.FeatureClass.FindField("BSM"); string strBSM = string.Empty; while ((pfeature = pCursor.NextFeature()) != null) { List Segmentslength = new List(); IGeometryCollection _GeoColl = pfeature.ShapeCopy as IGeometryCollection; for (int i = 0; i < _GeoColl.GeometryCount; i++) { ISegmentCollection _segmColl = _GeoColl.Geometry[i] as ISegmentCollection; for (int j = 0; j < _segmColl.SegmentCount; j++) { Segmentslength.Add(_segmColl.Segment[j].Length); } } if (Segmentslength.Average() > 70 || Segmentslength.Average() < 1) { if (iBSM != -1) strBSM = pfeature.Value[iBSM].ToString(); sqlList.Add($"INSERT INTO DataCheckResults(OBJECTID, BSM, ErrorLayer, ErrorCode, ErrorName,RuleType,ErrorArea,RepairfilePath) VALUES ('{pfeature.OID}', '{strBSM}', '{Check_LayerName}', '{Check_RuleCode}', '{Check_RuleName}','图形拓扑','{pfeature.Shape.ToJson()}','{Temppath}');"); } } } catch (Exception ex) { LogAPI.Debug("数据检查时发生异常,异常信息如下:"); LogAPI.Debug(ex); return; } finally { if (pfeature != null) Marshal.ReleaseComObject(pfeature); if (pCursor != null) Marshal.ReleaseComObject(pCursor); GC.Collect(); } } #endregion #region 要素不存在尖锐角和局部狭长图形(即不允许存在一个角度小于10度,或局部图形狭长的情况) private void Localslenderness(string Check_RuleCode, string Check_RuleName, string Check_LayerName, string Temppath) { IFeature pfeature = null; IFeatureCursor pCursor = null; IGeometry geo = null; ITopologicalOperator topo2 = null; IPolyline line2 = null; try { IWorkspaceAPI workspaceAPI = new WorkspaceAPI(Temppath, WorkspaceTypeEnum.GDBFile); var featureClass = workspaceAPI.OpenFeatureClass(Check_LayerName); pCursor = featureClass.FeatureClass.Search(null, true); int iBSM = featureClass.FeatureClass.FindField("BSM"); string strBSM = string.Empty; while ((pfeature = pCursor.NextFeature()) != null) { double angle = GetMinAngle(pfeature.ShapeCopy);//获取图形的最小角度 ITopologicalOperator topo = pfeature.ShapeCopy as ITopologicalOperator; IPolyline line1 = topo.Boundary as IPolyline; double length1 = line1.Length; int pointCount1 = (pfeature.ShapeCopy as IPointCollection).PointCount; geo = topo.Buffer(-0.05); topo2 = geo as ITopologicalOperator; line2 = topo2.Boundary as IPolyline; double length2 = line2.Length; int pointCount2 = (geo as IPointCollection).PointCount - 1; double delta_length = length1 - length2; double avg_halfangle = 180 * (pointCount1 - 1 - 2) / (pointCount1 - 1) / 2; double conner_normal_length = 2 * 0.05 / Math.Tan(avg_halfangle * (Math.PI / 180)); if ((delta_length > 8 * conner_normal_length * (pointCount1 - 1)) || angle < 10) { if (iBSM != -1) strBSM = pfeature.Value[iBSM].ToString(); sqlList.Add($"INSERT INTO DataCheckResults(OBJECTID, BSM, ErrorLayer, ErrorCode, ErrorName,RuleType,ErrorArea,RepairfilePath) VALUES ('{pfeature.OID}', '{strBSM}', '{Check_LayerName}', '{Check_RuleCode}', '{Check_RuleName}','图形拓扑','{pfeature.Shape.ToJson()}','{Temppath}');"); } if (topo != null) Marshal.ReleaseComObject(topo); if (line1 != null) Marshal.ReleaseComObject(line1); if (topo2 != null) Marshal.ReleaseComObject(topo2); if (line2 != null) Marshal.ReleaseComObject(line2); if (geo != null) Marshal.ReleaseComObject(geo); } } catch (Exception ex) { LogAPI.Debug("数据检查时发生异常,异常信息如下:"); LogAPI.Debug(ex); return; } finally { if (pfeature != null) Marshal.ReleaseComObject(pfeature); if (pCursor != null) Marshal.ReleaseComObject(pCursor); GC.Collect(); } } /// /// 获取最小角度 /// /// /// private static double GetMinAngle(IGeometry pGeo) { double result = -1; IPolygon4 poly4 = null; ITopologicalOperator topo = null; GeometryBag geoBag = null; IGeometryCollection geoCollection = null; try { if (pGeo == null || pGeo.IsEmpty) return result; poly4 = pGeo as IPolygon4; topo = poly4 as ITopologicalOperator; if (topo != null) topo.Simplify(); geoBag = poly4.ExteriorRingBag as GeometryBag; if (geoBag == null) return result; geoCollection = geoBag as IGeometryCollection; List rings = new List(); for (int j = 0; j < geoCollection.GeometryCount; j++) { IGeometry geo = geoCollection.get_Geometry(j); rings.Add(geo); //内环图形 IGeometryBag InteriorBag = (pGeo as IPolygon4).get_InteriorRingBag(geo as IRing); if (InteriorBag != null) { IGeometryCollection InteriorRingGeometryCollection = InteriorBag as IGeometryCollection; for (int IR = 0; IR < InteriorRingGeometryCollection.GeometryCount; IR++) { rings.Add(InteriorRingGeometryCollection.get_Geometry(IR)); } } } foreach (IGeometry ring in rings) { if (ring.IsEmpty) continue; IPointCollection points = ring as IPointCollection; int num = points.PointCount - 1; for (int i = 0; i < num; i++) { IPoint p1 = null; IPoint p2 = points.get_Point(i); IPoint p3 = null; if (i == 0) { p1 = points.get_Point(num - 1); p3 = points.get_Point(i + 1); } else if (i == num - 1) { p1 = points.get_Point(i - 1); p3 = points.get_Point(0); } else { p1 = points.get_Point(i - 1); p3 = points.get_Point(i + 1); } double angle = GetAngle(p2, p1, p3); if (result == -1) { result = angle; } else { if (result > angle) result = angle; } Marshal.ReleaseComObject(p1); Marshal.ReleaseComObject(p2); Marshal.ReleaseComObject(p3); } Marshal.ReleaseComObject(ring); } } catch (Exception ex) { throw ex; } finally { if (poly4 != null) Marshal.ReleaseComObject(poly4); if (topo != null) Marshal.ReleaseComObject(topo); if (geoBag != null) Marshal.ReleaseComObject(geoBag); if (geoCollection != null) Marshal.ReleaseComObject(geoCollection); } return result; } /// /// 计算角度 /// /// /// /// /// private static double GetAngle(IPoint cenPoint, IPoint firstPoint, IPoint secondPoint) { double ma_x = firstPoint.X - cenPoint.X; double ma_y = firstPoint.Y - cenPoint.Y; double mb_x = secondPoint.X - cenPoint.X; double mb_y = secondPoint.Y - cenPoint.Y; double v1 = (ma_x * mb_x) + (ma_y * mb_y); double ma_val = Math.Sqrt(ma_x * ma_x + ma_y * ma_y); double mb_val = Math.Sqrt(mb_x * mb_x + mb_y * mb_y); if (ma_val * mb_val == 0) { return -1; } double cosM = v1 / (ma_val * mb_val); double angleAMB = Math.Acos(cosM) * 180 / Math.PI; return angleAMB; } #endregion #region 地类图斑更新层内不存在不规则图斑(除地类1001、1002、1006、1009、1107、1109外,其余地类满足面积/周长<0.2,并且有一个角度小于20) private void Irregular(string Check_RuleCode, string Check_RuleName, string Check_LayerName, string Temppath) { IFeature pfeature = null; IFeatureCursor pCursor = null; try { IWorkspaceAPI workspaceAPI = new WorkspaceAPI(Temppath, WorkspaceTypeEnum.GDBFile); var featureClass = workspaceAPI.OpenFeatureClass(Check_LayerName); pCursor = featureClass.FeatureClass.Search(null, true); int iBSM = featureClass.FeatureClass.FindField("BSM"); int iDLBM = featureClass.FeatureClass.FindField("DLBM"); int iSHAPE_Area = featureClass.FeatureClass.FindField("SHAPE_Area"); int iSHAPE_Length = featureClass.FeatureClass.FindField("SHAPE_Length"); string strBSM = string.Empty; while ((pfeature = pCursor.NextFeature()) != null) { if ("1001,1002,1006,1009,1107,1109".Contains(pfeature.Value[iDLBM].ToString())) continue; double angle = GetMinAngle(pfeature.ShapeCopy);//获取图形的最小角度 var SHAPE_Area = pfeature.Value[iSHAPE_Area].ToDouble(); var SHAPE_Length = pfeature.Value[iSHAPE_Length].ToDouble(); if (SHAPE_Area / SHAPE_Length < 0.2 && angle < 20) { if (iBSM != -1) strBSM = pfeature.Value[iBSM].ToString(); sqlList.Add($"INSERT INTO DataCheckResults(OBJECTID, BSM, ErrorLayer, ErrorCode, ErrorName,RuleType,ErrorArea,RepairfilePath) VALUES ('{pfeature.OID}', '{strBSM}', '{Check_LayerName}', '{Check_RuleCode}', '{Check_RuleName}','图形拓扑','{pfeature.Shape.ToJson()}','{Temppath}');"); } } } catch (Exception ex) { LogAPI.Debug("数据检查时发生异常,异常信息如下:"); LogAPI.Debug(ex); return; } finally { if (pfeature != null) Marshal.ReleaseComObject(pfeature); if (pCursor != null) Marshal.ReleaseComObject(pCursor); GC.Collect(); } } #endregion #region 自相交-多部件 private void CheckGraphic(string Check_RuleCode, string Check_RuleName, string Check_LayerName, string Temppath) { IFeature pfeature = null; IFeatureCursor pCursor = null; try { IWorkspaceAPI workspaceAPI = new WorkspaceAPI(Temppath, WorkspaceTypeEnum.GDBFile); var featureClass = workspaceAPI.OpenFeatureClass(Check_LayerName); pCursor = featureClass.FeatureClass.Search(null, true); int iBSM = featureClass.FeatureClass.FindField("BSM"); string strBSM = string.Empty; while ((pfeature = pCursor.NextFeature()) != null) { if (Check_RuleName.Contains("自相交")) { if (JudgeSelfIntersect(pfeature.ShapeCopy)) { if (iBSM != -1) strBSM = pfeature.Value[iBSM].ToString(); IPolygon4 polygon = pfeature.ShapeCopy as IPolygon4; IGeometryBag bag = polygon.ExteriorRingBag; if ((bag as IGeometryCollection).GeometryCount > 1) { sqlList.Add($"INSERT INTO DataCheckResults(OBJECTID, BSM, ErrorLayer, ErrorCode, ErrorName,RuleType,ErrorArea,RepairfilePath) VALUES ('{pfeature.OID}', '{strBSM}', '{Check_LayerName}', '{Check_RuleCode}', '{Check_RuleName}','图形拓扑','{pfeature.Shape.ToJson()}','{Temppath}');"); } } } else if (Check_RuleName.Contains("组合图斑")) { IPointCollection polygonVertices = new PolygonClass(); IPointCollection lineVertices = pfeature.ShapeCopy as IPointCollection; polygonVertices.AddPointCollection(lineVertices); ITopologicalOperator3 pTopology = polygonVertices as ITopologicalOperator3; esriNonSimpleReasonEnum reason = esriNonSimpleReasonEnum.esriNonSimpleOK; pTopology.IsKnownSimple_2 = false; if (!pTopology.get_IsSimpleEx(out reason)) { if (iBSM != -1) strBSM = pfeature.Value[iBSM].ToString(); if (reason == esriNonSimpleReasonEnum.esriNonSimpleUnclosedRing) { IPolygon4 polygon = pfeature.Shape as IPolygon4; IGeometryBag bag = polygon.ExteriorRingBag; if ((bag as IGeometryCollection).GeometryCount > 1) { if (!JudgeSelfIntersect(pfeature.ShapeCopy)) sqlList.Add($"INSERT INTO DataCheckResults(OBJECTID, BSM, ErrorLayer, ErrorCode, ErrorName,RuleType,ErrorArea,RepairfilePath) VALUES ('{pfeature.OID}', '{strBSM}', '{Check_LayerName}', '{Check_RuleCode}', '{Check_RuleName}','图形拓扑','{pfeature.Shape.ToJson()}','{Temppath}');"); } } } if (pTopology != null) Marshal.ReleaseComObject(pTopology); if (lineVertices != null) Marshal.ReleaseComObject(lineVertices); if (polygonVertices != null) Marshal.ReleaseComObject(polygonVertices); } } } catch (Exception ex) { LogAPI.Debug("数据检查时发生异常,异常信息如下:"); LogAPI.Debug(ex); return; } finally { if (pfeature != null) Marshal.ReleaseComObject(pfeature); if (pCursor != null) Marshal.ReleaseComObject(pCursor); GC.Collect(); } } #endregion private bool JudgeSelfIntersect(IGeometry geometry) { ITopologicalOperator3 pTopology = null; try { pTopology = (geometry as ITopologicalOperator3).Boundary as ITopologicalOperator3; esriNonSimpleReasonEnum reason = esriNonSimpleReasonEnum.esriNonSimpleOK; pTopology.IsKnownSimple_2 = false; if (!pTopology.get_IsSimpleEx(out reason)) { if (reason == esriNonSimpleReasonEnum.esriNonSimpleSelfIntersections) return true; else return false; } return false; } catch { return false; } finally { if (pTopology != null) Marshal.ReleaseComObject(pTopology); } } } }