About creating geometric networks within a geodatabase
The first step in programmatically creating a geometric network is instantiating a NetworkLoader object. The INetworkLoader2 interface (which inherits the members of INetworkLoader) can be used to set its properties. See the following code example:
[C#]
INetworkLoader2 networkLoader2 = new NetworkLoaderClass();
[VB.NET]
Dim networkLoader2 As INetworkLoader2 = New NetworkLoaderClass()
Network name
The NetworkName property is required when creating a geometric network. The name of the geometric network (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 the feature dataset being used only contains a single geometric network, it might be convenient to name the geometric network based on the name of the feature dataset. See the following code example:
[C#]
networkLoader2.NetworkName = "Water_Net";
[VB.NET]
networkLoader2.NetworkName = "Water_Net"
Network type
A geometric network can be one of two types—utility or street. The majority of the functionality in geometric networks has been implemented for utility networks. Network datasets are tailored for use with street networks. See the following code example:
[C#]
networkLoader2.NetworkType = esriNetworkType.esriNTUtilityNetwork;
[VB.NET]
networkLoader2.NetworkType = esriNetworkType.esriNTUtilityNetwork
Feature dataset name
Geometric networks can only be created within a feature dataset. The NetworkLoader needs a reference to a FeatureDatasetName object for the feature dataset that contains the geometric network. The featureDatasetName variable in the following code example is a reference to an instance of the FeatureDatasetName class:
[C#]
networkLoader2.FeatureDatasetName = (IDatasetName)featureDatasetName;
[VB.NET]
networkLoader2.FeatureDatasetName = CType(featureDatasetName, IDatasetName)
Adding feature classes
A geometric network is built from feature classes. These feature classes must be contained within the feature dataset specified by the INetworkLoader.FeatureDatasetName property. There are some restrictions on the types of feature classes that can participate in a geometric network. Feature classes must be lines or points, cannot already be participating in a geometric network, and in the case of SDE, must not be registered as versioned. Before adding a feature class, check for these violations and any others by calling the INetworkLoader2.CanUseFeatureClass method. See the following code example:
[C#]
// Add the two classes to the network.
if (networkLoader2.CanUseFeatureClass("Distribmains") ==
esriNetworkLoaderFeatureClassCheck.esriNLFCCValid)
{
networkLoader2.AddFeatureClass("Distribmains", esriFeatureType.esriFTComplexEdge,
null, false);
}
if (networkLoader2.CanUseFeatureClass("Tanks") ==
esriNetworkLoaderFeatureClassCheck.esriNLFCCValid)
{
networkLoader2.AddFeatureClass("Tanks", esriFeatureType.esriFTSimpleJunction,
null, false);
}
[VB.NET]
If networkLoader2.CanUseFeatureClass("Distribmains") = esriNetworkLoaderFeatureClassCheck.esriNLFCCValid Then
networkLoader2.AddFeatureClass("Distribmains", esriFeatureType.esriFTComplexEdge, Nothing, False)
End If
If networkLoader2.CanUseFeatureClass("Tanks") = esriNetworkLoaderFeatureClassCheck.esriNLFCCValid Then
networkLoader2.AddFeatureClass("Tanks", esriFeatureType.esriFTSimpleJunction, Nothing, False)
End If
Enabled or disabled field
Every feature class in a network must have a field that determines whether a feature is enabled or disabled. Enabled and disabled features affect how the flow and trace results are determined. Use the default name for the enabled and disabled field. If INetworkLoader.PutEnabledDisabledFieldName is not called for a feature class, the network loader uses the default name for the enabled and disabled field. See the following illustration:
The default name for the enabled and disabled field can be obtained from the INetworkLoaderProps.DefaultEnabledField property. If an existing field is specified as the enabled and disabled field, verify that this field is of the correct type and domain using the INetworkLoader2.CheckEnabledDisabledField method. The INetworkLoader2.PreserveEnabledValues property provides the option of resetting all values in the existing field to true or preserving the existing values. If the specified field does not exist, the network loader automatically adds it to the feature class when it builds the network, populating all values in this field with the value of true to indicate that the features are enabled.
The following code example demonstrates using the default enabled or disabled field name, and checking the field before calling PutEnabledDisabledFieldName (see the note that follows the code). The following code example also sets the PreserveEnabledValues property to true:
[C#]
INetworkLoaderProps networkLoaderProps = (INetworkLoaderProps)networkLoader2;
String defaultEnabledFieldName = networkLoaderProps.DefaultEnabledField;
esriNetworkLoaderFieldCheck enabledFieldCheck =
networkLoader2.CheckEnabledDisabledField("Tanks", defaultEnabledFieldName);
switch (enabledFieldCheck)
{
case esriNetworkLoaderFieldCheck.esriNLFCValid:
case esriNetworkLoaderFieldCheck.esriNLFCNotFound:
networkLoader2.PutEnabledDisabledFieldName("Tanks", defaultEnabledFieldName);
break;
default:
Console.WriteLine(
"The field {0} could not be used as an enabled/disabled field.",
defaultEnabledFieldName);
break;
}
networkLoader2.PreserveEnabledValues = true;
[VB.NET]
Dim networkLoaderProps As INetworkLoaderProps = CType(networkLoader2, INetworkLoaderProps)
Dim defaultEnabledFieldName As String = networkLoaderProps.DefaultEnabledField
Dim enabledFieldCheck As esriNetworkLoaderFieldCheck = networkLoader2.CheckEnabledDisabledField("Tanks", defaultEnabledFieldName)
Select Case enabledFieldCheck
Case esriNetworkLoaderFieldCheck.esriNLFCValid
Case esriNetworkLoaderFieldCheck.esriNLFCNotFound
networkLoader2.PutEnabledDisabledFieldName("Tanks", defaultEnabledFieldName)
Case Else
Console.WriteLine("The field {0} could not be used as an enabled/disabled field.", defaultEnabledFieldName)
End Select
networkLoader2.PreserveEnabledValues = True
In reality, this code (with the exception of the call to PreserveEnabledValues) is not necessary, since in the absence of calls to PutEnabledDisabledFieldName for a feature class, the network loader assumes that the default enabled or disabled field should be used for that feature class. The preceding code example is provided for illustrative purposes only.
Ancillary roles
Geometric networks are used to model systems with directed flow where the direction of movement through the network is well defined. Flow direction in the geometric network is calculated using a series of sources and sinks. To participate as a source or sink, a feature class must be specified as having an ancillary role. Feature classes specified as having an ancillary role indicate that their features can act as sources or sinks to determine flow within the network. Only point feature classes can be specified as having an ancillary role; however, multiple point feature classes in a network can have ancillary roles. See the following illustration:
Use the INetworkLoader.PutAncillaryRole method to specify a feature class as participating as a source or sink. The field name passed in as the ancillaryRoleFieldName parameter should contain the ancillary role attribute for the feature class. Use the default name for the ancillary role field. The default name for the ancillary role field can be obtained from the INetworkLoaderProps.DefaultAncillaryRoleField property. If an existing field is specified as the ancillary role field, verify that this field is of the correct type and domain using the INetworkLoader2.CheckAncillaryRoleField method. If the specified field does not exist, the network loader automatically adds it to the feature class when it builds the network, populating all values in this field with 0.
The following code example demonstrates using the ancillary role field name and checking the ancillary role field before calling PutAncillaryRole:
[C#]
String defaultAncillaryRoleFieldName = networkLoaderProps.DefaultAncillaryRoleField;
esriNetworkLoaderFieldCheck ancillaryRoleFieldCheck =
networkLoader2.CheckAncillaryRoleField("Tanks", defaultAncillaryRoleFieldName);
switch (ancillaryRoleFieldCheck)
{
case esriNetworkLoaderFieldCheck.esriNLFCValid:
case esriNetworkLoaderFieldCheck.esriNLFCNotFound:
networkLoader2.PutAncillaryRole("Tanks",
esriNetworkClassAncillaryRole.esriNCARSourceSink,
defaultAncillaryRoleFieldName);
break;
default:
Console.WriteLine(
"The field {0} could not be used as an ancillary role field.",
defaultAncillaryRoleFieldName);
break;
}
[VB.NET]
Dim defaultAncillaryRoleFieldName As String = networkLoaderProps.DefaultAncillaryRoleField
Dim ancillaryRoleFieldCheck As esriNetworkLoaderFieldCheck = networkLoader2.CheckAncillaryRoleField("Tanks", defaultAncillaryRoleFieldName)
Select Case ancillaryRoleFieldCheck
Case esriNetworkLoaderFieldCheck.esriNLFCValid
Case esriNetworkLoaderFieldCheck.esriNLFCNotFound
networkLoader2.PutAncillaryRole("Tanks", esriNetworkClassAncillaryRole.esriNCARSourceSink, defaultAncillaryRoleFieldName)
Case Else
Console.WriteLine("The field {0} could not be used as an ancillary role field.", defaultAncillaryRoleFieldName)
End Select
Configuration keyword
If the geometric network is created in an ArcSDE geodatabase, a configuration keyword can be specified for building the network. A configuration keyword is used to specify storage and location parameters for optimal space and disk location efficiency. The configuration keyword is provided by the database administrator. The variable workspace in the following code example is of type ESRI.ArcGIS.Geodatabase.IWorkspace:
[C#]
if (workspace.Type == esriWorkspaceType.esriRemoteDatabaseWorkspace)
{
networkLoader2.ConfigurationKeyword = "Network_Defaults";
}
[VB.NET]
If workspace.Type = esriWorkspaceType.esriRemoteDatabaseWorkspace Then
networkLoader2.ConfigurationKeyword = "Network_Defaults"
End If
Snapping
When a geometric network is built, feature connectivity is determined by the spatial relationship of the features. If features are geometrically coincident, they will be connected during network building.
It might be known, for example, where the line features of the network are located but not where the point features are located. In this case, specify that the point features should be snapped. The line features stay in the same position but the coordinates of the points change to match the line features. If more than one feature class is specified to be snapped, the mean coordinate is computed. Feature classes participate in snapping when they are added to the network loader using the INetworkLoader.AddFeatureClass method.
Snap tolerance
The snap tolerance controls the search distance used for establishing connectivity during the network building process. The snap tolerance is specified in map units.
The following code example shows how to specify the snap tolerance to be the minimum or default tolerance. Usually, the minimum snapping tolerance is used to ensure feature connectivity within a geometric network.
[C#]
networkLoader2.SnapTolerance = networkLoader2.MinSnapTolerance;
[VB.NET]
networkLoader2.SnapTolerance = networkLoader2.MinSnapTolerance
Adding weights
Weights can also be added to a network. A weight is the cost of moving along a feature in a network. In a water utility network, this can be the diameter of a pipe, which can have an effect on the amount of flow through the pipe. To get all the weights on a network, use the INetSchema interface. The following code example shows how to add a new integer weight:
[C#]
networkLoader2.AddWeight("MainWeight", esriWeightType.esriWTDouble, 0);
// For weights of type esriWTBitGate, the BitGateSize parameter should be set:
networkLoader2.AddWeight("WTBitGateEx", esriWeightType.esriWTBitGate, 5);
[VB.NET]
networkLoader2.AddWeight("MainWeight", esriWeightType.esriWTDouble, 0)
' For weights of type esriWTBitGate, the BitGateSize parameter should be set:
networkLoader2.AddWeight("WTBitGateEx", esriWeightType.esriWTBitGate, 5)
After adding a weight to the network, indicate the feature classes and fields the weight will be associated with. By default, weights are not associated with feature classes. Use the INetworkLoader.AddWeightAssociation method to indicate the feature classes and fields the weight uses.
Adding weight associations
The weights specified for the network need to have values. These values are taken from the fields of the feature classes that participate in the network. Adding weight associations indicates to the network which fields belong to which weights. A weight can be associated with multiple feature classes but can only be associated with a single field in each feature class. See the following code example:
[C#]
networkLoader2.AddWeightAssociation("MainWeight", "Distribmains", "DIAMETER");
[VB.NET]
networkLoader2.AddWeightAssociation("MainWeight", "Distribmains", "DIAMETER")
These associations are dependent on the type of field and the type of weight created. For example, a weight of type esriWTDouble can only be associated with a field of type esriFieldTypeDouble. For weights of type esriWTBitGate, the field type can be either esriFieldTypeInteger or esriFieldTypeSmallInteger.
Building the network
After specifying all of the parameters for the network, calling the INetworkLoader.LoadNetwork method builds the network. See the following code example:
[C#]
networkLoader2.LoadNetwork();
[VB.NET]
networkLoader2.LoadNetwork()
After building the network
The feature classes participating in the geometric network can contain features with invalid geometry. The types of invalid geometries are detailed in the esriNetworkErrorType enumeration. If these types of features exist, they will be identified during the network creation process and recorded into the geometric network error table. The error table is created only when features with invalid geometries are found.
The following set of properties can be used to discover if any invalid geometries were found during network creation and to return the total number of invalid geometries or the total for each feature class.
The following code example returns the name of the error table, which will generally be the name of the geometric network with "_ERR" appended to the end:
[C#]
String errorTableName = networkLoader2.ErrorTableName;
[VB.NET]
Dim errorTableName As String = networkLoader2.ErrorTableName
The following code example returns the number of invalid features for the specified feature class:
[C#]
int numInvalidFeatures = networkLoader2.get_NumInvalidFeatures("Distribmains");
[VB.NET]
Dim numInvalidFeatures As Integer = networkLoader2.NumInvalidFeatures("Distribmains")
The following code example returns the number of invalid features for all feature classes in the geometric network:
[C#]
int totalNumInvalidFeatures = networkLoader2.TotalNumInvalidFeatures;
[VB.NET]
Dim totalNumInvalidFeatures As Integer = networkLoader2.TotalNumInvalidFeatures
Complete code example
The following are complete code examples of the previously shown code:
[C#]
public void CreateGeometricNetwork(IWorkspace workspace, IFeatureDatasetName
featureDatasetName)
{
// Create a network loader.
INetworkLoader2 networkLoader2 = new NetworkLoaderClass();
// Set the network name.
networkLoader2.NetworkName = "Water_Net";
// Set the network type.
networkLoader2.NetworkType = esriNetworkType.esriNTUtilityNetwork;
// Set the containing feature dataset.
networkLoader2.FeatureDatasetName = (IDatasetName)featureDatasetName;
// Add the two classes to the network.
if (networkLoader2.CanUseFeatureClass("Distribmains") ==
esriNetworkLoaderFeatureClassCheck.esriNLFCCValid)
{
networkLoader2.AddFeatureClass("Distribmains",
esriFeatureType.esriFTComplexEdge, null, false);
}
if (networkLoader2.CanUseFeatureClass("Tanks") ==
esriNetworkLoaderFeatureClassCheck.esriNLFCCValid)
{
networkLoader2.AddFeatureClass("Tanks", esriFeatureType.esriFTSimpleJunction,
null, false);
}
// Set the enabled field for the Distribmains class.
INetworkLoaderProps networkLoaderProps = (INetworkLoaderProps)networkLoader2;
String defaultEnabledFieldName = networkLoaderProps.DefaultEnabledField;
esriNetworkLoaderFieldCheck enabledFieldCheck =
networkLoader2.CheckEnabledDisabledField("Tanks", defaultEnabledFieldName);
switch (enabledFieldCheck)
{
case esriNetworkLoaderFieldCheck.esriNLFCValid:
case esriNetworkLoaderFieldCheck.esriNLFCNotFound:
networkLoader2.PutEnabledDisabledFieldName("Tanks",
defaultEnabledFieldName);
break;
default:
Console.WriteLine(
"The field {0} could not be used as an enabled/disabled field.",
defaultEnabledFieldName);
break;
}
networkLoader2.PreserveEnabledValues = true;
// Set the ancillary role field for the tanks class.
String defaultAncillaryRoleFieldName =
networkLoaderProps.DefaultAncillaryRoleField;
esriNetworkLoaderFieldCheck ancillaryRoleFieldCheck =
networkLoader2.CheckAncillaryRoleField("Tanks",
defaultAncillaryRoleFieldName);
switch (ancillaryRoleFieldCheck)
{
case esriNetworkLoaderFieldCheck.esriNLFCValid:
case esriNetworkLoaderFieldCheck.esriNLFCNotFound:
networkLoader2.PutAncillaryRole("Tanks",
esriNetworkClassAncillaryRole.esriNCARSourceSink,
defaultAncillaryRoleFieldName);
break;
default:
Console.WriteLine(
"The field {0} could not be used as an ancillary role field.",
defaultAncillaryRoleFieldName);
break;
}
// If the geodatabase is an SDE GDB, set the configuration keyword.
if (workspace.Type == esriWorkspaceType.esriRemoteDatabaseWorkspace)
{
networkLoader2.ConfigurationKeyword = "Network_Defaults";
}
// Set the snap tolerance for the network.
networkLoader2.SnapTolerance = networkLoader2.MinSnapTolerance;
// Add a weight with a double type to the network.
networkLoader2.AddWeight("MainWeight", esriWeightType.esriWTDouble, 0);
// For weights of type esriWTBitGate, the BitGateSize parameter should be set:
networkLoader2.AddWeight("WTBitGateEx", esriWeightType.esriWTBitGate, 5);
// Associate the MainWeight weight with the DIAMETER field of Distribmains.
networkLoader2.AddWeightAssociation("MainWeight", "Distribmains", "DIAMETER");
// Load the network.
networkLoader2.LoadNetwork();
// Get the name of the network's error table.
String errorTableName = networkLoader2.ErrorTableName;
// Display the number of invalid features in the Distribmains class.
int numInvalidFeatures = networkLoader2.get_NumInvalidFeatures("Distribmains");
Console.WriteLine("Distribmains contains {0} invalid features.",
numInvalidFeatures);
// Display the number of invalid features in the network.
int totalNumInvalidFeatures = networkLoader2.TotalNumInvalidFeatures;
Console.WriteLine("The network contains {0} invalid features.",
totalNumInvalidFeatures);
}
[VB.NET]
Public Sub CreateGeometricNetwork(ByVal workspace As IWorkspace, ByVal featureDatasetName As IFeatureDatasetName)
' Create a network loader.
Dim networkLoader2 As INetworkLoader2 = New NetworkLoaderClass()
' Set the network name.
networkLoader2.NetworkName = "Water_Net"
' Set the network type.
networkLoader2.NetworkType = esriNetworkType.esriNTUtilityNetwork
' Set the containing feature dataset.
networkLoader2.FeatureDatasetName = CType(featureDatasetName, IDatasetName)
' Add the two classes to the network.
If networkLoader2.CanUseFeatureClass("Distribmains") = esriNetworkLoaderFeatureClassCheck.esriNLFCCValid Then
networkLoader2.AddFeatureClass("Distribmains", esriFeatureType.esriFTComplexEdge, Nothing, False)
End If
If networkLoader2.CanUseFeatureClass("Tanks") = esriNetworkLoaderFeatureClassCheck.esriNLFCCValid Then
networkLoader2.AddFeatureClass("Tanks", esriFeatureType.esriFTSimpleJunction, Nothing, False)
End If
' Set the enabled field for the Distribmains class.
Dim networkLoaderProps As INetworkLoaderProps = CType(networkLoader2, INetworkLoaderProps)
Dim defaultEnabledFieldName As String = networkLoaderProps.DefaultEnabledField
Dim enabledFieldCheck As esriNetworkLoaderFieldCheck = networkLoader2.CheckEnabledDisabledField("Tanks", defaultEnabledFieldName)
Select Case enabledFieldCheck
Case esriNetworkLoaderFieldCheck.esriNLFCValid
Case esriNetworkLoaderFieldCheck.esriNLFCNotFound
networkLoader2.PutEnabledDisabledFieldName("Tanks", defaultEnabledFieldName)
Case Else
Console.WriteLine("The field {0} could not be used as an enabled/disabled field.", defaultEnabledFieldName)
End Select
networkLoader2.PreserveEnabledValues = True
' Set the ancillary role field for the tanks class.
Dim defaultAncillaryRoleFieldName As String = networkLoaderProps.DefaultAncillaryRoleField
Dim ancillaryRoleFieldCheck As esriNetworkLoaderFieldCheck = networkLoader2.CheckAncillaryRoleField("Tanks", defaultAncillaryRoleFieldName)
Select Case ancillaryRoleFieldCheck
Case esriNetworkLoaderFieldCheck.esriNLFCValid
Case esriNetworkLoaderFieldCheck.esriNLFCNotFound
networkLoader2.PutAncillaryRole("Tanks", esriNetworkClassAncillaryRole.esriNCARSourceSink, defaultAncillaryRoleFieldName)
Case Else
Console.WriteLine("The field {0} could not be used as an ancillary role field.", defaultAncillaryRoleFieldName)
End Select
' If the geodatabase is an SDE GDB, set the configuration keyword.
If workspace.Type = esriWorkspaceType.esriRemoteDatabaseWorkspace Then
networkLoader2.ConfigurationKeyword = "Network_Defaults"
End If
' Set the snap tolerance for the network.
networkLoader2.SnapTolerance = networkLoader2.MinSnapTolerance
' Add a weight with a double type to the network.
networkLoader2.AddWeight("MainWeight", esriWeightType.esriWTDouble, 0)
' For weights of type esriWTBitGate, the BitGateSize parameter should be set:
networkLoader2.AddWeight("WTBitGateEx", esriWeightType.esriWTBitGate, 5)
' Associate the MainWeight weight with the DIAMETER field of Distribmains.
networkLoader2.AddWeightAssociation("MainWeight", "Distribmains", "DIAMETER")
' Load the network.
networkLoader2.LoadNetwork()
' Get the name of the network's error table.
Dim errorTableName As String = networkLoader2.ErrorTableName
' Display the number of invalid features in the Distribmains class.
Dim numInvalidFeatures As Integer = networkLoader2.NumInvalidFeatures("Distribmains")
Console.WriteLine("Distribmains contains {0} invalid features.", numInvalidFeatures)
' Display the number of invalid features in the network.
Dim totalNumInvalidFeatures As Integer = networkLoader2.TotalNumInvalidFeatures
Console.WriteLine("The network contains {0} invalid features.", totalNumInvalidFeatures)
End Sub
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):
ESRI.ArcGIS.Geodatabase ESRI.ArcGIS.System (ESRI.ArcGIS.esriSystem)ESRI.ArcGIS.NetworkAnalysis
Development licensing | Deployment licensing |
---|---|
ArcGIS for Desktop Standard | ArcGIS for Desktop Standard |
ArcGIS for Desktop Advanced | ArcGIS for Desktop Advanced |
Engine Developer Kit | Engine |