Creating a topology in the geodatabase


Summary
A topology is a collection of simple feature classes within the same feature dataset that participate in topological relationships with a set of rules that govern those relationships. Topologies can have multiple feature classes in the same topological role. A feature dataset can have multiple topologies, but a feature class can only belong to one topology and only simple feature classes can participate in a topology.
Before creating the topology, ensure that an exclusive schema lock has been obtained for the feature dataset. Use the ISchemaLock interface to determine if other locks exist and to get an exclusive lock on the feature dataset. This topic shows a common workflow for creating topologies within the geodatabase.


About creating a topology in the geodatabase

Topologies can be created in the geodatabase using the ITopologyContainer.CreateTopology and ITopologyContainer2.CreateTopologyEx methods, both of which have an ITopology return type. Once the topology is created, the ITopology.AddClass and ITopologyRuleContainer.AddRule methods can be used to add classes and rules to the topology.
Each topology has one associated topology graph. The topology graph is a planar representation of the geometries in the feature classes participating in a geodatabase topology. If accessing the topology graph directly to work with topology primitives, such as edges and nodes is required, see Working with topologically related features.
When features are created, edited, or deleted, the topology is responsible for creating or modifying a dirty area that encompasses the envelope of the feature. A dirty area is a special type of feature where the state of the topology is unknown. Features that are covered by dirty areas can still be edited and queried, but their topological relationships cannot be guaranteed to be correct. A dirty area must be validated to discover the topology of its underlying features and guarantee their correctness.
The following illustration shows an example of how dirty areas and topology errors work in a topology:


Each topology has one inherent rule—esriTRTFeatureLargerThanClusterTolerance—to identify features that are less than the defined cluster tolerance for the topology.

Initial topology creation

Both available methods create a topology with the specified name, cluster tolerance, maximum allowable number of generated errors, and for ArcSDE, the supplied configuration keyword is created. When a topology is initially created, it has no participating feature classes or rules. The decision on when to use CreateTopology over CreateTopologyEx (and vice versa) is based on whether the feature classes that participate in the topology are z–aware. If they are not z–aware, use the CreateTopology method. If the feature classes are z–aware, use the CreateTopologyEx method as it allows the setting of a z–cluster tolerance, in addition to the x,y–cluster tolerance.
Give careful consideration to specifying the parameters when creating a topology. Once the topology is built, none of the parameters can be modified. To change properties, such as cluster tolerance, the topology must be deleted and rebuilt with the new parameters.

Topology name

A name is required to create a topology. The name of the topology (fully qualified name for ArcSDE geodatabases) must be unique within the geodatabase. The IWorkspace2.NameExists property can be used to verify the uniqueness of a name. If a feature dataset contains a single topology, it might be convenient to give it a name that is based on that of the feature dataset, such as Parcels_Topo.

X,y–cluster tolerance

In general, set the ClusterTolerance parameter to the ITopologyContainer.DefaultClusterTolerance property of the feature dataset. In geodatabases for ArcGIS 9.2 and later, this value is equal to the tolerance of the feature dataset, which is generally 0.001 meters or the equivalent in the units of the spatial reference. Values that are smaller than the default cluster tolerance or larger than the ITopologyContainer.MaximumClusterTolerance property are not permitted.

Z–cluster tolerance

The z–tolerance is used to distinguish the z–height or elevation of vertices within the tolerance of one another. For example, two adjacent features of different heights can share a common edge between them. Their x,y–vertices are located close together, not their z–value or height.
The value supplied for z–tolerance depends on the type of surface being modeled with the z-aware feature classes. When modeling city buildings, two buildings can be adjacent to one another and appear to share a common edge in the x,y–domain. However, there might be concerns about maintaining the relative height of each building structure during the topology validation process. Setting the z–cluster tolerance to a value of 0 prevents z-values from clustering when the topology is validated. The default z–cluster tolerance for all topologies is 0 and can be obtained through the ITopologyContainer2.DefaultZClusterTolerance property.
The following illustration shows how the validation process behaves with a z–cluster tolerance of 0. The vertices on the left side of the red feature (smaller squares) are coincident with the right edge of the blue feature (larger squares). This results in two vertices being introduced to the blue feature during validation. Because the z–tolerance is 0, the two new vertices have z–values of 10, equaling the values of their neighboring vertices in the blue feature.
When modeling a surface, datasets can be collected with different x,y,z–accuracies. In this case, it might be beneficial to set the z–cluster tolerance greater than 0 to allow clustering during the validation process. To avoid z–values collected with a high-level of accuracy clustering to z–values of less accuracy, each feature class can be assigned a rank. Lower-ranked features' z–values cluster to the elevation of higher-ranked vertices if they fall within the cluster tolerance. Z–values of vertices belonging to feature classes of the same rank are averaged if they fall within the cluster tolerance.
The following illustration shows how the validation process behaves with a z–cluster tolerance greater than 0. The vertices on the left side of the red feature (smaller squares) are coincident with vertices on the right edge of the blue feature (larger squares). The vertices on the red feature have z–values of 20, while the vertices of the blue feature have z–values of 10. During validation, the z–values are clustered, since they lie within the z–cluster tolerance and result in the vertices having z–values of 15.

Maximum generated error count and configuration keywords

The maxGeneratedErrorCount parameter specifies the maximum number of errors validation generates before stopping. Setting a value of –1 indicates there is no limit to the number of errors that are generated. Generally, use the default value of –1.
The configurationKeyword parameter allows the application to control the physical layout for this table in the underlying relational database management system (RDBMS). For example, in the case of an Oracle database, the configuration keyword controls the table space where the table is created, the initial and next extents, and other properties.
The configurationKeywords parameter allows the application to specify a configuration keyword for the topology. Configuration keywords are set up by the ArcSDE data administrator. The list of available keywords supported by a workspace can be obtained using the IWorkspaceConfiguration interface. The configurationKeyword parameter is not mandatory when building a topology in an ArcSDE geodatabase. An empty string can be specified where the topology is built using the default configuration. For more information on configuration keywords, see the ArcGIS Desktop Help topic Configuration keywords for ArcSDE geodatabases.
Before creating a topology, obtain an exclusive schema lock for the target feature dataset.  For more information on obtaining an exclusive lock, see Using schema locks, or the complete code example at the end of this topic.
The following code examples show how to use the CreateTopology and CreateTopologyEx methods to create a topology:
[C#]
// featureDataset is an IFeatureDataset where the topology will be located.
// specifyZClusterTolerance is a System.Boolean whether a ZClusterTolerance has been specified.
// topologyName is a string with the topology's name.

// Cast the feature dataset to the ITopologyContainer2 interface to create a topology.
ITopologyContainer2 topologyContainer = (ITopologyContainer2)featureDataset;
ITopology topology = null;
if (specifyZClusterTolerance)
{
    topology = topologyContainer.CreateTopologyEx(topologyName,
        topologyContainer.DefaultClusterTolerance,
        topologyContainer.DefaultZClusterTolerance,  - 1, "");
}

else
{
    topology = topologyContainer.CreateTopology(topologyName,
        topologyContainer.DefaultClusterTolerance,  - 1, "");
}
[VB.NET]
' featureDataset is an IFeatureDataset where the topology will be located.
' specifyZClusterTolerance is a System.Boolean whether a ZClusterTolerance has been specified.
' topologyName is a String with the topology's name

' Cast the feature dataset to the ITopologyContainer2 interface to create a topology.
Dim topologyContainer As ITopologyContainer2 = CType(featureDataset, ITopologyContainer2)
Dim topology As ITopology = Nothing
If specifyZClusterTolerance Then
    topology = topologyContainer.CreateTopologyEx(topologyName, topologyContainer.DefaultClusterTolerance, topologyContainer.DefaultZClusterTolerance, -1, "")
Else
    topology = topologyContainer.CreateTopology(topologyName, topologyContainer.DefaultClusterTolerance, -1, "")
End If

Add feature classes to a topology

The AddClass method is used to add a feature class to a topology with the specified weight and ranks. The weight must be an integer between 1 and 10. Although it is not used in ArcGIS, it must still be specified. The x,y–rank and z–rank must each be an integer between 1 and 63.
Ranks higher than 51 result in errors when specified on the New Topology wizard or Topology property page. Even if the feature class being added to the topology is not z–aware, it must have a z–rank specified. The x,y and z–ranks represent the accuracies of the feature class relative to other feature classes participating in the topology. Feature classes with a higher rank, such as 1, are more accurate than feature classes with a lower rank, such as 2. 
Ranks are a relative measure of accuracy. The difference between two features classes of ranks 1 and 2 is the same as two feature classes with ranks of 1 and 50. Multiple feature classes in a topology can have the same rank.
The EventNotificationOnValidate parameter indicates if an event is broadcast when the topology that the feature class participates in is validated. The EventNotificationOnValidate parameter can only be set if the topology is created programmatically. The ITopologyClassEvents interface exposes the OnValidate event, which is fired each time a dirty area is validated in the topology where the class is participating. The event returns an IGeometry reference corresponding to the area that was validated.
Complicated feature classes, such as annotation, dimension, geometric network, and feature classes already in a topology, cannot be added to a topology. Also, object classes, or tables and versioned uncomplicated feature classes, cannot be added to a topology. 
After a populated feature class is added to a topology that has been validated—in whole or in part—the state of the topology changes and a dirty area corresponding to the extent of the feature class is created. If an unpopulated feature class is added to a topology, the topology's state does not change and no dirty area is created.
The following code example shows how to add a feature class to a topology:
[C#]
// ITopology.AddClass(IClass class, double weight, int xyRank, int zRnk, Boolean EventNotificationOnValidate).
topology.AddClass(featureClass, weight, xyRank, zRank, false);
[VB.NET]
' ITopology.AddClass(IClass class, double weight, int xyrank, int zrank, Boolean EventNotificationOnValidate).
topology.AddClass(featureClass, weight, xyRank, zRank, False)

Add rules to a topology

As previously mentioned, each topology is created with at least one default rule (that is, must be larger than cluster tolerance rule). In most cases, additional rules will be added to a topology. The ITopologyRuleContainer interface provides access for adding, removing, and returning topology rules from a topology. This interface also provides access to members that control the promotion and demotion of topology errors and exceptions.
Before adding a rule to a topology, use the CanAddRule property to determine if the rule is consistent and does not conflict with any existing topology rules. For example, topology rules of the same type cannot be specified at the class level and subtype level for the same feature class.
Using AddRule on a topology that has already been validated—in whole or in part—results in a dirty area created for the extent of the feature classes participating in the rule and a change to the state of the topology to esriTSUnanalyzed.
The following code example shows how to create a single feature class topology rule and add it to a topology: 
[C#]
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.");
    }
}
[VB.NET]
Public Sub AddRuleToTopology(ByVal topology As ITopology, ByVal ruleType As esriTopologyRuleType, ByVal ruleName As String, ByVal featureClass As IFeatureClass)
    
    ' Create a topology rule.
    Dim topologyRule As ITopologyRule = 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.
    Dim topologyRuleContainer As ITopologyRuleContainer = CType(topology, ITopologyRuleContainer)
    If topologyRuleContainer.CanAddRule(topologyRule) Then
        topologyRuleContainer.AddRule(topologyRule)
    Else
        Throw New ArgumentException("Could not add specified rule to the topology.")
    End If
    
End Sub
The following code example demonstrates how to create a topology rule between two feature classes, specify it at the subtype level for the destination, and add it to the topology:
[C#]
public void AddRuleToTopology(ITopology topology, esriTopologyRuleType ruleType,
    String ruleName, IFeatureClass originClass, int originSubtype, IFeatureClass
    destinationClass, int destinationSubtype)
{
    // Create a topology rule.
    ITopologyRule topologyRule = new TopologyRuleClass();
    topologyRule.TopologyRuleType = ruleType;
    topologyRule.Name = ruleName;
    topologyRule.OriginClassID = originClass.FeatureClassID;
    topologyRule.AllOriginSubtypes = false;
    topologyRule.OriginSubtype = originSubtype;
    topologyRule.DestinationClassID = destinationClass.FeatureClassID;
    topologyRule.AllDestinationSubtypes = false;
    topologyRule.DestinationSubtype = destinationSubtype;

    // 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.");
    }
}
[VB.NET]
Public Sub AddRuleToTopology(ByVal topology As ITopology, ByVal ruleType As esriTopologyRuleType, ByVal ruleName As String, ByVal originClass As IFeatureClass, ByVal originSubtype As Integer, ByVal destinationClass As IFeatureClass, ByVal destinationSubtype As Integer)
    
    ' Create a topology rule.
    Dim topologyRule As ITopologyRule = New TopologyRuleClass()
    topologyRule.TopologyRuleType = ruleType
    topologyRule.Name = ruleName
    topologyRule.OriginClassID = originClass.FeatureClassID
    topologyRule.AllOriginSubtypes = False
    topologyRule.OriginSubtype = originSubtype
    topologyRule.DestinationClassID = destinationClass.FeatureClassID
    topologyRule.AllDestinationSubtypes = False
    topologyRule.DestinationSubtype = destinationSubtype
    
    ' Cast the topology to the ITopologyRuleContainer interface and add the rule.
    Dim topologyRuleContainer As ITopologyRuleContainer = CType(topology, ITopologyRuleContainer)
    If topologyRuleContainer.CanAddRule(topologyRule) Then
        topologyRuleContainer.AddRule(topologyRule)
    Else
        Throw New ArgumentException("Could not add specified rule to the topology.")
    End If
    
End Sub

Validate the topology

Once the topology has been created with all the feature classes and rules, the topology can be validated. This is not required, but until doing so, the entire topology will be covered by a dirty area and the topological relationships of the features cannot be guaranteed.
The following code example shows one way of running a validation on a topology:
[C#]
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);
    }
}
[VB.NET]
Public Sub ValidateTopology(ByVal topology As ITopology, ByVal envelope As IEnvelope)
    
    ' Get the dirty area within the provided envelope.
    Dim locationPolygon As IPolygon = New PolygonClass()
    Dim segmentCollection As ISegmentCollection = CType(locationPolygon, ISegmentCollection)
    segmentCollection.SetRectangle(envelope)
    Dim polygon As IPolygon = topology.DirtyArea(locationPolygon)
    
    ' If a dirty area exists, validate the topology.
    If (Not polygon.IsEmpty) Then
        ' Define the area to validate and validate the topology.
        Dim areaToValidate As IEnvelope = polygon.Envelope
        Dim areaValidated As IEnvelope = topology.ValidateTopology(areaToValidate)
    End If
    
