sanjayrana

Create Network Dataset from a Shapefile using C#

Discussion created by sanjayrana on Mar 11, 2013
Hi Everyone,

I am trying to create a very simple network dataset from a simple polyline shapefile. I can do this easily using ArcCatalog.
ArcCatalog shows the conversion settings in a summary as following:

Name: Street_sim_ND
Type: Shapefile-Based Network Dataset

Sources:
Edge Sources:
Street_sim

Connectivity:
Group 1:
Edge Connectivity:
Street_sim (End Point)

Elevation Model: None

Attributes:
Length:
Usage Type: Cost
Data Type: Double
Units Type: Feet
Use by Default: True
Source Attribute Evaluators:
Street_sim (From-To): Field
Language: VBScript
Expression: [Shape]
Street_sim (To-From): Field
Language: VBScript
Expression: [Shape]
Default Attribute Evaluators:
Default Edges: Constant = 0
Default Junctions: Constant = 0

Directions:
Directions Ready: No
-Length Attribute Required


However, my attempts to do this programmatically using C# have run into problem. I get a COMException error. Here's my code. It crashed out at the field evaluator bit of the code, highlighted in red bold. Note that I read in the shapefile name as an argument to the method that runs the code below:

            string shpName = shapefilename with full path;
      
            // Create a new empty data element for a buildable network dataset.
            IDENetworkDataset2 deNetworkDataset = new DENetworkDatasetClass();
            deNetworkDataset.Buildable = true;            

            // Open the shapefile and cast to the IGeoDataset interface.
            IWorkspaceFactory workspaceFactory = new ShapefileWorkspaceFactoryClass();           
          
            //IWorkspace workspace = workspaceFactory.OpenFromFile(@"C:\Program Files\ArcGIS\DeveloperKit\SamplesNET\data\CreateNetworkDataset",0);
            IWorkspace workspace = workspaceFactory.OpenFromFile(@System.IO.Path.GetDirectoryName(shpName), 0);
            IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspace;
            IFeatureClass featureClass = featureWorkspace.OpenFeatureClass(@System.IO.Path.GetFileNameWithoutExtension(shpName));
            IGeoDataset geoDataset = (IGeoDataset)featureClass;
           
            // Copy the shapefile's extent and spatial reference to the network dataset data element.
            IDEGeoDataset deGeoDataset = (IDEGeoDataset)deNetworkDataset;
            deGeoDataset.Extent = geoDataset.Extent;
            deGeoDataset.SpatialReference = geoDataset.SpatialReference;

            // Name - Specify the name of the network dataset //
            IDataElement dataElement = (IDataElement)deNetworkDataset;
            dataElement.Name = "Streets_ND";

            // Elevation Model - Specify elevation model of the network //
            deNetworkDataset.ElevationModel = esriNetworkElevationModel.esriNEMNone;          
           
            // Specify the network dataset's global turn policy
            //deNetworkDataset.SupportsTurns = false;                                   

            // Source and Connectivity//
            // Create a new EdgeFeatureSource object and point it to the Streets shapefile.
            IEdgeFeatureSource streetsEdgeFeatureSource = new EdgeFeatureSourceClass();
            INetworkSource streetsNetworkSource = (INetworkSource)streetsEdgeFeatureSource;           
            streetsNetworkSource.Name = System.IO.Path.GetFileNameWithoutExtension(shpName);
            streetsNetworkSource.ElementType = esriNetworkElementType.esriNETEdge;

            // Set the connectivity settings for the edge feature source.
            streetsEdgeFeatureSource.UsesSubtypes = false;
            streetsEdgeFeatureSource.ClassConnectivityGroup = 1;
            streetsEdgeFeatureSource.ClassConnectivityPolicy = esriNetworkEdgeConnectivityPolicy.esriNECPEndVertex;

            // Add the EdgeFeatureSource object to the data element as a source in the network dataset.
            IArray sourceArray = new ArrayClass();
            sourceArray.Add(streetsEdgeFeatureSource);
            deNetworkDataset.Sources = sourceArray;

            // Attributes
            IArray attributeArray = new ArrayClass();
            IEvaluatedNetworkAttribute lengthEvaluatedNetworkAttribute = new  EvaluatedNetworkAttributeClass();

            INetworkAttribute2 lengthNetworkAttribute2 = (INetworkAttribute2)lengthEvaluatedNetworkAttribute;
            lengthNetworkAttribute2.Name = "Length";
            lengthNetworkAttribute2.UsageType = esriNetworkAttributeUsageType.esriNAUTCost;
            lengthNetworkAttribute2.DataType = esriNetworkAttributeDataType.esriNADTDouble;
            lengthNetworkAttribute2.Units = esriNetworkAttributeUnits.esriNAUFeet;
            lengthNetworkAttribute2.UseByDefault = true;

            // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
            INetworkFieldEvaluator lengthFTNetworkFieldEvaluator = new NetworkFieldEvaluatorClass();
            lengthFTNetworkFieldEvaluator.SetExpression("[Shape]", "");
            INetworkEvaluator lengthFTNetworkEvaluator = (INetworkEvaluator)lengthFTNetworkFieldEvaluator;
            lengthEvaluatedNetworkAttribute.set_Evaluator(streetsNetworkSource, esriNetworkEdgeDirection.esriNEDNone, lengthFTNetworkEvaluator);

            INetworkFieldEvaluator lengthTFNetworkFieldEvaluator = new NetworkFieldEvaluatorClass();
            lengthTFNetworkFieldEvaluator.SetExpression("[Shape]", "");
            INetworkEvaluator lengthTFNetworkEvaluator = (INetworkEvaluator)lengthTFNetworkFieldEvaluator;
            lengthEvaluatedNetworkAttribute.set_Evaluator(streetsNetworkSource, esriNetworkEdgeDirection.esriNEDNone, lengthTFNetworkEvaluator);

            INetworkConstantEvaluator lengthNetworkConstantEvaluator = new NetworkConstantEvaluatorClass();
            lengthNetworkConstantEvaluator.ConstantValue = 0;
            INetworkEvaluator lengthConstantNetworkEvaluator = (INetworkEvaluator) lengthNetworkConstantEvaluator;
            lengthEvaluatedNetworkAttribute.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, lengthConstantNetworkEvaluator);
            lengthEvaluatedNetworkAttribute.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, lengthConstantNetworkEvaluator);           

            // Add the attribute to the array.
            attributeArray.Add(lengthEvaluatedNetworkAttribute);
            deNetworkDataset.Attributes = attributeArray;

            // Create a new UID that references the NetworkDatasetWorkspaceExtension.
            UID ndWorkspaceExtensionUID = new UIDClass();
            ndWorkspaceExtensionUID.Value = "esriGeoDatabase.NetworkDatasetWorkspaceExtension";

            // Get the workspace extension and create the network dataset based on the data element.
            IWorkspaceExtensionManager workspaceExtensionManager = (IWorkspaceExtensionManager)workspace;
            IWorkspaceExtension workspaceExtension = workspaceExtensionManager.FindExtension(ndWorkspaceExtensionUID);
            IDatasetContainer2 datasetContainer2 = (IDatasetContainer2)workspaceExtension;
            IDEDataset deDataset = (IDEDataset)deNetworkDataset;
            INetworkDataset networkDataset = (INetworkDataset) datasetContainer2.CreateDataset(deDataset);

            // Once the network dataset is created, build it.
            INetworkBuild networkBuild = (INetworkBuild)networkDataset;
            networkBuild.BuildNetwork(geoDataset.Extent);


I have basically (thoughtlessly!) recycled ESRI's sample code for something similar but obviously unable to do it properly.
Any suggestions will be most appreciated.

Thanks,
Sanj.

Outcomes