How to create a topology in the geodatabase


This document was published with and applies to ArcGIS 9.3.
A 10 version also exists. A 9.2 version also exists.
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.

Prior to 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 article shows a common workflow for creating topologies within the geodatabase.

Development licensing Deployment licensing
ArcEditor ArcEditor
ArcInfo ArcInfo
Engine Developer Kit Engine Runtime: Geodatabase Update

To use the code in this article, the following namespaces must be referenced via the using (C#) or Imports (VB.NET) statements. It is also necessary to add the corresponding references to the project in order to gain access to these APIs.

In this topic


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 the article How to access the topology graph.

When new features are created, edited, or deleted, the topology is responsible for creating or modifying a dirty area that will encompass 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 screen shot 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, the CreateTopology method should be used. If the feature classes are z–aware, CreateTopologyEx method should be used as it allows the setting of a z–cluster tolerance, in addition to the x,y–cluster tolerance.
 
Careful consideration should be given 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 may 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, the ClusterTolerance parameter should be set 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 may 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 will prevent 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 of the left side of the red feature are coincident with the right edge of the blue feature. 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. See the following:
 
 
When modeling a surface, datasets can be collected with different x,y and z–accuracies. In this case, it may 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 of the left side of the red feature are coincident with vertices on the right edge of the blue feature. 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. See the following:
 
 
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, the default value of –1 should be used.
 
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 for an ArcSDE instance 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, refer to the Desktop documentation on "An overview of configuration keywords and how they are used".
 
Prior to creating a topology, an exclusive schema lock should be obtained for the target feature dataset.  For more information on obtaining an exclusive lock, see the article How to use schema locks with the geodatabase, or the complete code example at the end of this article.
 
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 new 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 new 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 in either 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 sample 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 mentioned previously, 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 new 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 new 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 new 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 new 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 new topology:

[C#]
public void CreateTopology()
{
  // Open the workspace and the required datasets.
  IWorkspaceFactory workspaceFactory = new FileGDBWorkspaceFactoryClass();
  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 workspaceFactory As IWorkspaceFactory = New FileGDBWorkspaceFactoryClass()
    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:

How to access the topology graph
How to check for topology error features in a geodatabase topology
How to listen to the OnValidate event for a geodatabase topology