End Sub

Complete code example

The following code example shows the previous examples being used sequentially to create a topology:
[C#]
public void CreateTopology()
{
    // Open the workspace and the required datasets.
    Type factoryType = Type.GetTypeFromProgID(
        "esriDataSourcesGDB.FileGDBWorkspaceFactory");
    IWorkspaceFactory workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance
        (factoryType);
    IWorkspace workspace = workspaceFactory.OpenFromFile(@
        "C:\arcgis\ArcTutor\BuildingaGeodatabase\Montgomery.gdb", 0);
    IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspace;
    IFeatureDataset featureDataset = featureWorkspace.OpenFeatureDataset("Landbase");
    IFeatureClass blocksFC = featureWorkspace.OpenFeatureClass("Blocks");
    IFeatureClass parcelsFC = featureWorkspace.OpenFeatureClass("Parcels");

    // Attempt to acquire an exclusive schema lock on the feature dataset.
    ISchemaLock schemaLock = (ISchemaLock)featureDataset;
    try
    {
        schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock);

        // Create the topology.
        ITopologyContainer2 topologyContainer = (ITopologyContainer2)featureDataset;
        ITopology topology = topologyContainer.CreateTopology("Landbase_Topology",
            topologyContainer.DefaultClusterTolerance,  - 1, "");

        // Add feature classes and rules to the topology.
        topology.AddClass(blocksFC, 5, 1, 1, false);
        topology.AddClass(parcelsFC, 5, 1, 1, false);
        AddRuleToTopology(topology, esriTopologyRuleType.esriTRTAreaNoOverlap, 
            "No Block Overlap", blocksFC);
        AddRuleToTopology(topology,
            esriTopologyRuleType.esriTRTAreaCoveredByAreaClass, 
            "ResParcels Covered by ResBlocks", parcelsFC, 1, blocksFC, 1);

        // Get an envelope with the topology's extents and validate the topology.
        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);
    }
}
[VB.NET]
Public Sub CreateTopology()
    
    ' Open the workspace and the required datasets.
    Dim factoryType As Type = Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory")
    Dim workspaceFactory As IWorkspaceFactory = (IWorkspaceFactory)Activator.CreateInstance(factoryType)
    Dim workspace As IWorkspace = workspaceFactory.OpenFromFile("C:\arcgis\ArcTutor\BuildingaGeodatabase\Montgomery.gdb", 0)
    Dim featureWorkspace As IFeatureWorkspace = CType(workspace, IFeatureWorkspace)
    Dim featureDataset As IFeatureDataset = featureWorkspace.OpenFeatureDataset("Landbase")
    Dim blocksFC As IFeatureClass = featureWorkspace.OpenFeatureClass("Blocks")
    Dim parcelsFC As IFeatureClass = featureWorkspace.OpenFeatureClass("Parcels")
    
    ' Attempt to acquire an exclusive schema lock on the feature dataset.
    Dim schemaLock As ISchemaLock = CType(featureDataset, ISchemaLock)
    
    Try
    
    schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock)
    
    ' Create the topology.
    Dim topologyContainer As ITopologyContainer2 = CType(featureDataset, ITopologyContainer2)
    Dim topology As ITopology = topologyContainer.CreateTopology("Landbase_Topology", topologyContainer.DefaultClusterTolerance, -1, "")
    
    ' Add feature classes and rules to the topology.
    topology.AddClass(blocksFC, 5, 1, 1, False)
    topology.AddClass(parcelsFC, 5, 1, 1, False)
    AddRuleToTopology(topology, esriTopologyRuleType.esriTRTAreaNoOverlap, "No Block Overlap", blocksFC)
    AddRuleToTopology(topology, esriTopologyRuleType.esriTRTAreaCoveredByAreaClass, "ResParcels Covered by ResBlocks", parcelsFC, 1, blocksFC, 1)
    
    ' Get an envelope with the topology's extents and validate the topology.
    Dim geoDataset As IGeoDataset = CType(topology, IGeoDataset)
    Dim envelope As IEnvelope = geoDataset.Extent
    ValidateTopology(topology, envelope)
    
    Catch comExc As COMException
    
    Throw New Exception(String.Format("Error creating topology: {0} Message: {1}", comExc.ErrorCode, comExc.Message), comExc)
    
    Finally
    
    schemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock)
    
    End Try
    
End Sub


See Also:

Working with topologically related features
Checking for topology error features in a geodatabase topology
Listening to the OnValidate event for a geodatabase topology




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 for Desktop Standard ArcGIS for Desktop Standard
ArcGIS for Desktop Advanced ArcGIS for Desktop Advanced
Engine Developer Kit Engine: Geodatabase Update