目录
1 拓扑检查
1.1 拓扑检查的基本流程
1.2 拓扑检查代码
1.2.1 checkTopologyError
1.2.2 AddRuleToTopology
1.2.3 ValidateTopology
1.2.4 调用代码及效果
2 拓扑关系枚举
2.1 将文字描述转化为拓扑规则枚举对象
2.2 根据拓扑关系ID获取拓扑描述
X 异常处置
X.1 Error creating topology:-2147220960 Message:应用程序未获得创建或修改此类型数据的方案的许可
X.1.1异常描述
X.1.2 解决方案
X.2 Error creating topology:-2147220960 Message:尝试打开的数据库已被机器....以排他方式打开
X.2.1 异常描述
X.2.2 解决办法
X.3 从其他地方抄来的关于许可的说明
官方参考
先介绍一个ArcGIS拓扑检查的坑:
要素拓扑检查会修改原始数据,比如两条线间距为0.009米,实际不相交;如果容差设为0.1米,经过拓扑检查之后,会将此处融合并导致要素相交,如下图:
面对此种情形,我们应该在ArcCatalog中,新建 --> FeatureClassSet,设置更小的容差:
然后,将要检查的数据拷贝到该要素数据集中,然后在执行拓扑检查即可;注意两者的投影坐标系必须一致。
///
/// 检查要素层中存在的拓扑错误
///
/// 工作空间名称
/// 数据集名称
/// 要素类名称
/// 拓扑要素层名,拓扑检查结果记录在该层中
public void checkTopologyError(string wsPath, string dsPath, string feaPath, string topologyName)
{
// Open the workspace and the required datasets.
Type factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.AccessWorkspaceFactory");
//ESRI.ArcGIS.DataSourcesGDB
IWorkspaceFactory workspaceFactory = new AccessWorkspaceFactory();
//1. 打开数据集文件
IWorkspace workspace = workspaceFactory.OpenFromFile(wsPath, 0);
IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspace;
//2. 打开数据集文件
IFeatureDataset featureDataset = featureWorkspace.OpenFeatureDataset(dsPath);
//3. 向拓扑集中添加要素层
IFeatureClass LRDLlayer = featureWorkspace.OpenFeatureClass(feaPath);
//4. 设置拓扑处理对数据集的独占权限
ISchemaLock schemaLock = (ISchemaLock)featureDataset;//注意此时不能使用ArcGIS再打开这个数据集
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.esriTRTLineNoDangles, "线要素不允许有悬挂点", LRDLlayer);
AddRuleToTopology(topology, esriTopologyRuleType.esriTRTLineNoPseudos, "线要素不允许有伪节点", LRDLlayer);
AddRuleToTopology(topology, esriTopologyRuleType.esriTRTLineNoIntersectOrInteriorTouch, "线要素不能重叠或内部接触", LRDLlayer);
AddRuleToTopology(topology, esriTopologyRuleType.esriTRTLineNoSelfIntersect, "线要素不能自相交", LRDLlayer);
//5.5 拓扑验证
IGeoDataset geoDataset = (IGeoDataset)topology;
IEnvelope 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("Could not add specified rule to the topology.");
}
}
//拓扑有效性检查
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);
}
}
private void buttonExecute_Click(object sender, EventArgs e)
{
try
{
//---------------------------检查拓扑错误-------------------------------------
string inPath = textBoxInput.Text;
string ouPath = textBoxOutput.Text;
if (System.IO.File.Exists(inPath))
{
checkTopologyError(inPath, "Topology", "LRDL", "TopologyCheck1");
}
//------------------------------------------------------------------------------
}
catch (Exception ex)
{
MessageBox.Show("触发异常操作:" + ex.ToString(), "执行失败");
}
}
///
/// 根据错误的中文描述转换成esri拓扑枚举
///
/// 拓扑类型
/// ESRI.ArcGIS.Geodatabase下的拓扑规则枚举类
private esriTopologyRuleType PRV_ConvertTopologyRuleType(TopoErroType IN_TopoRuleType)
{
esriTopologyRuleType Temp_TopoRuleType;
switch (IN_TopoRuleType)
{
case TopoErroType.面要素之间无空隙:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaNoGaps;
break;
case TopoErroType.任何规则:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTAny;
break;
case TopoErroType.要素大于最小容差:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTFeatureLargerThanClusterTolerance;
break;
case TopoErroType.面要素间无重叠:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaNoOverlap;
break;
case TopoErroType.第二个图层面要素必须被第一个图层任一面要素覆盖:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaCoveredByAreaClass;
break;
case TopoErroType.面要素必须只包含一个点要素:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaContainOnePoint;
break;
case TopoErroType.两图层面要素必须互相覆盖:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaAreaCoverEachOther;
break;
case TopoErroType.第一个图层面要素必须被第一个图层任一面要素包含:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaCoveredByArea;
break;
case TopoErroType.图层间面要素不能相互覆盖:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaNoOverlapArea;
break;
case TopoErroType.线要素必须跟面图层边界的一部分或全部重叠:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineCoveredByAreaBoundary;
break;
case TopoErroType.点要素必须落在面要素边界上:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTPointCoveredByAreaBoundary;
break;
case TopoErroType.点要素必须落在面要素内:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTPointProperlyInsideArea;
break;
case TopoErroType.线要素间不能有相互重叠部分:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoOverlap;
break;
case TopoErroType.线要素之间不能相交:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoIntersection;
break;
case TopoErroType.线要素不允许有悬挂点:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoDangles;
break;
case TopoErroType.线要素不允许有假节点:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoPseudos;
break;
case TopoErroType.第一个图层线要素应被第二个线图层线要素覆盖:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineCoveredByLineClass;
break;
case TopoErroType.第一个图层线要素不被第二个线图层线要素覆盖:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoOverlapLine;
break;
case TopoErroType.点要素应被线要素覆盖:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTPointCoveredByLine;
break;
case TopoErroType.点要素应在线要素的端点上:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTPointCoveredByLineEndpoint;
break;
case TopoErroType.面要素边界必须被线要素覆盖:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaBoundaryCoveredByLine;
break;
case TopoErroType.面要素的边界必须被另一面要素边界覆盖:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaBoundaryCoveredByAreaBoundary;
break;
case TopoErroType.线要素不能自重叠:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoSelfOverlap;
break;
case TopoErroType.线要素不能自相交:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoSelfIntersect;
break;
case TopoErroType.线要素间不能重叠和相交:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoIntersectOrInteriorTouch;
break;
case TopoErroType.线要素端点必须被点要素覆盖:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineEndpointCoveredByPoint;
break;
case TopoErroType.面要素内必须包含至少一个点要素:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaContainPoint;
break;
case TopoErroType.线不能是多段:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoMultipart;
break;
case TopoErroType.点要素之间不相交:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTPointDisjoint;
break;
case TopoErroType.线要素必须不相交:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoIntersectLine;
break;
case TopoErroType.线必须不相交或内部接触:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoIntersectOrInteriorTouchLine;
break;
default:
Temp_TopoRuleType = esriTopologyRuleType.esriTRTAny;//将此规则赋予拓扑会直接报错
break;
}
return Temp_TopoRuleType;
}
//根据错误ID获取对应描述
public enum TopoErroType
{
任何规则 = -1,
要素大于最小容差 = 0,
面要素之间无空隙 = 1,
面要素间无重叠 = 3,
第二个图层面要素必须被第一个图层任一面要素覆盖 = 4,
两图层面要素必须互相覆盖 = 5,
第一个图层面要素必须被第一个图层任一面要素包含 = 7,
图层间面要素不能相互覆盖 = 8,
线要素必须跟面图层边界的一部分或全部重叠 = 10,
线要素必须在面内 = 11,
点要素必须落在面要素边界上 = 13,
点要素必须落在面要素内 = 15,
面要素必须只包含一个点要素 = 16,
线要素间不能有相互重叠部分 = 19,
线要素之间不能相交 = 20,
线要素不允许有悬挂点 = 21,
线要素不允许有假节点 = 22,
第一个图层线要素应被第二个线图层线要素覆盖 = 26,
第一个图层线要素不被第二个线图层线要素覆盖 = 28,
点要素应被线要素覆盖 = 29,
点要素应在线要素的端点上 = 31,
点要素之间不相交 = 34,
点要素重合点要素 = 35,
面要素边界必须被线要素覆盖 = 37,
面要素的边界必须被另一面要素边界覆盖 = 38,
线要素不能自重叠 = 39,
线要素不能自相交 = 40,
线要素间不能重叠和相交 = 41,
线要素端点必须被点要素覆盖 = 42,
面要素内必须包含至少一个点要素 = 43,
线不能是多段 = 44,
线要素必须不相交 = 45,
线必须不相交或内部接触 = 46
};
///
/// 根据ID获取错误类型
///
/// l类型ID
/// 类型字符串
private string PRV_RecorverTopologyRuleType(int IN_TopoType)
{
//根据枚举值获取枚举名
string Temp_ErrorDiscripe = Enum.GetName(typeof(TopoErroType), IN_TopoType);
if (Temp_ErrorDiscripe == null)
return (IN_TopoType.ToString());//若规则不在列表内则直接返回规则号
else
return Temp_ErrorDiscripe;
}
原因:缺乏Advanced许可
只勾选Advanced,其他的不要勾选。
这个异常是因为你的数据库文件被其他软件,如ArcGIS打开了,需要关闭
如果要素层同时被ArcGIS打开,会报如下异常:意思是要素已被排他的方式占用
关闭数据库文件
原文链接:ArcGIS Engine中的License设置
AE开发中的License有两种方法进行设置,一种是通过LicenseControl控件,另一种是通过IAoInitialize接口设置。整个应用程序中只能有一种方式存在,如果进行了两种License设置,就可能产生错误。当然,对于一个健壮的程序而言,我们还需要在初始化之前先判断将被初始化的许可是否可用,应先使用IsProductCodeAvailable方法进行判断,需要初始化扩展模块的许可,可使用CheckOutExtension方法。下面为许可的检测代码
一些重要原则
ArcEngine创建拓扑并验证拓扑
ArcEngine实现拓扑检查
喜欢我的分享,可以关注以下两个公众号: