Checking for topology error features in a geodatabase topology (ArcObjects .NET 10.6 SDK)
ArcObjects Help for .NET developers > Developing with ArcGIS > Learning ArcObjects > Managing data > Working with feature data > Topologies > Checking for topology error features in a geodatabase topology (ArcObjects .NET 10.6 SDK)

Checking for topology error features in a geodatabase topology


Summary
This topic describes the different ways to search for and find error features discovered during validation of a geodatabase topology.

In this topic


Opening the topology

When checking for topology error features, first, open the topology by opening a feature dataset, cast it to the ITopologyContainer interface, and open the topology using the ITopologyContainer.TopologyByName property. See the following code example:
[C#]
// For example, featureDatasetName="Landbase."
// topologyName="Landbase_topology".
public ITopology OpenTopologyFromFeatureWorkspace(IFeatureWorkspace featureWorkspace,
    String featureDatasetName, String topologyName)
{
    // Open the feature dataset and cast it to ITopologyContainer.
    IFeatureDataset featureDataset=featureWorkspace.OpenFeatureDataset
        (featureDatasetName);
    ITopologyContainer topologyContainer=(ITopologyContainer)featureDataset;

    // Open the topology and return it.
    ITopology topology=topologyContainer.get_TopologyByName(topologyName);
    return topology;
}
[VB.NET]
' For example, featureDatasetName="Landbase."
' topologyName="Landbase_topology".

Public Function OpenTopologyFromFeatureWorkspace(ByVal featureWorkspace As IFeatureWorkspace, ByVal featureDatasetName As String, ByVal topologyName As String) As ITopology
    
    ' Open the feature dataset and cast it to ITopologyContainer.
    Dim featureDataset As IFeatureDataset=featureWorkspace.OpenFeatureDataset(featureDatasetName)
    Dim topologyContainer As ITopologyContainer=CType(featureDataset, ITopologyContainer)
    
    ' Open the topology and return it.
    Dim topology As ITopology=topologyContainer.TopologyByName(topologyName)
    
    Return topology
    
End Function
Alternatives to using the ITopologyContainer interface exist. For example, the ITopologyWorkspace interface can be used if the feature dataset containing the topology is unknown.

Checking for topology error features

The ITopology.State property can be used to check for the existence of error features in a topology. It has a return type of esriTopologyState. If the topology has been validated and errors were found, esriTSAnalyzedWithErrors will be returned.

Viewing a topology's rules

The topology's rules can be accessed by using ITopologyRuleContainer, which is implemented by the Topology class. ITopologyRuleContainer has several methods for viewing a topology's rules based on the ID of a feature class or a specific subtype of a feature class. 
The following code example shows how to acquire and use an enumerator of topology rules:
[C#]
public void DisplayTypesForEachRule(ITopology topology)
{
    // Cast the topology to ITopologyRuleContainer and get the rule enumerator.
    ITopologyRuleContainer topologyRuleContainer=(ITopologyRuleContainer)topology;
    IEnumRule enumRule=topologyRuleContainer.Rules;

    // Iterate through each rule.
    enumRule.Reset();
    IRule rule=null;
    while ((rule=enumRule.Next()) != null)
    {
        // Cast to ITopology and display the rule type.
        ITopologyRule topologyRule=(ITopologyRule)rule;
        Console.WriteLine("Rule type: {0}", topologyRule.TopologyRuleType);
    }
}
[VB.NET]
Public Sub DisplayTypesForEachRule(ByVal topology As ITopology)
    
    ' Cast the topology to ITopologyRuleContainer and get the rule enumerator.
    Dim topologyRuleContainer As ITopologyRuleContainer=CType(topology, ITopologyRuleContainer)
    Dim enumRule As IEnumRule=topologyRuleContainer.Rules
    
    ' Iterate through each rule.
    enumRule.Reset()
    Dim rule As IRule=Nothing
    
    Do While Not (rule) Is Nothing
        ' Cast to ITopology and display the rule type.
        Dim topologyRule As ITopologyRule=CType(rule, ITopologyRule)
        Console.WriteLine("Rule type: {0}", topologyRule.TopologyRuleType)
        rule=enumRule.Next()
    Loop
    
End Sub
For more information about topology rule types, see ITopologyRule and esriTopologyRuleType.

Accessing a topology's error features

Topologies can be cast to the IErrorFeatureContainer interface, which has properties that can be used to return the error features associated with a topology. Given a topology error feature, the following properties can be inspected through the ITopologyErrorFeature interface:
  • Rule violated
  • Feature class or classes involved in the error
  • Geometry of the error
  • Feature IDs of the features involved in the error
  • If the error has been marked as an exception
Each property on IErrorFeatureContainer requires a spatial reference parameter. For most users, this will be the spatial reference of the topology. 
The following code example shows the quickest method for obtaining the spatial reference of a topology:
[C#]
public ISpatialReference GetSpatialReferenceFromTopology(ITopology topology)
{
    IGeoDataset geoDataset=(IGeoDataset)topology;
    return geoDataset.SpatialReference;
}
[VB.NET]
Public Function GetSpatialReferenceFromTopology(ByVal topology As ITopology) As ISpatialReference
    
    Dim geoDataset As IGeoDataset=CType(topology, IGeoDataset)
    
    Return geoDataset.SpatialReference
    
End Function
The preceding code example will be included as part of the later examples in this topic.

Accessing error features with an ITopologyRule

There are four properties on the IErrorFeatureContainer interface. The IErrorFeatureContainer.ErrorFeatures property returns an enumerator of error features belonging to the specified topology rule within the supplied extent. The following code example shows how to get the error features for the extent of the topology:
[C#]
// Given the topology and specific topology rule, return the error features for that rule.
public void DisplayErrorFeaturesForRule(ITopology topology, ITopologyRule
    topologyRule)
{
    // Cast to required interfaces and get the spatial reference.
    IErrorFeatureContainer errorFeatureContainer=(IErrorFeatureContainer)topology;
    IGeoDataset geoDataset=(IGeoDataset)topology;
    ISpatialReference spatialReference=geoDataset.SpatialReference;

    // Get an enumerator for the error features.
    IEnumTopologyErrorFeature enumTopologyErrorFeature =
        errorFeatureContainer.get_ErrorFeatures(spatialReference, topologyRule,
        geoDataset.Extent, true, false);

    // Display the origin IDs for each of the error features.
    ITopologyErrorFeature topologyErrorFeature=null;
    while ((topologyErrorFeature=enumTopologyErrorFeature.Next()) != null)
    {
        Console.WriteLine("Origin feature OID: {0}", topologyErrorFeature.OriginOID);
    }
}
[VB.NET]
' Given the topology and specific topology rule, return the error features for that rule.

Public Sub DisplayErrorFeaturesForRule(ByVal topology As ITopology, ByVal topologyRule As ITopologyRule)
    
    ' Cast to required interfaces and get the spatial reference.
    Dim errorFeatureContainer As IErrorFeatureContainer=CType(topology, IErrorFeatureContainer)
    Dim geoDataset As IGeoDataset=CType(topology, IGeoDataset)
    Dim spatialReference As ISpatialReference=geoDataset.SpatialReference
    
    ' Get an enumerator for the error features.
    Dim enumTopologyErrorFeature As IEnumTopologyErrorFeature=errorFeatureContainer.ErrorFeatures(spatialReference, topologyRule, geoDataset.Extent, True, False)
    
    ' Display the origin IDs for each of the error features.
    Dim topologyErrorFeature As ITopologyErrorFeature=Nothing
    
    Do While Not (topologyErrorFeature) Is Nothing
        Console.WriteLine("Origin feature OID: {0}", topologyErrorFeature.OriginOID)
        topologyErrorFeature=enumTopologyErrorFeature.Next()
    Loop
    
End Sub
The final two parameters of the IErrorFeatureContainer.ErrorFeatures property indicate respectively, if error features and error features marked as exceptions should be retrieved. The preceding code example shows error features, not exceptions. At least one of the parameters must have a true value or the property fails.

Accessing error features by geometry type

The IErrorFeatureContainer.ErrorFeaturesByGeometryType property returns all error features of a certain geometry type. See the following code example that writes the ID properties for each error feature with the specified geometry type to the console:
[C#]
public void DisplayErrorFeatureByGeometryType(ITopology topology, esriGeometryType
    geometryType)
{
    // Cast to required interfaces and get the spatial reference.
    IErrorFeatureContainer errorFeatureContainer=(IErrorFeatureContainer)topology;
    IGeoDataset geoDataset=(IGeoDataset)topology;
    ISpatialReference spatialReference=geoDataset.SpatialReference;

    // Get all errors that have the specified geometry type.
    IEnumTopologyErrorFeature enumTopologyErrorFeature =
        errorFeatureContainer.get_ErrorFeaturesByGeometryType(spatialReference,
        geometryType, false);

    // Display each error feature (if any exist) and display their properties.
    ITopologyErrorFeature topologyErrorFeature=null;
    while ((topologyErrorFeature=enumTopologyErrorFeature.Next()) != null)
    {
        Console.WriteLine("Error Feature Origin Class ID: {0}",
            topologyErrorFeature.OriginClassID);
        Console.WriteLine("Error Feature Origin Feature ID: {0}",
            topologyErrorFeature.OriginOID);
        Console.WriteLine("Error Feature Dest. Class ID: {0}",
            topologyErrorFeature.DestinationClassID);
        Console.WriteLine("Error Feature Dest. Feature ID: {0}",
            topologyErrorFeature.DestinationOID);
    }
}
[VB.NET]
Public Sub DisplayErrorFeatureByGeometryType(ByVal topology As ITopology, ByVal geometryType As esriGeometryType)
    
    ' Cast to required interfaces and get the spatial reference.
    Dim errorFeatureContainer As IErrorFeatureContainer=CType(topology, IErrorFeatureContainer)
    Dim geoDataset As IGeoDataset=CType(topology, IGeoDataset)
    Dim spatialReference As ISpatialReference=geoDataset.SpatialReference
    
    ' Get all errors that have the specified geometry type.
    Dim enumTopologyErrorFeature As IEnumTopologyErrorFeature=errorFeatureContainer.ErrorFeaturesByGeometryType(spatialReference, geometryType, False)
    
    ' Display each error feature (if any exist) and display their properties.
    Dim topologyErrorFeature As ITopologyErrorFeature=Nothing
    
    Do While Not (topologyErrorFeature) Is Nothing
        Console.WriteLine("Error Feature Origin Class ID: {0}", topologyErrorFeature.OriginClassID)
        Console.WriteLine("Error Feature Origin Feature ID: {0}", topologyErrorFeature.OriginOID)
        Console.WriteLine("Error Feature Dest. Class ID: {0}", topologyErrorFeature.DestinationClassID)
        Console.WriteLine("Error Feature Dest. Feature ID: {0}", topologyErrorFeature.DestinationOID)
        topologyErrorFeature=enumTopologyErrorFeature.Next()
    Loop
    
End Sub
Similar to the IErrorFeatureContainer.ErrorFeatures property, the final parameter of the IErrorFeatureContainer.ErrorFeaturesByGeometryType property is a Boolean, which indicates if errors or exceptions should be returned. See the following:
  • If set to false (as in the preceding code example), only error features will be returned.
  • If set to true, only exceptions will be returned.

Accessing error features by rule type

The IErrorFeatureContainer.ErrorFeaturesByRuleType property returns an enumerator of error features belonging to the specified topology rule type in the supplied extent. Notice how this differs from the IErrorFeatureContainer.ErrorFeatures property, in that a reference to an ITopologyRule is not required, but rather a value from the esriTopologyRuleType enumeration is. This also differs from the other property in that no specific rule is specified; therefore, if several rules have the same rule type, error features from each will be returned. See the following code example:
[C#]
public void DisplayErrorFeatureByRuleType(ITopology topology, esriTopologyRuleType
    topologyRuleType)
{
    // Cast to required interfaces and get the spatial reference.
    IErrorFeatureContainer errorFeatureContainer=(IErrorFeatureContainer)topology;
    IGeoDataset geoDataset=(IGeoDataset)topology;
    ISpatialReference spatialReference=geoDataset.SpatialReference;

    // Return all errors for the supplied rule in the given extent, then retrieve the first one.
    IEnumTopologyErrorFeature enumTopologyErrorFeature =
        errorFeatureContainer.get_ErrorFeaturesByRuleType(spatialReference,
        topologyRuleType, geoDataset.Extent, true, false);

    // Get the first error feature (if any exist) and display its properties.
    ITopologyErrorFeature topologyErrorFeature=enumTopologyErrorFeature.Next();
    if (topologyErrorFeature != null)
    {
        Console.WriteLine("Error Feature Origin Class ID: {0}",
            topologyErrorFeature.OriginClassID);
        Console.WriteLine("Error Feature Origin Feature ID: {0}",
            topologyErrorFeature.OriginOID);
        Console.WriteLine("Error Feature Dest. Class ID: {0}",
            topologyErrorFeature.DestinationClassID);
        Console.WriteLine("Error Feature Dest. Feature ID: {0}",
            topologyErrorFeature.DestinationOID);
    }
}
[VB.NET]
Public Sub DisplayErrorFeatureByRuleType(ByVal topology As ITopology, ByVal topologyRuleType As esriTopologyRuleType)
    
    ' Cast to required interfaces and get the spatial reference.
    Dim errorFeatureContainer As IErrorFeatureContainer=CType(topology, IErrorFeatureContainer)
    Dim geoDataset As IGeoDataset=CType(topology, IGeoDataset)
    Dim spatialReference As ISpatialReference=geoDataset.SpatialReference
    
    ' Return all errors for the supplied rule in the given extent, then retrieve the first one.
    Dim enumTopologyErrorFeature As IEnumTopologyErrorFeature=errorFeatureContainer.ErrorFeaturesByRuleType(spatialReference, topologyRuleType, geoDataset.Extent, True, False)
    
    ' Get the first error feature (if any exist) and display its properties.
    Dim topologyErrorFeature As ITopologyErrorFeature=enumTopologyErrorFeature.Next()
    If Not topologyErrorFeature Is Nothing Then
        Console.WriteLine("Error Feature Origin Class ID: {0}", topologyErrorFeature.OriginClassID)
        Console.WriteLine("Error Feature Origin Feature ID: {0}", topologyErrorFeature.OriginOID)
        Console.WriteLine("Error Feature Dest. Class ID: {0}", topologyErrorFeature.DestinationClassID)
        Console.WriteLine("Error Feature Dest. Feature ID: {0}", topologyErrorFeature.DestinationOID)
    End If
    
End Sub
As with the IErrorFeatureContainer.ErrorFeatures property, the final two parameters are Booleans. The first parameter indicates if error features will be returned and the second indicates if exceptions will be returned. 

Accessing error features individually

The IErrorFeatureContainer.ErrorFeature property returns a specific topology error feature corresponding to the rule type, geometry type, and source feature information. The rule and geometry type are required, as topological rules can result in error features with different geometries (point, line, or polygon). See the following code example:
[C#]
// The following code example returns a polygon topology error feature for the must not 
// overlap rule.
public ITopologyErrorFeature GetErrorFeatureForNoOverlapRule(ITopology topology,
    IFeatureClass featureClass, int originFeatureOID, int destFeatureOID)
{
    // Cast to required interfaces and get the spatial reference.
    IErrorFeatureContainer errorFeatureContainer=(IErrorFeatureContainer)topology;
    IGeoDataset geoDataset=(IGeoDataset)topology;
    ISpatialReference spatialReference=geoDataset.SpatialReference;

    // Find the error feature and return it.
    ITopologyErrorFeature topologyErrorFeature =
        errorFeatureContainer.get_ErrorFeature(spatialReference,
        esriTopologyRuleType.esriTRTAreaNoOverlap,
        esriGeometryType.esriGeometryPolygon, featureClass.FeatureClassID,
        originFeatureOID, featureClass.FeatureClassID, destFeatureOID);
    return topologyErrorFeature;
}
[VB.NET]
' The following code example returns a polygon topology error feature for the must not
' overlap rule.

Public Function GetErrorFeatureForNoOverlapRule(ByVal topology As ITopology, ByVal featureClass As IFeatureClass, ByVal originFeatureOID As Integer, ByVal destFeatureOID As Integer) As ITopologyErrorFeature
    
    ' Cast to required interfaces and get the spatial reference.
    Dim errorFeatureContainer As IErrorFeatureContainer=CType(topology, IErrorFeatureContainer)
    Dim geoDataset As IGeoDataset=CType(topology, IGeoDataset)
    Dim spatialReference As ISpatialReference=geoDataset.SpatialReference
    
    ' Find the error feature and return it.
    Dim topologyErrorFeature As ITopologyErrorFeature=errorFeatureContainer.ErrorFeature(spatialReference, esriTopologyRuleType.esriTRTAreaNoOverlap, esriGeometryType.esriGeometryPolygon, featureClass.FeatureClassID, originFeatureOID, featureClass.FeatureClassID, destFeatureOID)
    
    Return topologyErrorFeature
    
End Function
The IErrorFeatureContainer.ErrorFeature property has the following parameters that require knowledge of the rule being used, and the feature classes and features resulting in the error feature:
  • GeometryType—Geometry type of the error feature requested
  • OriginClassID—Class ID of the feature class to which the rule is applied
  • OriginOID—ObjectID of the origin feature causing the error
  • DestinationClassID—Class ID of the feature class in which the rule interacts
  • DestinationOID—ObjectID of the destination feature causing the error
Passing correct values into each of these parameters is crucial, as the property returns a null value if any are incorrect. In addition, not all parameters are applicable for each rule type. An example is the "must not have gaps" rule. Since gaps do not really belong to features, the OriginOID and DestinationOID parameters must have values of 0.
Many rules involve a single class, with no destination class involved (as shown in the previous code example). Since two features are involved, both feature class IDs must be specified, even though the origin and destination class ID is the same. For the most part, if only one feature class is part of the rule and only a single feature is involved, the destination class ID can be set to 0.
Other rules use two classes but only an origin feature. The polygon rule, "contains point," follows this pattern. The origin and destination class ID parameters must contain valid class IDs, but since the error features indicate the absence of a feature (a point within a polygon), the destination ObjectID will always be 0. The polygon rule, "must cover each other," requires features of two different polygon feature classes to cover each other. If it has an origin feature uncovered, the destination feature ID will be 0, but if a destination feature is uncovered, the origin feature ID will be 0.
Selecting the correct geometry type for the error feature is also important, as a rule that is applied to a feature class of one geometry type can return error features of a different geometry type. For example, the "must not have gaps" rule, which applies to feature classes containing polygons but returns error features with polyline geometries. Further complicating the situation is that not all rules consistently return error features with the same geometry type. The rule for lines "must not intersect" is an example of this, as it can return error features with point or line geometries, depending on the cause of the error. If an incorrect geometry type is passed to the IErrorFeatureContainer.ErrorFeature property, a null value will be returned, even if all of the other parameters are correct.

Accessing error features by extent

Another common task is finding the topology errors within given extent. The following code example shows how to do this:
[C#]
public void FindAllErrorFeatures(ITopology topology, IEnvelope searchExtent)
{
    // Cast to required interfaces and get the spatial reference.
    IErrorFeatureContainer errorFeatureContainer=(IErrorFeatureContainer)topology;
    IGeoDataset geoDataset=(IGeoDataset)topology;
    ISpatialReference spatialReference=geoDataset.SpatialReference;
    ITopologyRuleContainer topologyRuleContainer=(ITopologyRuleContainer)topology;

    // Get an enumerator for the topology's rules and iterate through them.
    IEnumRule enumRule=topologyRuleContainer.Rules;
    enumRule.Reset();
    IRule rule=null;
    while ((rule=enumRule.Next()) != null)
    {
        // For each rule, get an enumerator for all of the error features and exceptions.
        ITopologyRule topologyRule=(ITopologyRule)rule;
        IEnumTopologyErrorFeature enumTopologyErrorFeature =
            errorFeatureContainer.get_ErrorFeatures(spatialReference, topologyRule,
            searchExtent, true, true);

        ITopologyErrorFeature topologyErrorFeature=null;
        while ((topologyErrorFeature=enumTopologyErrorFeature.Next()) != null)
        {
            // For each error feature, display the class ID, ObjectID, and if it's an exception.
            Console.WriteLine("Class ID: {0} Object ID: {0} IsException {0}",
                topologyErrorFeature.OriginClassID, topologyErrorFeature.OriginOID,
                topologyErrorFeature.IsException);
        }
    }
}
[VB.NET]
Public Sub FindAllErrorFeatures(ByVal topology As ITopology, ByVal searchExtent As IEnvelope)
    
    ' Cast to required interfaces and get the spatial reference.
    Dim errorFeatureContainer As IErrorFeatureContainer=CType(topology, IErrorFeatureContainer)
    Dim geoDataset As IGeoDataset=CType(topology, IGeoDataset)
    Dim spatialReference As ISpatialReference=geoDataset.SpatialReference
    Dim topologyRuleContainer As ITopologyRuleContainer=CType(topology, ITopologyRuleContainer)
    
    ' Get an enumerator for the topology's rules and iterate through them.
    Dim enumRule As IEnumRule=topologyRuleContainer.Rules
    enumRule.Reset()
    Dim rule As IRule=Nothing
    
    Do While Not (rule) Is Nothing
        ' For each rule, get an enumerator for all of the error features and exceptions.
        Dim topologyRule As ITopologyRule=CType(rule, ITopologyRule)
        Dim enumTopologyErrorFeature As IEnumTopologyErrorFeature=errorFeatureContainer.ErrorFeatures(spatialReference, topologyRule, searchExtent, True, True)
        
        Dim topologyErrorFeature As ITopologyErrorFeature=Nothing
        
        Do While Not (topologyErrorFeature) Is Nothing
            ' For each error feature, display the class ID, ObjectID, and if it's an exception.
            Console.WriteLine("Class ID: {0} Object ID: {0} IsException {0}", topologyErrorFeature.OriginClassID, topologyErrorFeature.OriginOID, topologyErrorFeature.IsException)
            topologyErrorFeature=enumTopologyErrorFeature.Next()
        Loop
        
        rule=enumRule.Next()
        
    Loop
    
End Sub


See Also:

Creating a topology in the geodatabase
Working with topologically related features
Listening to the OnValidate event for a geodatabase topology
Geodatabase topology rules and topology error fixes




To use the code in this topic, reference the following assemblies in your Visual Studio project. In the code files, you will need using (C#) or Imports (VB .NET) directives for the corresponding namespaces (given in parenthesis below if different from the assembly name):
Development licensing Deployment licensing
ArcGIS Desktop Standard ArcGIS Desktop Standard
ArcGIS Desktop Advanced ArcGIS Desktop Advanced
Engine Developer Kit Engine: Geodatabase Update