年度变更建库软件5.0版本
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

424 lines
18 KiB

6 months ago
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
{
/// <summary>
/// 拓扑帮助类
/// </summary>
public class DataCheckTopologyHelper
{
/// <summary>
///
/// </summary>
/// <param name="lstTopologyRule"></param>
/// <param name="m_Workspace"></param>
/// <param name="lstFeatureClassTabelName"></param>
/// <param name="objectName"></param>
/// <returns></returns>
public static List<RuleEntity> CreateTopology(List<ITopologyRule> lstTopologyRule,IWorkspace m_Workspace,List<string> 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<IFeatureClass> lstFeatureClass = new List<IFeatureClass>();
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<RuleEntity> 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);
}
}
}
/// <summary>
/// 判断拓扑是否存在,存在则删除
/// </summary>
/// <param name="m_Workspace">工作空间</param>
/// <param name="pFeatDS">要素集</param>
/// <param name="topologyName">拓扑名称</param>
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("无法将指定的规则添加到拓扑中");
}
}
/// <summary>
/// 创建拓扑
/// </summary>
/// <param name="pFtDs"></param>
/// <param name="pTopologyName"></param>
/// <param name="clusterTolerance"></param>
/// <returns></returns>
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);
}
}
/// <summary>
/// 通过名称获取要素集
/// </summary>
/// <param name="workspace"></param>
/// <param name="dsName"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 去掉".",得到名称缩写
/// </summary>
/// <param name="objectName"></param>
/// <returns></returns>
private static string GetFeatureObjectName(string objectName)
{
int index = objectName.LastIndexOf(".");
if (index >= 0)
{
return objectName.Substring(index + 1);
}
else
{
return objectName;
}
}
/// <summary>
/// 检查建立的拓扑
/// </summary>
/// <param name="topology"></param>
/// <param name="envelope"></param>
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);
}
/// <summary>
/// 给定拓扑和查找的范围,返回所有的拓扑错误要素
/// </summary>
/// <param name="topology"></param>
/// <param name="searchExtent"></param>
public static List<RuleEntity> FindAllErrorFeatures(ITopology topology, IEnvelope searchExtent, List<IFeatureClass> lstFeatureClass)
{
List<RuleEntity> lstErrorEnity = new List<RuleEntity>();
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文件,请先删除");
}
}
}
}