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.
423 lines
18 KiB
423 lines
18 KiB
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文件,请先删除"); |
|
} |
|
} |
|
|
|
} |
|
}
|
|
|