目录
X.1 Error creating topology:-2147220960 Message:应用程序未获得创建或修改此类型数据的方案的许可
X.2 Error creating topology:-2147220960 Message:尝试打开的数据库已被机器....以排他方式打开
先介绍一个ArcGIS拓扑检查的坑:
要素拓扑检查会修改原始数据,比如两条线间距为0.009米,实际不相交;如果容差设为0.1米,经过拓扑检查之后,会将此处融合并导致要素相交,如下图:
面对此种情形,我们应该在ArcCatalog中,新建 --> FeatureClassSet,设置更小的容差:
然后,将要检查的数据拷贝到该要素数据集中,然后在执行拓扑检查即可;注意两者的投影坐标系必须一致。
1 拓扑检查
1.1 拓扑检查的基本流程
1.2 拓扑检查代码
1.2.1 checkTopologyError
/// <summary>
/// 检查要素层中存在的拓扑错误
/// </summary>
/// <param name="wsPath">工作空间名称</param>
/// <param name="dsPath">数据集名称</param>
/// <param name="feaPath">要素类名称</param>
/// <param name="topologyName">拓扑要素层名,拓扑检查结果记录在该层中</param>
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("拓扑检查完毕", "提示信息");
}
1.2.2 AddRuleToTopology
/// <summary>
/// 增加拓扑规则
/// </summary>
/// <param name="topology">拓扑集</param>
/// <param name="ruleType">拓扑规则</param>
/// <param name="ruleName">规则名称</param>
/// <param name="featureClass">要素类</param>
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.");
}
}
1.2.3 ValidateTopology
//拓扑有效性检查
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);
}
}
1.2.4 调用代码及效果
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(), "执行失败");
}
}
![](https://img-blog.csdnimg.cn/20200319181551303.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20xbTJtM21tbQ==,size_16,color_FFFFFF,t_70)
2 拓扑关系枚举
2.1 将文字描述转化为拓扑规则枚举对象
/// <summary>
/// 根据错误的中文描述转换成esri拓扑枚举
/// </summary>
/// <param name="IN_TopoRuleType">拓扑类型</param>
/// <returns>ESRI.ArcGIS.Geodatabase下的拓扑规则枚举类</returns>
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;
}
2.2 根据拓扑关系ID获取拓扑描述
//根据错误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
};
/// <summary>
/// 根据ID获取错误类型
/// </summary>
/// <param name="IN_TopoType">l类型ID</param>
/// <returns>类型字符串</returns>
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;
}
X 异常处置
X.1 Error creating topology:-2147220960 Message:应用程序未获得创建或修改此类型数据的方案的许可
X.1.1异常描述
原因:缺乏Advanced许可
X.1.2 解决方案
只勾选Advanced,其他的不要勾选。
X.2 Error creating topology:-2147220960 Message:尝试打开的数据库已被机器....以排他方式打开
X.2.1 异常描述
这个异常是因为你的数据库文件被其他软件,如ArcGIS打开了,需要关闭
如果要素层同时被ArcGIS打开,会报如下异常:意思是要素已被排他的方式占用
X.2.2 解决办法
关闭数据库文件
X.3 从其他地方抄来的关于许可的说明
AE开发中的License有两种方法进行设置,一种是通过LicenseControl控件,另一种是通过IAoInitialize接口设置。整个应用程序中只能有一种方式存在,如果进行了两种License设置,就可能产生错误。当然,对于一个健壮的程序而言,我们还需要在初始化之前先判断将被初始化的许可是否可用,应先使用IsProductCodeAvailable方法进行判断,需要初始化扩展模块的许可,可使用CheckOutExtension方法。下面为许可的检测代码
一些重要原则
- 初始化许可的一条重要原则就是一个程序只能初始化许可一次,已经初始化许可的程序一旦运行就无法再修改其初始化的许可,即程序运行期间无法修改其使用的许可。
- LicenseControl中多选许可是没有意义的,第一个被勾选的许可生效。理论上License中可以勾选多项许可,但运行程序时其作用的是第一个被勾选的许可。如下图只有ArcGIS Engine许可被初始化了。
- 什么情况下需要GDB Update许可:当需要对SDE里数据进行编辑时,以及需要在SDE和Personal Geodatabase中创建复杂ArcGIS对象时,需要使用GDB Update许可。对SDE里的数据编辑,很好理解,大致就是进行数据插入,删除,更新;对表添加、删除和修改,表结构的变化(添加、删除列)等,因为这些动作都会造成后台数据库的写操作。
- 对 于Personal Geodatabase,进行简单数据对象和编辑,包括创建、删除和修改普通表都是不需要GDB Update许可的,但对于复杂的Geodatabse对象的创建、删除和修改,则需要GDB Update许可,其中复杂的Geodatabse对象包括几何网络,网络分析模型,拓扑,关系类。这也是为什么往往有写好了一个创建几何网络或拓扑的程 序后,执行起来会被报“需要Geodatabase Update许可”的错。
- 当需要获取GDB Update许可时,只需勾选ArcGIS Engine Enterprise Geodatabase就可以了
官方参考
- Checking for topology error features in a geodatabase topology
- ArcEngine 拓扑检查 总结
- ArcEngine的拓扑检查类
喜欢我的分享,可以关注以下两个公众号: