Example #1
0
        /// <summary>Adds edge feature classes to the network dataset</summary>
        /// <remarks>
        /// - For each 'edge' element in the config file, adds a new EdgeFeatureSource to the NDS
        /// - A new feature class is extracted from *_OSM_LN using a filter specified in the config file
        /// </remarks>
        private void ExtractEdgeFeatureClasses()
        {
            IList <SourceFeatureClassInfo> edges = _xml.EdgeFeatureClasses().ToList();

            if ((edges == null) || (edges.Count == 0))
            {
                return;
            }

            ConvertRequiredTagsToAttributes(true);

            // Create the new feature class using the query filter from the config XML
            foreach (SourceFeatureClassInfo edge in edges)
            {
                string edgeClassName = GetFullClassName(edge.Name);
                SelectFeaturesToNewFeatureClass(_osmLinePath, _dsPath + "\\" + edgeClassName, edge.Query);

                INetworkSource edgeNetworkSource = new EdgeFeatureSourceClass();
                edgeNetworkSource.Name        = edgeClassName;
                edgeNetworkSource.ElementType = esriNetworkElementType.esriNETEdge;

                IEdgeFeatureSource edgeFeatureSource = (IEdgeFeatureSource)edgeNetworkSource;
                edgeFeatureSource.UsesSubtypes            = false;
                edgeFeatureSource.ClassConnectivityPolicy = (esriNetworkEdgeConnectivityPolicy)edge.ConnectPolicy;

                if (edge.StreetNameFields != null)
                {
                    // Create a StreetNameFields object and populate its settings for the Streets source.
                    IStreetNameFields streetNameFields = new StreetNameFieldsClass();
                    streetNameFields.Priority                 = 1;
                    streetNameFields.StreetNameFieldName      = edge.StreetNameFields.StreetName;
                    streetNameFields.PrefixDirectionFieldName = edge.StreetNameFields.DirectionPrefix;
                    streetNameFields.SuffixDirectionFieldName = edge.StreetNameFields.DirectionSuffix;
                    streetNameFields.PrefixTypeFieldName      = edge.StreetNameFields.TypePrefix;
                    streetNameFields.SuffixTypeFieldName      = edge.StreetNameFields.TypeSuffix;

                    INetworkSourceDirections sourceDirections = new NetworkSourceDirectionsClass();
                    IArray streetNameFieldsArray = new ArrayClass();
                    streetNameFieldsArray.Add(streetNameFields);
                    sourceDirections.StreetNameFields = streetNameFieldsArray;
                    ((INetworkSource)edgeFeatureSource).NetworkSourceDirections = sourceDirections;
                }

                _edgeSources.Add(edgeFeatureSource);
            }
        }
        /// <summary>Adds edge feature classes to the network dataset</summary>
        /// <remarks>
        /// - For each 'edge' element in the config file, adds a new EdgeFeatureSource to the NDS
        /// - A new feature class is extracted from *_OSM_LN using a filter specified in the config file
        /// </remarks>
        private void ExtractEdgeFeatureClasses()
        {
            IList<SourceFeatureClassInfo> edges = _xml.EdgeFeatureClasses().ToList();
            if ((edges == null) || (edges.Count == 0))
                return;

            ConvertRequiredTagsToAttributes(true);

            // Create the new feature class using the query filter from the config XML
            foreach (SourceFeatureClassInfo edge in edges)
            {
                string edgeClassName = GetFullClassName(edge.Name);
                SelectFeaturesToNewFeatureClass(_osmLinePath, _dsPath + "\\" + edgeClassName, edge.Query);

                INetworkSource edgeNetworkSource = new EdgeFeatureSourceClass();
                edgeNetworkSource.Name = edgeClassName;
                edgeNetworkSource.ElementType = esriNetworkElementType.esriNETEdge;

                IEdgeFeatureSource edgeFeatureSource = (IEdgeFeatureSource)edgeNetworkSource;
                edgeFeatureSource.UsesSubtypes = false;
                edgeFeatureSource.ClassConnectivityPolicy = (esriNetworkEdgeConnectivityPolicy)edge.ConnectPolicy;

                if (edge.StreetNameFields != null)
                {
                    // Create a StreetNameFields object and populate its settings for the Streets source.
                    IStreetNameFields streetNameFields = new StreetNameFieldsClass();
                    streetNameFields.Priority = 1;
                    streetNameFields.StreetNameFieldName = edge.StreetNameFields.StreetName;
                    streetNameFields.PrefixDirectionFieldName = edge.StreetNameFields.DirectionPrefix;
                    streetNameFields.SuffixDirectionFieldName = edge.StreetNameFields.DirectionSuffix;
                    streetNameFields.PrefixTypeFieldName = edge.StreetNameFields.TypePrefix;
                    streetNameFields.SuffixTypeFieldName = edge.StreetNameFields.TypeSuffix;

                    INetworkSourceDirections sourceDirections = new NetworkSourceDirectionsClass();
                    IArray streetNameFieldsArray = new ArrayClass();
                    streetNameFieldsArray.Add(streetNameFields);
                    sourceDirections.StreetNameFields = streetNameFieldsArray;
                    ((INetworkSource)edgeFeatureSource).NetworkSourceDirections = sourceDirections;
                }

                _edgeSources.Add(edgeFeatureSource);
            }
        }
        private void CreateAndBuildNetworkDataset(string outputFileGdbPath, double fgdbVersion, string fdsName, string ndsName,
                                                  bool createNetworkAttributesInMetric, bool createArcGISOnlineNetworkAttributes,
                                                  string timeZoneIDBaseFieldName, bool directedTimeZoneIDFields, string commonTimeZone,
                                                  bool usesHistoricalTraffic, ITrafficFeedLocation trafficFeedLocation, bool usesTransport)
        {
            // This code is modified from "How to create a network dataset" in the ArcObjects SDK.

            //
            // Create a network dataset data element
            //

            // Create an empty data element for a buildable network dataset.
            IDENetworkDataset3 deNetworkDataset = new DENetworkDatasetClass();
            deNetworkDataset.Buildable = true;

            // Open the feature dataset and cast to the IGeoDataset interface.
            Type factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory");
            var workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance(factoryType);
            IWorkspace workspace = workspaceFactory.OpenFromFile(outputFileGdbPath, 0);
            var featureWorkspace = (IFeatureWorkspace)workspace;
            IFeatureDataset featureDataset = featureWorkspace.OpenFeatureDataset(fdsName);
            var geoDataset = (IGeoDataset)featureDataset;

            // Copy the feature dataset's extent and spatial reference to the network dataset data element.
            var deGeoDataset = (IDEGeoDataset)deNetworkDataset;
            deGeoDataset.Extent = geoDataset.Extent;
            deGeoDataset.SpatialReference = geoDataset.SpatialReference;

            // Specify the name of the network dataset.
            var dataElement = (IDataElement)deNetworkDataset;
            dataElement.Name = ndsName;

            //
            // Add network sources
            //

            // Specify the network dataset's elevation model.
            deNetworkDataset.ElevationModel = esriNetworkElevationModel.esriNEMElevationFields;

            // Create an EdgeFeatureSource object and point it to the Streets feature class.
            INetworkSource edgeNetworkSource = new EdgeFeatureSourceClass();
            edgeNetworkSource.Name = StreetsFCName;
            edgeNetworkSource.ElementType = esriNetworkElementType.esriNETEdge;

            // Set the edge feature source's connectivity settings.
            var edgeFeatureSource = (IEdgeFeatureSource)edgeNetworkSource;
            edgeFeatureSource.UsesSubtypes = false;
            edgeFeatureSource.ClassConnectivityGroup = 1;
            edgeFeatureSource.ClassConnectivityPolicy = esriNetworkEdgeConnectivityPolicy.esriNECPEndVertex;
            edgeFeatureSource.FromElevationFieldName = "F_ZLEV";
            edgeFeatureSource.ToElevationFieldName = "T_ZLEV";

            //
            // Specify directions settings for the edge source
            //

            // Create a StreetNameFields object for the primary street names and populate its settings.
            IStreetNameFields2 streetNameFields = new StreetNameFieldsClass();
            streetNameFields.Priority = 1; // Priority 1 indicates the primary street name.
            streetNameFields.LanguageFieldName = "Language";
            streetNameFields.FullNameFieldName = "ST_NAME";
            streetNameFields.PrefixDirectionFieldName = "ST_NM_PREF";
            streetNameFields.PrefixTypeFieldName = "ST_TYP_BEF";
            streetNameFields.StreetNameFieldName = "ST_NM_BASE";
            streetNameFields.SuffixTypeFieldName = "ST_TYP_AFT";
            streetNameFields.SuffixDirectionFieldName = "ST_NM_SUFF";
            streetNameFields.HighwayDirectionFieldName = "DIRONSIGN";

            // Create a StreetNameFields object for the alternate street names and populate its settings.
            IStreetNameFields2 altStreetNameFields = new StreetNameFieldsClass();
            altStreetNameFields.Priority = 2; // Priority 2 indicates the alternate street name.
            altStreetNameFields.LanguageFieldName = "Language_Alt";
            altStreetNameFields.FullNameFieldName = "ST_NAME_Alt";
            altStreetNameFields.PrefixDirectionFieldName = "ST_NM_PREF_Alt";
            altStreetNameFields.PrefixTypeFieldName = "ST_TYP_BEF_Alt";
            altStreetNameFields.StreetNameFieldName = "ST_NM_BASE_Alt";
            altStreetNameFields.SuffixTypeFieldName = "ST_TYP_AFT_Alt";
            altStreetNameFields.SuffixDirectionFieldName = "ST_NM_SUFF_Alt";
            altStreetNameFields.HighwayDirectionFieldName = "DIRONSIGN_Alt";

            // Add the StreetNameFields objects to a new NetworkSourceDirections object,
            // then add it to the EdgeFeatureSource created earlier.
            INetworkSourceDirections nsDirections = new NetworkSourceDirectionsClass();
            IArray nsdArray = new ArrayClass();
            nsdArray.Add(streetNameFields as IStreetNameFields);
            nsdArray.Add(altStreetNameFields as IStreetNameFields);
            nsDirections.StreetNameFields = nsdArray;
            edgeNetworkSource.NetworkSourceDirections = nsDirections;

            //
            // Specify the turn source
            //

            deNetworkDataset.SupportsTurns = true;

            // Create a TurnFeatureSource object and point it to the RestrictedTurns feature class.
            INetworkSource turnNetworkSource = new TurnFeatureSourceClass();
            turnNetworkSource.Name = TurnFCName;
            turnNetworkSource.ElementType = esriNetworkElementType.esriNETTurn;

            //
            // Add all sources to the data element
            //

            IArray sourceArray = new ArrayClass();
            sourceArray.Add(edgeNetworkSource);
            sourceArray.Add(turnNetworkSource);

            deNetworkDataset.Sources = sourceArray;

            //
            // Add the traffic data tables (if applicable)
            //

            if (usesHistoricalTraffic || trafficFeedLocation != null)
            {
                // Create a new TrafficData object and populate its historical and live traffic settings.
                var traffData = new TrafficDataClass() as ITrafficData2;
                traffData.LengthAttributeName = createNetworkAttributesInMetric ? "Kilometers" : "Miles";

                // Populate the speed profile table settings.
                var histTraff = traffData as IHistoricalTrafficData2;
                histTraff.ProfilesTableName = ProfilesTableName;
                if (usesHistoricalTraffic)
                {
                    if (fgdbVersion == 10.0)
                    {
                        histTraff.FirstTimeSliceFieldName = "TimeFactor_0000";
                        histTraff.LastTimeSliceFieldName = "TimeFactor_2345";
                    }
                    else
                    {
                        histTraff.FirstTimeSliceFieldName = "SpeedFactor_0000";
                        histTraff.LastTimeSliceFieldName = "SpeedFactor_2345";
                    }
                }
                else
                {
                    histTraff.FirstTimeSliceFieldName = "SpeedFactor_AM";
                    histTraff.LastTimeSliceFieldName = "SpeedFactor_PM";
                }
                histTraff.TimeSliceDurationInMinutes = usesHistoricalTraffic ? 15 : 720;
                histTraff.FirstTimeSliceStartTime = new DateTime(1, 1, 1, 0, 0, 0); // 12 AM
                // Note: the last time slice finish time is implied from the above settings and need not be specified.

                // Populate the street-speed profile join table settings.
                histTraff.JoinTableName = HistTrafficJoinTableName;
                if (usesHistoricalTraffic)
                {
                    if (fgdbVersion == 10.0)
                    {
                        histTraff.JoinTableBaseTravelTimeFieldName = "BaseMinutes";
                        histTraff.JoinTableBaseTravelTimeUnits = esriNetworkAttributeUnits.esriNAUMinutes;
                    }
                    else
                    {
                        histTraff.JoinTableBaseSpeedFieldName = "BaseSpeed";
                        histTraff.JoinTableBaseSpeedUnits = esriNetworkAttributeUnits.esriNAUKilometersPerHour;
                    }
                }
                else
                {
                    histTraff.JoinTableBaseSpeedFieldName = "KPH";
                    histTraff.JoinTableBaseSpeedUnits = esriNetworkAttributeUnits.esriNAUKilometersPerHour;
                }
                IStringArray fieldNames = new NamesClass();
                fieldNames.Add("U");
                fieldNames.Add("M");
                fieldNames.Add("T");
                fieldNames.Add("W");
                fieldNames.Add("R");
                fieldNames.Add("F");
                fieldNames.Add("S");
                histTraff.JoinTableProfileIDFieldNames = fieldNames;

                // For creating 10.1 and later, populate the dynamic traffic settings.
                if (fgdbVersion >= 10.1 && trafficFeedLocation != null)
                {
                    var dynTraff = traffData as IDynamicTrafficData;
                    dynTraff.DynamicTrafficTableName = TMCJoinTableName;
                    dynTraff.DynamicTrafficTMCFieldName = "TMC";
                    dynTraff.TrafficFeedLocation = trafficFeedLocation;
                }

                // Add the traffic data to the network dataset data element.
                deNetworkDataset.TrafficData = (ITrafficData)traffData;
            }

            //
            // Add network attributes
            //

            IArray attributeArray = new ArrayClass();

            // Initialize variables reused when creating attributes:
            IEvaluatedNetworkAttribute evalNetAttr;
            INetworkAttribute2 netAttr2;
            INetworkFieldEvaluator netFieldEval;
            INetworkConstantEvaluator netConstEval;

            if (!createArcGISOnlineNetworkAttributes)
            {
                //
                // Oneway network attribute
                //

                // Create an EvaluatedNetworkAttribute object and populate its settings.
                evalNetAttr = CreateRestrAttrNoEvals("Oneway", fgdbVersion, -1.0, true, "", "");

                // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("restricted", "restricted = False\n\r" +
                                           "Select Case UCase([DIR_TRAVEL])\n\r" +
                                           "  Case \"N\", \"TF\", \"T\": restricted = True\n\r" +
                                           "End Select");
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("restricted", "restricted = False\n\r" +
                                           "Select Case UCase([DIR_TRAVEL])\n\r" +
                                           "  Case \"N\", \"FT\", \"F\": restricted = True\n\r" +
                                           "End Select");
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = false; // False = traversable.
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = false; // False = traversable.
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = false; // False = traversable.
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

                // Add the attribute to the array.
                attributeArray.Add(evalNetAttr);
            }

            //
            // Minutes network attribute
            //

            // Create an EvaluatedNetworkAttribute object and populate its settings.
            evalNetAttr = new EvaluatedNetworkAttributeClass();
            netAttr2 = (INetworkAttribute2)evalNetAttr;
            netAttr2.Name = "Minutes";
            netAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTCost;
            netAttr2.DataType = esriNetworkAttributeDataType.esriNADTDouble;
            netAttr2.Units = esriNetworkAttributeUnits.esriNAUMinutes;
            netAttr2.UseByDefault = createArcGISOnlineNetworkAttributes ? false : !(usesHistoricalTraffic || (trafficFeedLocation != null));

            if (usesHistoricalTraffic)
            {
                // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("[FT_Minutes]", "");
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("[TF_Minutes]", "");
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);
            }
            else
            {
                // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("[Minutes]", "");
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("[Minutes]", "");
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);
            }

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

            // Add the attribute to the array.
            attributeArray.Add(evalNetAttr);

            //
            // Length network attribute(s)
            //

            if (createArcGISOnlineNetworkAttributes || createNetworkAttributesInMetric)
            {
                evalNetAttr = CreateLengthNetworkAttribute("Kilometers", esriNetworkAttributeUnits.esriNAUKilometers,
                                                           "[Meters] / 1000", edgeNetworkSource);
                // Add the attribute to the array.
                attributeArray.Add(evalNetAttr);
            }
            if (createArcGISOnlineNetworkAttributes || !createNetworkAttributesInMetric)
            {
                evalNetAttr = CreateLengthNetworkAttribute("Miles", esriNetworkAttributeUnits.esriNAUMiles,
                                                           "[Meters] / 1609.344", edgeNetworkSource);
                // Add the attribute to the array.
                attributeArray.Add(evalNetAttr);
            }

            //
            // RoadClass network attribute
            //

            // Create an EvaluatedNetworkAttribute object and populate its settings.
            evalNetAttr = new EvaluatedNetworkAttributeClass();
            netAttr2 = (INetworkAttribute2)evalNetAttr;
            netAttr2.Name = "RoadClass";
            netAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTDescriptor;
            netAttr2.DataType = esriNetworkAttributeDataType.esriNADTInteger;
            netAttr2.Units = esriNetworkAttributeUnits.esriNAUUnknown;
            netAttr2.UseByDefault = false;

            // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
            string roadClassExpression = "rc = 1          'Local road\n\r" +
                                         "If UCase([FERRY_TYPE]) = \"B\" Then\n\r" +
                                         "  rc = 4          'Ferry\n\r" +
                                         "ElseIf UCase([ROUNDABOUT]) = \"Y\" Then\n\r" +
                                         "  rc = 5          'Roundabout\n\r" +
                                         "ElseIf UCase([RAMP]) = \"Y\" Then\n\r" +
                                         "  rc = 3          'Ramp\n\r" +
                                         "ElseIf UCase([CONTRACC]) = \"Y\" Then\n\r" +
                                         "  rc = 2          'Highway\n\r" +
                                         "End If";

            netFieldEval = new NetworkFieldEvaluatorClass();
            netFieldEval.SetExpression("rc", roadClassExpression);
            evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

            netFieldEval = new NetworkFieldEvaluatorClass();
            netFieldEval.SetExpression("rc", roadClassExpression);
            evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

            // Add the attribute to the array.
            attributeArray.Add(evalNetAttr);

            if (fgdbVersion >= 10.1)
            {
                //
                // ManeuverClass network attribute
                //

                // Create an EvaluatedNetworkAttribute object and populate its settings.
                evalNetAttr = new EvaluatedNetworkAttributeClass();
                netAttr2 = (INetworkAttribute2)evalNetAttr;
                netAttr2.Name = "ManeuverClass";
                netAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTDescriptor;
                netAttr2.DataType = esriNetworkAttributeDataType.esriNADTInteger;
                netAttr2.Units = esriNetworkAttributeUnits.esriNAUUnknown;
                netAttr2.UseByDefault = false;

                // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                string maneuverClassExpression = "mc = 0          'Default\n\r" +
                                                 "If UCase([INTERINTER]) = \"Y\" Then\n\r" +
                                                 "  mc = 1          'Intersection Internal\n\r" +
                                                 "ElseIf UCase([MANOEUVRE]) = \"Y\" Then\n\r" +
                                                 "  mc = 2          'Maneuver\n\r" +
                                                 "End If";

                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("mc", maneuverClassExpression);
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("mc", maneuverClassExpression);
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

                // Add the attribute to the array.
                attributeArray.Add(evalNetAttr);
            }

            if (usesHistoricalTraffic || trafficFeedLocation != null)
            {
                //
                // TravelTime network attribute
                //

                // Create an EvaluatedNetworkAttribute object and populate its settings.
                evalNetAttr = new EvaluatedNetworkAttributeClass();
                netAttr2 = (INetworkAttribute2)evalNetAttr;
                netAttr2.Name = "TravelTime";
                netAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTCost;
                netAttr2.DataType = esriNetworkAttributeDataType.esriNADTDouble;
                netAttr2.Units = esriNetworkAttributeUnits.esriNAUMinutes;
                netAttr2.UseByDefault = true;

                // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                IHistoricalTravelTimeEvaluator histTravelTimeEval = new NetworkEdgeTrafficEvaluatorClass();
                histTravelTimeEval.WeekdayFallbackAttributeName = "Minutes";
                histTravelTimeEval.WeekendFallbackAttributeName = "Minutes";
                histTravelTimeEval.TimeNeutralAttributeName = "Minutes";
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)histTravelTimeEval);

                histTravelTimeEval = new NetworkEdgeTrafficEvaluatorClass();
                histTravelTimeEval.WeekdayFallbackAttributeName = "Minutes";
                histTravelTimeEval.WeekendFallbackAttributeName = "Minutes";
                histTravelTimeEval.TimeNeutralAttributeName = "Minutes";
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)histTravelTimeEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

                // Add the attribute to the array.
                attributeArray.Add(evalNetAttr);
            }
            else if (createArcGISOnlineNetworkAttributes)
            {
                //
                // TravelTime network attribute (dummy that is the same as the Minutes network attribute)
                //

                // Create an EvaluatedNetworkAttribute object and populate its settings.
                evalNetAttr = new EvaluatedNetworkAttributeClass();
                netAttr2 = (INetworkAttribute2)evalNetAttr;
                netAttr2.Name = "TravelTime";
                netAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTCost;
                netAttr2.DataType = esriNetworkAttributeDataType.esriNADTDouble;
                netAttr2.Units = esriNetworkAttributeUnits.esriNAUMinutes;
                netAttr2.UseByDefault = true;

                // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("[Minutes]", "");
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("[Minutes]", "");
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

                // Add the attribute to the array.
                attributeArray.Add(evalNetAttr);
            }

            //
            // TimeAt1KPH attribute
            //

            // Create an EvaluatedNetworkAttribute object and populate its settings.
            evalNetAttr = new EvaluatedNetworkAttributeClass();
            netAttr2 = (INetworkAttribute2)evalNetAttr;
            netAttr2.Name = "TimeAt1KPH";
            netAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTCost;
            netAttr2.DataType = esriNetworkAttributeDataType.esriNADTDouble;
            netAttr2.Units = esriNetworkAttributeUnits.esriNAUMinutes;
            netAttr2.UseByDefault = false;

            // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
            netFieldEval = new NetworkFieldEvaluatorClass();
            netFieldEval.SetExpression("[Meters] * 0.06", "");
            evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

            netFieldEval = new NetworkFieldEvaluatorClass();
            netFieldEval.SetExpression("[Meters] * 0.06", "");
            evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

            // Add the attribute to the array.
            attributeArray.Add(evalNetAttr);

            //
            // WalkTime attribute
            //

            // Create an EvaluatedNetworkAttribute object and populate its settings.
            evalNetAttr = new EvaluatedNetworkAttributeClass();
            netAttr2 = (INetworkAttribute2)evalNetAttr;
            netAttr2.Name = "WalkTime";
            netAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTCost;
            netAttr2.DataType = esriNetworkAttributeDataType.esriNADTDouble;
            netAttr2.Units = esriNetworkAttributeUnits.esriNAUMinutes;
            netAttr2.UseByDefault = false;

            // Create a parameter for Walking Speed (km/h) and add it to the network attribute.
            INetworkAttributeParameter2 netAttrParam = new NetworkAttributeParameterClass();
            netAttrParam.Name = "Walking Speed (km/h)";
            netAttrParam.VarType = (int)(VarEnum.VT_R8);
            netAttrParam.DefaultValue = 5.0;
            netAttrParam.ParameterUsageType = esriNetworkAttributeParameterUsageType.esriNAPUTGeneral;
            IArray paramArray = new ArrayClass();
            paramArray.Add(netAttrParam);
            netAttr2.Parameters = paramArray;

            // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
            INetworkFunctionEvaluator netFuncEval = new NetworkFunctionEvaluatorClass();
            netFuncEval.FirstArgument = "TimeAt1KPH";
            netFuncEval.Operator = "/";
            netFuncEval.SecondArgument = "Walking Speed (km/h)";
            evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFuncEval);

            netFuncEval = new NetworkFunctionEvaluatorClass();
            netFuncEval.FirstArgument = "TimeAt1KPH";
            netFuncEval.Operator = "/";
            netFuncEval.SecondArgument = "Walking Speed (km/h)";
            evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFuncEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

            // Add the attribute to the array.
            attributeArray.Add(evalNetAttr);

            //
            // Vehicle-specific network attributes
            //

            evalNetAttr = CreateVehicleNetworkAttribute("Driving an Automobile", true, -1.0, createArcGISOnlineNetworkAttributes,
                                                        "AR_AUTO", "AR_AUTO", fgdbVersion, edgeNetworkSource, turnNetworkSource, usesTransport);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateVehicleNetworkAttribute("Driving a Bus", false, -1.0, createArcGISOnlineNetworkAttributes,
                                                        "AR_BUS", "AR_BUS", fgdbVersion, edgeNetworkSource, turnNetworkSource, usesTransport);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateVehicleNetworkAttribute("Driving a Taxi", false, -1.0, createArcGISOnlineNetworkAttributes,
                                                        "AR_TAXIS", "AR_TAXIS", fgdbVersion, edgeNetworkSource, turnNetworkSource, usesTransport);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateVehicleNetworkAttribute("Walking", false, -1.0, false, "AR_PEDEST", "AR_PEDSTRN",
                                                        fgdbVersion, edgeNetworkSource, turnNetworkSource, usesTransport);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateVehicleNetworkAttribute("Avoid Truck Restricted Roads", false, AvoidHighFactor, createArcGISOnlineNetworkAttributes,
                                                        "AR_TRUCKS", "", fgdbVersion, edgeNetworkSource, turnNetworkSource, usesTransport);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateDrivingATruckNetworkAttribute(createArcGISOnlineNetworkAttributes, fgdbVersion, edgeNetworkSource, turnNetworkSource, usesTransport);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateVehicleNetworkAttribute("Driving an Emergency Vehicle", false, -1.0, createArcGISOnlineNetworkAttributes,
                                                        "AR_EMERVEH", "AR_EMERVEH", fgdbVersion, edgeNetworkSource, turnNetworkSource, usesTransport);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateVehicleNetworkAttribute("Riding a Motorcycle", false, -1.0, createArcGISOnlineNetworkAttributes,
                                                        "AR_MOTOR", "AR_MOTOR", fgdbVersion, edgeNetworkSource, turnNetworkSource, usesTransport);
            attributeArray.Add(evalNetAttr);

            //
            // Through Traffic Prohibited network attribute
            //

            evalNetAttr = CreateVehicleNetworkAttribute("Through Traffic Prohibited", (fgdbVersion >= 10.1), AvoidHighFactor, false,
                                                        "AR_TRAFF", "AR_THRUTR", fgdbVersion, edgeNetworkSource, turnNetworkSource, usesTransport);
            attributeArray.Add(evalNetAttr);

            //
            // Avoid-type network attributes
            //

            evalNetAttr = CreateAvoidNetworkAttribute("Avoid Unpaved Roads", "[PAVED] = \"N\"",
                                                      true, fgdbVersion, edgeNetworkSource, AvoidHighFactor);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateAvoidNetworkAttribute("Avoid Toll Roads", "[UFR_AUTO] = \"Y\"",
                                                      false, fgdbVersion, edgeNetworkSource);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateAvoidNetworkAttribute("Avoid Toll Roads for Trucks", "[UFR_TRUCKS] = \"Y\"",
                                                      false, fgdbVersion, edgeNetworkSource);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateAvoidNetworkAttribute("Avoid Limited Access Roads", "[CONTRACC] = \"Y\"",
                                                      false, fgdbVersion, edgeNetworkSource);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateAvoidNetworkAttribute("Avoid Ferries", "[FERRY_TYPE] = \"B\" Or [FERRY_TYPE] = \"R\"",
                                                      false, fgdbVersion, edgeNetworkSource);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateAvoidNetworkAttribute("Avoid Express Lanes", "[EXPR_LANE] = \"Y\"",
                                                      true, fgdbVersion, edgeNetworkSource, -1.0);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateAvoidNetworkAttribute("Avoid Carpool Roads", "[CARPOOLRD] = \"Y\"",
                                                      true, fgdbVersion, edgeNetworkSource, -1.0);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateAvoidNetworkAttribute("Avoid Private Roads", "[PUB_ACCESS] = \"N\"",
                                                      true, fgdbVersion, edgeNetworkSource);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateAvoidNetworkAttribute("Roads Under Construction Prohibited", "[ClosedForConstruction] = \"Y\"",
                                                      true, fgdbVersion, edgeNetworkSource, -1.0);
            attributeArray.Add(evalNetAttr);

            //
            // Avoid Gates network attribute
            //

            // Create an EvaluatedNetworkAttribute object and populate its settings.
            evalNetAttr = CreateRestrAttrNoEvals("Avoid Gates", fgdbVersion, AvoidMediumFactor, (fgdbVersion >= 10.1), "", "");

            // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
            netFieldEval = new NetworkFieldEvaluatorClass();
            netFieldEval.SetExpression("[COND_TYPE] = 4", "");
            evalNetAttr.set_Evaluator(turnNetworkSource, esriNetworkEdgeDirection.esriNEDNone, (INetworkEvaluator)netFieldEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = false;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = false;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = false;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

            // Add the attribute to the array.
            attributeArray.Add(evalNetAttr);

            //
            // Hierarchy network attribute
            //

            // Create an EvaluatedNetworkAttribute object and populate its settings.
            evalNetAttr = new EvaluatedNetworkAttributeClass();
            netAttr2 = (INetworkAttribute2)evalNetAttr;
            netAttr2.Name = "Hierarchy";
            netAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTHierarchy;
            netAttr2.DataType = esriNetworkAttributeDataType.esriNADTInteger;
            netAttr2.Units = esriNetworkAttributeUnits.esriNAUUnknown;
            netAttr2.UseByDefault = true;

            // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
            if (usesTransport)
            {
                string transportHierarchyPreLogic = "h = CInt( [FUNC_CLASS] )\n" +
                                                    "If Not IsNull([TruckFCOverride]) Then h = [TruckFCOverride]";

                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("h", transportHierarchyPreLogic);
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("h", transportHierarchyPreLogic);
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);
            }
            else
            {
                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("CInt( [FUNC_CLASS] )", "");
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("CInt( [FUNC_CLASS] )", "");
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);
            }

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

            // Add the attribute to the array.
            attributeArray.Add(evalNetAttr);

            // Since this is the hierarchy attribute, also set it as the hierarchy cluster attribute.
            deNetworkDataset.HierarchyClusterAttribute = (INetworkAttribute)evalNetAttr;

            // Specify the ranges for the hierarchy levels.
            deNetworkDataset.HierarchyLevelCount = 3;
            deNetworkDataset.set_MaxValueForHierarchy(1, 2); // level 1: up to 2
            deNetworkDataset.set_MaxValueForHierarchy(2, 4); // level 2: 3 - 4
            deNetworkDataset.set_MaxValueForHierarchy(3, 5); // level 3: 5 and higher (these values only go up to 5)

            //
            // Create and specify the time zone attribute (if applicable)
            //

            if (timeZoneIDBaseFieldName != "" || commonTimeZone != "")
            {
                string timeZoneAttrName = timeZoneIDBaseFieldName;
                if (timeZoneIDBaseFieldName == "")
                {
                    timeZoneAttrName = "TimeZoneID";

                    // Create the time zone table with the common time zone
                    TimeZoneUtilities.CreateTimeZoneTable(outputFileGdbPath, commonTimeZone);
                }

                //
                // TimeZoneID network attribute
                //

                // Create an EvaluatedNetworkAttribute object and populate its settings.
                evalNetAttr = new EvaluatedNetworkAttributeClass();
                netAttr2 = (INetworkAttribute2)evalNetAttr;
                netAttr2.Name = timeZoneAttrName;
                netAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTDescriptor;
                netAttr2.DataType = esriNetworkAttributeDataType.esriNADTInteger;
                netAttr2.Units = esriNetworkAttributeUnits.esriNAUUnknown;
                netAttr2.UseByDefault = false;

                // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                if (timeZoneIDBaseFieldName == "")
                {
                    netConstEval = new NetworkConstantEvaluatorClass();
                    netConstEval.ConstantValue = 1;
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netConstEval);

                    netConstEval = new NetworkConstantEvaluatorClass();
                    netConstEval.ConstantValue = 1;
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netConstEval);
                }
                else if (directedTimeZoneIDFields)
                {
                    netFieldEval = new NetworkFieldEvaluatorClass();
                    netFieldEval.SetExpression("[FT_" + timeZoneIDBaseFieldName + "]", "");
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                    netFieldEval = new NetworkFieldEvaluatorClass();
                    netFieldEval.SetExpression("[TF_" + timeZoneIDBaseFieldName + "]", "");
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);
                }
                else
                {
                    netFieldEval = new NetworkFieldEvaluatorClass();
                    netFieldEval.SetExpression("[" + timeZoneIDBaseFieldName + "]", "");
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                    netFieldEval = new NetworkFieldEvaluatorClass();
                    netFieldEval.SetExpression("[" + timeZoneIDBaseFieldName + "]", "");
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);
                }

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

                // Set this as the time zone attribute, and specify the time zone table.
                deNetworkDataset.TimeZoneAttributeName = timeZoneAttrName;
                deNetworkDataset.TimeZoneTableName = "TimeZones";

                // Add the attribute to the array.
                attributeArray.Add(evalNetAttr);
            }

            #region Add network attributes for Transport restrictions

            if (usesTransport)
            {
                string distUnit = " (feet)";
                string wtUnit = " (pounds)";
                if (createNetworkAttributesInMetric || createArcGISOnlineNetworkAttributes)
                {
                    distUnit = " (meters)";
                    wtUnit = " (kilograms)";
                }

                if (fgdbVersion >= 10.1)
                {
                    // Create attributes for preferred truck routes

                    if (createArcGISOnlineNetworkAttributes)
                    {
                        evalNetAttr = CreateLoadRestrictionAttribute("Use Preferred Truck Routes", true,
                                                                     "PreferredTruckRoute", fgdbVersion, edgeNetworkSource, null);
                        attributeArray.Add(evalNetAttr);
                    }
                    else
                    {
                        evalNetAttr = CreateMultiFieldLoadRestrictionAttribute("National STAA Preferred Route", true,
                                                                               new string[] { "STAAPreferred" },
                                                                               fgdbVersion, edgeNetworkSource, null);
                        attributeArray.Add(evalNetAttr);

                        evalNetAttr = CreateMultiFieldLoadRestrictionAttribute("National STAA and State Truck Designated Preferred Routes", true,
                                                                               new string[] { "STAAPreferred", "TruckDesignatedPreferred" },
                                                                               fgdbVersion, edgeNetworkSource, null);
                        attributeArray.Add(evalNetAttr);

                        evalNetAttr = CreateMultiFieldLoadRestrictionAttribute("National STAA and State Truck Designated and Locally Preferred Routes", true,
                                                                               new string[] { "STAAPreferred", "TruckDesignatedPreferred", "LocallyPreferred" },
                                                                               fgdbVersion, edgeNetworkSource, null);
                        attributeArray.Add(evalNetAttr);
                    }

                    // Create attributes for other preferred routes

                    if (createArcGISOnlineNetworkAttributes)
                    {
                        evalNetAttr = CreateLoadRestrictionAttribute("Use Preferred Hazmat Routes", true,
                                                                     "PreferredHazmatRoute", fgdbVersion, edgeNetworkSource, null);
                        attributeArray.Add(evalNetAttr);
                    }
                    else
                    {
                        evalNetAttr = CreateLoadRestrictionAttribute("Hazmat: NRHM Preferred Route", true,
                                                                     "NRHMPreferred", fgdbVersion, edgeNetworkSource, null);
                        attributeArray.Add(evalNetAttr);

                        evalNetAttr = CreateLoadRestrictionAttribute("Hazmat: Explosives Preferred Route", true,
                                                                     "ExplosivesPreferred", fgdbVersion, edgeNetworkSource, null);
                        attributeArray.Add(evalNetAttr);

                        evalNetAttr = CreateLoadRestrictionAttribute("Hazmat: Poisonous Inhalation Hazard Preferred Route", true,
                                                                     "PIHPreferred", fgdbVersion, edgeNetworkSource, null);
                        attributeArray.Add(evalNetAttr);

                        evalNetAttr = CreateLoadRestrictionAttribute("Hazmat: Medical Waste Materials Preferred Route", true,
                                                                     "MedicalWastePreferred", fgdbVersion, edgeNetworkSource, null);
                        attributeArray.Add(evalNetAttr);

                        evalNetAttr = CreateLoadRestrictionAttribute("Hazmat: Radioactive Materials Preferred Route", true,
                                                                     "RadioactivePreferred", fgdbVersion, edgeNetworkSource, null);
                        attributeArray.Add(evalNetAttr);

                        evalNetAttr = CreateLoadRestrictionAttribute("Hazmat: General Hazardous Materials Preferred Route", true,
                                                                     "HazmatPreferred", fgdbVersion, edgeNetworkSource, null);
                        attributeArray.Add(evalNetAttr);
                    }
                }

                // Create attributes for prohibited Hazmat routes

                if (createArcGISOnlineNetworkAttributes)
                {
                    evalNetAttr = CreateLoadRestrictionAttribute("Any Hazmat Prohibited", false,
                                                                 "AGOL_AnyHazmatProhibited", fgdbVersion, edgeNetworkSource, turnNetworkSource);
                    attributeArray.Add(evalNetAttr);
                }
                else
                {
                    evalNetAttr = CreateLoadRestrictionAttribute("Hazmat: Explosives Prohibited", false,
                                                                 "ExplosivesProhibited", fgdbVersion, edgeNetworkSource, turnNetworkSource);
                    attributeArray.Add(evalNetAttr);

                    evalNetAttr = CreateLoadRestrictionAttribute("Hazmat: Gas Prohibited", false,
                                                                 "GasProhibited", fgdbVersion, edgeNetworkSource, turnNetworkSource);
                    attributeArray.Add(evalNetAttr);

                    evalNetAttr = CreateLoadRestrictionAttribute("Hazmat: Flammable Goods Prohibited", false,
                                                                 "FlammableProhibited", fgdbVersion, edgeNetworkSource, turnNetworkSource);
                    attributeArray.Add(evalNetAttr);

                    evalNetAttr = CreateLoadRestrictionAttribute("Hazmat: Flammable solid/Combustible Prohibited", false,
                                                                 "CombustibleProhibited", fgdbVersion, edgeNetworkSource, turnNetworkSource);
                    attributeArray.Add(evalNetAttr);

                    evalNetAttr = CreateLoadRestrictionAttribute("Hazmat: Organic Goods Prohibited", false,
                                                                 "OrganicProhibited", fgdbVersion, edgeNetworkSource, turnNetworkSource);
                    attributeArray.Add(evalNetAttr);

                    evalNetAttr = CreateLoadRestrictionAttribute("Hazmat: Poison Goods Prohibited", false,
                                                                 "PoisonProhibited", fgdbVersion, edgeNetworkSource, turnNetworkSource);
                    attributeArray.Add(evalNetAttr);

                    evalNetAttr = CreateLoadRestrictionAttribute("Hazmat: Radioactive Goods Prohibited", false,
                                                                 "RadioactiveProhibited", fgdbVersion, edgeNetworkSource, turnNetworkSource);
                    attributeArray.Add(evalNetAttr);

                    evalNetAttr = CreateLoadRestrictionAttribute("Hazmat: Corrosive Goods Prohibited", false,
                                                                 "CorrosiveProhibited", fgdbVersion, edgeNetworkSource, turnNetworkSource);
                    attributeArray.Add(evalNetAttr);

                    evalNetAttr = CreateLoadRestrictionAttribute("Hazmat: Other Hazardous Materials Prohibited", false,
                                                                 "OtherHazmatProhibited", fgdbVersion, edgeNetworkSource, turnNetworkSource);
                    attributeArray.Add(evalNetAttr);

                    evalNetAttr = CreateLoadRestrictionAttribute("Hazmat: Any Hazardous Materials Prohibited", false,
                                                                 "AnyHazmatProhibited", fgdbVersion, edgeNetworkSource, turnNetworkSource);
                    attributeArray.Add(evalNetAttr);

                    evalNetAttr = CreateLoadRestrictionAttribute("Hazmat: Poisonous Inhalation Hazard Prohibited", false,
                                                                 "PIHProhibited", fgdbVersion, edgeNetworkSource, turnNetworkSource);
                    attributeArray.Add(evalNetAttr);

                    evalNetAttr = CreateLoadRestrictionAttribute("Hazmat: Goods Harmful to Water Prohibited", false,
                                                                 "HarmfulToWaterProhibited", fgdbVersion, edgeNetworkSource, turnNetworkSource);
                    attributeArray.Add(evalNetAttr);

                    evalNetAttr = CreateLoadRestrictionAttribute("Hazmat: Explosive and Flammable Prohibited", false,
                                                                 "ExplosiveAndFlammableProhibited", fgdbVersion, edgeNetworkSource, turnNetworkSource);
                    attributeArray.Add(evalNetAttr);
                }

                // Create attributes for other restricted routes

                evalNetAttr = CreateDimensionalLimitAttribute("Height Limit" + distUnit, "HeightLimit_Meters", createNetworkAttributesInMetric,
                                                              false, edgeNetworkSource, turnNetworkSource);
                attributeArray.Add(evalNetAttr);
                evalNetAttr = CreateDimensionalRestrictionAttribute("Height Restriction", "Height Limit" + distUnit, "Vehicle Height" + distUnit,
                                                                    fgdbVersion, edgeNetworkSource, turnNetworkSource);
                attributeArray.Add(evalNetAttr);

                evalNetAttr = CreateDimensionalLimitAttribute("Weight Limit" + wtUnit, "WeightLimit_Kilograms", createNetworkAttributesInMetric,
                                                              true, edgeNetworkSource, turnNetworkSource);
                attributeArray.Add(evalNetAttr);
                evalNetAttr = CreateDimensionalRestrictionAttribute("Weight Restriction", "Weight Limit" + wtUnit, "Vehicle Weight" + wtUnit,
                                                                    fgdbVersion, edgeNetworkSource, turnNetworkSource);
                attributeArray.Add(evalNetAttr);

                evalNetAttr = CreateDimensionalLimitAttribute("Weight Limit per Axle" + wtUnit, "WeightLimitPerAxle_Kilograms", createNetworkAttributesInMetric,
                                                              true, edgeNetworkSource, turnNetworkSource);
                attributeArray.Add(evalNetAttr);
                evalNetAttr = CreateDimensionalRestrictionAttribute("Weight per Axle Restriction", "Weight Limit per Axle" + wtUnit, "Vehicle Weight per Axle" + wtUnit,
                                                                    fgdbVersion, edgeNetworkSource, turnNetworkSource);
                attributeArray.Add(evalNetAttr);

                evalNetAttr = CreateDimensionalLimitAttribute("Length Limit" + distUnit, "LengthLimit_Meters", createNetworkAttributesInMetric,
                                                              false, edgeNetworkSource, turnNetworkSource);
                attributeArray.Add(evalNetAttr);
                evalNetAttr = CreateDimensionalRestrictionAttribute("Length Restriction", "Length Limit" + distUnit, "Vehicle Length" + distUnit,
                                                                    fgdbVersion, edgeNetworkSource, turnNetworkSource);
                attributeArray.Add(evalNetAttr);

                evalNetAttr = CreateDimensionalLimitAttribute("Width Limit" + distUnit, "WidthLimit_Meters", createNetworkAttributesInMetric,
                                                              false, edgeNetworkSource, turnNetworkSource);
                attributeArray.Add(evalNetAttr);
                evalNetAttr = CreateDimensionalRestrictionAttribute("Width Restriction", "Width Limit" + distUnit, "Vehicle Width" + distUnit,
                                                                    fgdbVersion, edgeNetworkSource, turnNetworkSource);
                attributeArray.Add(evalNetAttr);

                evalNetAttr = CreateQuantityLimitAttribute("Maximum Number of Trailers Allowed on Truck", "MaxTrailersAllowedOnTruck",
                                                           edgeNetworkSource, turnNetworkSource);
                attributeArray.Add(evalNetAttr);
                evalNetAttr = CreateQuantityRestrictionAttribute("Truck with Trailers Restriction", "Maximum Number of Trailers Allowed on Truck", "Number of Trailers on Truck",
                                                                 fgdbVersion, edgeNetworkSource, turnNetworkSource);
                attributeArray.Add(evalNetAttr);

                evalNetAttr = CreateLoadRestrictionAttribute("Semi or Tractor with One or More Trailers Prohibited", false,
                                                             "SemiOrTractorWOneOrMoreTrailersProhibited", fgdbVersion, edgeNetworkSource, turnNetworkSource);
                attributeArray.Add(evalNetAttr);

                evalNetAttr = CreateQuantityLimitAttribute("Maximum Number of Axles Allowed", "MaxAxlesAllowed",
                                                           edgeNetworkSource, turnNetworkSource);
                attributeArray.Add(evalNetAttr);
                evalNetAttr = CreateQuantityRestrictionAttribute("Axle Count Restriction", "Maximum Number of Axles Allowed", "Number of Axles",
                                                                 fgdbVersion, edgeNetworkSource, turnNetworkSource);
                attributeArray.Add(evalNetAttr);

                evalNetAttr = CreateLoadRestrictionAttribute("Single Axle Vehicles Prohibited", false,
                                                             "SingleAxleProhibited", fgdbVersion, edgeNetworkSource, turnNetworkSource);
                attributeArray.Add(evalNetAttr);

                evalNetAttr = CreateLoadRestrictionAttribute("Tandem Axle Vehicles Prohibited", false,
                                                             "TandemAxleProhibited", fgdbVersion, edgeNetworkSource, turnNetworkSource);
                attributeArray.Add(evalNetAttr);

                evalNetAttr = CreateDimensionalLimitAttribute("Kingpin to Rear Axle Length Limit" + distUnit, "KingpinToRearAxleLengthLimit_Meters", createNetworkAttributesInMetric,
                                                              false, edgeNetworkSource, turnNetworkSource);
                attributeArray.Add(evalNetAttr);
                evalNetAttr = CreateDimensionalRestrictionAttribute("Kingpin to Rear Axle Length Restriction", "Kingpin to Rear Axle Length Limit" + distUnit, "Vehicle Kingpin to Rear Axle Length" + distUnit,
                                                                    fgdbVersion, edgeNetworkSource, turnNetworkSource);
                attributeArray.Add(evalNetAttr);

                //
                // TruckTravelTime attribute
                //

                // Create an EvaluatedNetworkAttribute object and populate its settings.
                evalNetAttr = new EvaluatedNetworkAttributeClass();
                netAttr2 = (INetworkAttribute2)evalNetAttr;
                netAttr2.Name = "TruckTravelTime";
                netAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTCost;
                netAttr2.DataType = esriNetworkAttributeDataType.esriNADTDouble;
                netAttr2.Units = esriNetworkAttributeUnits.esriNAUMinutes;
                netAttr2.UseByDefault = false;

                // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                if (usesHistoricalTraffic)
                {
                    netFieldEval = new NetworkFieldEvaluatorClass();
                    netFieldEval.SetExpression("ttt", "ttt = [FT_Minutes]\ntruckSpeed = [FT_TruckKPH]\nIf Not IsNull(truckSpeed) Then ttt = [Meters] * 0.06 / truckSpeed\nIf ttt < [FT_Minutes] Then ttt = [FT_Minutes]");
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                    netFieldEval = new NetworkFieldEvaluatorClass();
                    netFieldEval.SetExpression("ttt", "ttt = [TF_Minutes]\ntruckSpeed = [TF_TruckKPH]\nIf Not IsNull(truckSpeed) Then ttt = [Meters] * 0.06 / truckSpeed\nIf ttt < [TF_Minutes] Then ttt = [TF_Minutes]");
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);
                }
                else
                {
                    netFieldEval = new NetworkFieldEvaluatorClass();
                    netFieldEval.SetExpression("[Meters] * 0.06 / truckSpeed", "truckSpeed = [FT_TruckKPH]\nIf IsNull(truckSpeed) Then truckSpeed = [KPH]\nIf truckSpeed > [KPH] Then truckSpeed = [KPH]");
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                    netFieldEval = new NetworkFieldEvaluatorClass();
                    netFieldEval.SetExpression("[Meters] * 0.06 / truckSpeed", "truckSpeed = [TF_TruckKPH]\nIf IsNull(truckSpeed) Then truckSpeed = [KPH]\nIf truckSpeed > [KPH] Then truckSpeed = [KPH]");
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);
                }

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

                // Add the attribute to the array.
                attributeArray.Add(evalNetAttr);
            }
            else if (createArcGISOnlineNetworkAttributes)
            {
                //
                // TruckTravelTime network attribute (dummy that is the same as the Minutes network attribute)
                //

                // Create an EvaluatedNetworkAttribute object and populate its settings.
                evalNetAttr = new EvaluatedNetworkAttributeClass();
                netAttr2 = (INetworkAttribute2)evalNetAttr;
                netAttr2.Name = "TruckTravelTime";
                netAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTCost;
                netAttr2.DataType = esriNetworkAttributeDataType.esriNADTDouble;
                netAttr2.Units = esriNetworkAttributeUnits.esriNAUMinutes;
                netAttr2.UseByDefault = false;

                if (usesHistoricalTraffic)
                {
                    // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                    netFieldEval = new NetworkFieldEvaluatorClass();
                    netFieldEval.SetExpression("[FT_Minutes]", "");
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                    netFieldEval = new NetworkFieldEvaluatorClass();
                    netFieldEval.SetExpression("[TF_Minutes]", "");
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);
                }
                else
                {
                    // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                    netFieldEval = new NetworkFieldEvaluatorClass();
                    netFieldEval.SetExpression("[Minutes]", "");
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                    netFieldEval = new NetworkFieldEvaluatorClass();
                    netFieldEval.SetExpression("[Minutes]", "");
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);
                }

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

                // Add the attribute to the array.
                attributeArray.Add(evalNetAttr);
            }
            #endregion

            //
            // Add all attributes to the data element
            //

            deNetworkDataset.Attributes = attributeArray;

            if (fgdbVersion >= 10.1)
            {
                //
                // Add travel modes
                //

                IArray travelModeArray = new ArrayClass();

                // Initialize variables reused when creating travel modes:
                INetworkTravelMode2 travelMode;
                string timeAttributeName;
                string distanceAttributeName;
                IStringArray restrictionsArray;
                IArray paramValuesArray;
                INetworkTravelModeParameterValue tmParamValue;
                string preferredTruckRoutesAttributeName = createArcGISOnlineNetworkAttributes ?
                                                           "Use Preferred Truck Routes" : "National STAA and State Truck Designated and Locally Preferred Routes";

                //
                // Driving Time travel mode
                //

                // Create a NetworkTravelMode object and populate its settings.
                travelMode = new NetworkTravelModeClass();
                travelMode.Name = "Driving Time";
                timeAttributeName = ((usesHistoricalTraffic || createArcGISOnlineNetworkAttributes) ? "TravelTime" : "Minutes");
                distanceAttributeName = (createNetworkAttributesInMetric ? "Kilometers" : "Miles");
                travelMode.ImpedanceAttributeName = timeAttributeName;
                travelMode.TimeAttributeName = timeAttributeName;
                travelMode.DistanceAttributeName = distanceAttributeName;
                travelMode.UseHierarchy = true;
                travelMode.RestrictUTurns = esriNetworkForwardStarBacktrack.esriNFSBAtDeadEndsAndIntersections;
                travelMode.OutputGeometryPrecision = 10;
                travelMode.OutputGeometryPrecisionUnits = esriUnits.esriMeters;
                travelMode.Type = "AUTOMOBILE";
                travelMode.Description = "Models the movement of cars and other similar small automobiles, such as pickup trucks, and finds solutions that optimize travel time. " +
                                         "Travel obeys one-way roads, avoids illegal turns, and follows other rules that are specific to cars. " +
                                         "Dynamic travel speeds based on traffic are used where it is available when you specify a start time.";

                // Populate the restriction attributes to use.
                restrictionsArray = new StrArrayClass();
                restrictionsArray.Add("Driving an Automobile");
                restrictionsArray.Add("Through Traffic Prohibited");
                restrictionsArray.Add("Avoid Unpaved Roads");
                restrictionsArray.Add("Avoid Express Lanes");
                restrictionsArray.Add("Avoid Carpool Roads");
                restrictionsArray.Add("Avoid Private Roads");
                restrictionsArray.Add("Roads Under Construction Prohibited");
                restrictionsArray.Add("Avoid Gates");
                if (!createArcGISOnlineNetworkAttributes)
                    restrictionsArray.Add("Oneway");    // For ArcGIS Online, the Oneway information is rolled into the Driving restrictions.

                travelMode.RestrictionAttributeNames = restrictionsArray;

                // Add the travel mode to the array.
                travelModeArray.Add(travelMode);

                //
                // Driving Distance travel mode
                //

                // Create a NetworkTravelMode object and populate its settings.
                travelMode = new NetworkTravelModeClass();
                travelMode.Name = "Driving Distance";
                timeAttributeName = ((usesHistoricalTraffic || createArcGISOnlineNetworkAttributes) ? "TravelTime" : "Minutes");
                distanceAttributeName = (createNetworkAttributesInMetric ? "Kilometers" : "Miles");
                travelMode.ImpedanceAttributeName = distanceAttributeName;
                travelMode.TimeAttributeName = timeAttributeName;
                travelMode.DistanceAttributeName = distanceAttributeName;
                travelMode.UseHierarchy = true;
                travelMode.RestrictUTurns = esriNetworkForwardStarBacktrack.esriNFSBAtDeadEndsAndIntersections;
                travelMode.OutputGeometryPrecision = 10;
                travelMode.OutputGeometryPrecisionUnits = esriUnits.esriMeters;
                travelMode.Type = "AUTOMOBILE";
                travelMode.Description = "Models the movement of cars and other similar small automobiles, such as pickup trucks, and finds solutions that optimize travel distance. " +
                                         "Travel obeys one-way roads, avoids illegal turns, and follows other rules that are specific to cars.";

                // Populate the restriction attributes to use.
                restrictionsArray = new StrArrayClass();
                restrictionsArray.Add("Driving an Automobile");
                restrictionsArray.Add("Through Traffic Prohibited");
                restrictionsArray.Add("Avoid Unpaved Roads");
                restrictionsArray.Add("Avoid Express Lanes");
                restrictionsArray.Add("Avoid Carpool Roads");
                restrictionsArray.Add("Avoid Private Roads");
                restrictionsArray.Add("Roads Under Construction Prohibited");
                restrictionsArray.Add("Avoid Gates");
                if (!createArcGISOnlineNetworkAttributes)
                    restrictionsArray.Add("Oneway");    // For ArcGIS Online, the Oneway information is rolled into the Driving restrictions.

                travelMode.RestrictionAttributeNames = restrictionsArray;

                // Add the travel mode to the array.
                travelModeArray.Add(travelMode);

                //
                // Rural Driving Time travel mode
                //

                // Create a NetworkTravelMode object and populate its settings.
                travelMode = new NetworkTravelModeClass();
                travelMode.Name = "Rural Driving Time";
                timeAttributeName = ((usesHistoricalTraffic || createArcGISOnlineNetworkAttributes) ? "TravelTime" : "Minutes");
                distanceAttributeName = (createNetworkAttributesInMetric ? "Kilometers" : "Miles");
                travelMode.ImpedanceAttributeName = timeAttributeName;
                travelMode.TimeAttributeName = timeAttributeName;
                travelMode.DistanceAttributeName = distanceAttributeName;
                travelMode.UseHierarchy = true;
                travelMode.RestrictUTurns = esriNetworkForwardStarBacktrack.esriNFSBAtDeadEndsAndIntersections;
                travelMode.OutputGeometryPrecision = 10;
                travelMode.OutputGeometryPrecisionUnits = esriUnits.esriMeters;
                travelMode.Type = "AUTOMOBILE";
                travelMode.Description = "Models the movement of cars and other similar small automobiles, such as pickup trucks, and finds solutions that optimize travel time. " +
                                         "Travel obeys one-way roads, avoids illegal turns, and follows other rules that are specific to cars, but does not discourage travel on unpaved roads. " +
                                         "Dynamic travel speeds based on traffic are used where it is available when you specify a start time.";

                // Populate the restriction attributes to use.
                restrictionsArray = new StrArrayClass();
                restrictionsArray.Add("Driving an Automobile");
                restrictionsArray.Add("Through Traffic Prohibited");
                restrictionsArray.Add("Avoid Express Lanes");
                restrictionsArray.Add("Avoid Carpool Roads");
                restrictionsArray.Add("Avoid Private Roads");
                restrictionsArray.Add("Roads Under Construction Prohibited");
                restrictionsArray.Add("Avoid Gates");
                if (!createArcGISOnlineNetworkAttributes)
                    restrictionsArray.Add("Oneway");    // For ArcGIS Online, the Oneway information is rolled into the Driving restrictions.

                travelMode.RestrictionAttributeNames = restrictionsArray;

                // Add the travel mode to the array.
                travelModeArray.Add(travelMode);

                //
                // Rural Driving Distance travel mode
                //

                // Create a NetworkTravelMode object and populate its settings.
                travelMode = new NetworkTravelModeClass();
                travelMode.Name = "Rural Driving Distance";
                timeAttributeName = ((usesHistoricalTraffic || createArcGISOnlineNetworkAttributes) ? "TravelTime" : "Minutes");
                distanceAttributeName = (createNetworkAttributesInMetric ? "Kilometers" : "Miles");
                travelMode.ImpedanceAttributeName = distanceAttributeName;
                travelMode.TimeAttributeName = timeAttributeName;
                travelMode.DistanceAttributeName = distanceAttributeName;
                travelMode.UseHierarchy = true;
                travelMode.RestrictUTurns = esriNetworkForwardStarBacktrack.esriNFSBAtDeadEndsAndIntersections;
                travelMode.OutputGeometryPrecision = 10;
                travelMode.OutputGeometryPrecisionUnits = esriUnits.esriMeters;
                travelMode.Type = "AUTOMOBILE";
                travelMode.Description = "Models the movement of cars and other similar small automobiles, such as pickup trucks, and finds solutions that optimize travel distance. " +
                                         "Travel obeys one-way roads, avoids illegal turns, and follows other rules that are specific to cars, but does not discourage travel on unpaved roads.";

                // Populate the restriction attributes to use.
                restrictionsArray = new StrArrayClass();
                restrictionsArray.Add("Driving an Automobile");
                restrictionsArray.Add("Through Traffic Prohibited");
                restrictionsArray.Add("Avoid Express Lanes");
                restrictionsArray.Add("Avoid Carpool Roads");
                restrictionsArray.Add("Avoid Private Roads");
                restrictionsArray.Add("Roads Under Construction Prohibited");
                restrictionsArray.Add("Avoid Gates");
                if (!createArcGISOnlineNetworkAttributes)
                    restrictionsArray.Add("Oneway");    // For ArcGIS Online, the Oneway information is rolled into the Driving restrictions.

                travelMode.RestrictionAttributeNames = restrictionsArray;

                // Add the travel mode to the array.
                travelModeArray.Add(travelMode);

                //
                // Trucking Time travel mode
                //

                // Create a NetworkTravelMode object and populate its settings.
                travelMode = new NetworkTravelModeClass();
                travelMode.Name = "Trucking Time";
                timeAttributeName = ((usesTransport || createArcGISOnlineNetworkAttributes) ? "TruckTravelTime" : "Minutes");
                distanceAttributeName = (createNetworkAttributesInMetric ? "Kilometers" : "Miles");
                travelMode.ImpedanceAttributeName = timeAttributeName;
                travelMode.TimeAttributeName = timeAttributeName;
                travelMode.DistanceAttributeName = distanceAttributeName;
                travelMode.UseHierarchy = true;
                travelMode.RestrictUTurns = esriNetworkForwardStarBacktrack.esriNFSBNoBacktrack;
                travelMode.OutputGeometryPrecision = 10;
                travelMode.OutputGeometryPrecisionUnits = esriUnits.esriMeters;
                travelMode.Type = "TRUCK";
                travelMode.Description = "Models basic truck travel by preferring designated truck routes, and finds solutions that optimize travel time. " +
                                         "Routes must obey one-way roads, avoid illegal turns, and so on.";

                // Populate attribute parameter values to use.
                paramValuesArray = new ArrayClass();
                tmParamValue = new NetworkTravelModeParameterValueClass();
                tmParamValue.AttributeName = "Driving a Truck";
                tmParamValue.ParameterName = "Restriction Usage";
                tmParamValue.Value = AvoidHighFactor;
                paramValuesArray.Add(tmParamValue);

                // Populate the restriction attributes to use.
                restrictionsArray = new StrArrayClass();
                restrictionsArray.Add("Driving a Truck");
                restrictionsArray.Add("Avoid Truck Restricted Roads");
                restrictionsArray.Add("Avoid Unpaved Roads");
                restrictionsArray.Add("Avoid Express Lanes");
                restrictionsArray.Add("Avoid Carpool Roads");
                restrictionsArray.Add("Avoid Private Roads");
                restrictionsArray.Add("Roads Under Construction Prohibited");
                restrictionsArray.Add("Avoid Gates");
                if (!createArcGISOnlineNetworkAttributes)
                    restrictionsArray.Add("Oneway");    // For ArcGIS Online, the Oneway information is rolled into the Driving restrictions.
                if (usesTransport)
                {
                    restrictionsArray.Add(preferredTruckRoutesAttributeName);
                    tmParamValue = new NetworkTravelModeParameterValueClass();
                    tmParamValue.AttributeName = preferredTruckRoutesAttributeName;
                    tmParamValue.ParameterName = "Restriction Usage";
                    tmParamValue.Value = PreferHighFactor;
                    paramValuesArray.Add(tmParamValue);
                }

                travelMode.RestrictionAttributeNames = restrictionsArray;
                travelMode.AttributeParameterValues = paramValuesArray;

                // Add the travel mode to the array.
                travelModeArray.Add(travelMode);

                //
                // Trucking Distance travel mode
                //

                // Create a NetworkTravelMode object and populate its settings.
                travelMode = new NetworkTravelModeClass();
                travelMode.Name = "Trucking Distance";
                timeAttributeName = ((usesTransport || createArcGISOnlineNetworkAttributes) ? "TruckTravelTime" : "Minutes");
                distanceAttributeName = (createNetworkAttributesInMetric ? "Kilometers" : "Miles");
                travelMode.ImpedanceAttributeName = distanceAttributeName;
                travelMode.TimeAttributeName = timeAttributeName;
                travelMode.DistanceAttributeName = distanceAttributeName;
                travelMode.UseHierarchy = true;
                travelMode.RestrictUTurns = esriNetworkForwardStarBacktrack.esriNFSBNoBacktrack;
                travelMode.OutputGeometryPrecision = 10;
                travelMode.OutputGeometryPrecisionUnits = esriUnits.esriMeters;
                travelMode.Type = "TRUCK";
                travelMode.Description = "Models basic truck travel by preferring designated truck routes, and finds solutions that optimize travel distance. " +
                                         "Routes must obey one-way roads, avoid illegal turns, and so on.";

                // Populate attribute parameter values to use.
                paramValuesArray = new ArrayClass();
                tmParamValue = new NetworkTravelModeParameterValueClass();
                tmParamValue.AttributeName = "Driving a Truck";
                tmParamValue.ParameterName = "Restriction Usage";
                tmParamValue.Value = AvoidHighFactor;
                paramValuesArray.Add(tmParamValue);

                // Populate the restriction attributes to use.
                restrictionsArray = new StrArrayClass();
                restrictionsArray.Add("Driving a Truck");
                restrictionsArray.Add("Avoid Truck Restricted Roads");
                restrictionsArray.Add("Avoid Unpaved Roads");
                restrictionsArray.Add("Avoid Express Lanes");
                restrictionsArray.Add("Avoid Carpool Roads");
                restrictionsArray.Add("Avoid Private Roads");
                restrictionsArray.Add("Roads Under Construction Prohibited");
                restrictionsArray.Add("Avoid Gates");
                if (!createArcGISOnlineNetworkAttributes)
                    restrictionsArray.Add("Oneway");    // For ArcGIS Online, the Oneway information is rolled into the Driving restrictions.
                if (usesTransport)
                {
                    restrictionsArray.Add(preferredTruckRoutesAttributeName);
                    tmParamValue = new NetworkTravelModeParameterValueClass();
                    tmParamValue.AttributeName = preferredTruckRoutesAttributeName;
                    tmParamValue.ParameterName = "Restriction Usage";
                    tmParamValue.Value = PreferHighFactor;
                    paramValuesArray.Add(tmParamValue);
                }

                travelMode.RestrictionAttributeNames = restrictionsArray;
                travelMode.AttributeParameterValues = paramValuesArray;

                // Add the travel mode to the array.
                travelModeArray.Add(travelMode);

                //
                // Walking Time travel mode
                //

                // Create a NetworkTravelMode object and populate its settings.
                travelMode = new NetworkTravelModeClass();
                travelMode.Name = "Walking Time";
                timeAttributeName = "WalkTime";
                distanceAttributeName = (createNetworkAttributesInMetric ? "Kilometers" : "Miles");
                travelMode.ImpedanceAttributeName = timeAttributeName;
                travelMode.TimeAttributeName = timeAttributeName;
                travelMode.DistanceAttributeName = distanceAttributeName;
                travelMode.UseHierarchy = false;
                travelMode.RestrictUTurns = esriNetworkForwardStarBacktrack.esriNFSBAllowBacktrack;
                travelMode.OutputGeometryPrecision = 2;
                travelMode.OutputGeometryPrecisionUnits = esriUnits.esriMeters;
                travelMode.Type = "WALK";

                string walkDescription = "Follows paths and roads that allow pedestrian traffic and finds solutions that optimize travel time. ";
                if (createArcGISOnlineNetworkAttributes)
                    walkDescription += "The walking speed is set to 5 kilometers per hour.";
                else
                    walkDescription += "By default, the walking speed is set to 5 kilometers per hour.";
                travelMode.Description = walkDescription;

                // Populate the restriction attributes to use.
                restrictionsArray = new StrArrayClass();
                restrictionsArray.Add("Walking");
                restrictionsArray.Add("Avoid Private Roads");
                travelMode.RestrictionAttributeNames = restrictionsArray;

                // Add the travel mode to the array.
                travelModeArray.Add(travelMode);

                //
                // Walking Distance travel mode
                //

                // Create a NetworkTravelMode object and populate its settings.
                travelMode = new NetworkTravelModeClass();
                travelMode.Name = "Walking Distance";
                timeAttributeName = "WalkTime";
                distanceAttributeName = (createNetworkAttributesInMetric ? "Kilometers" : "Miles");
                travelMode.ImpedanceAttributeName = distanceAttributeName;
                travelMode.TimeAttributeName = timeAttributeName;
                travelMode.DistanceAttributeName = distanceAttributeName;
                travelMode.UseHierarchy = false;
                travelMode.RestrictUTurns = esriNetworkForwardStarBacktrack.esriNFSBAllowBacktrack;
                travelMode.OutputGeometryPrecision = 2;
                travelMode.OutputGeometryPrecisionUnits = esriUnits.esriMeters;
                travelMode.Type = "WALK";
                travelMode.Description = "Follows paths and roads that allow pedestrian traffic and finds solutions that optimize travel distance.";

                // Populate the restriction attributes to use.
                restrictionsArray = new StrArrayClass();
                restrictionsArray.Add("Walking");
                restrictionsArray.Add("Avoid Private Roads");
                travelMode.RestrictionAttributeNames = restrictionsArray;

                // Add the travel mode to the array.
                travelModeArray.Add(travelMode);

                //
                // Add all travel modes to the data element
                //

                deNetworkDataset.TravelModes = travelModeArray;
            }

            //
            // Specify directions settings
            //

            // Create a NetworkDirections object and populate its settings.
            INetworkDirections networkDirections = new NetworkDirectionsClass();
            networkDirections.DefaultOutputLengthUnits = createNetworkAttributesInMetric ? esriNetworkAttributeUnits.esriNAUKilometers : esriNetworkAttributeUnits.esriNAUMiles;
            networkDirections.LengthAttributeName = createNetworkAttributesInMetric ? "Kilometers" : "Miles";
            networkDirections.TimeAttributeName = "Minutes";
            networkDirections.RoadClassAttributeName = "RoadClass";
            var netDirSignposts = (ISignposts)networkDirections;
            netDirSignposts.SignpostFeatureClassName = SignpostFCName;
            netDirSignposts.SignpostStreetsTableName = SignpostJoinTableName;

            if (fgdbVersion >= 10.1)
            {
                // Specify the RoadSplits table.
                var netDirRoadSplits = (IRoadSplits)networkDirections;
                netDirRoadSplits.RoadSplitsTableName = RoadSplitsTableName;

                // Create a DirectionsAttributeMapping object for the ManeuverClass mapping.
                IDirectionsAttributeMapping dirAttrMapping = new DirectionsAttributeMappingClass();
                dirAttrMapping.KeyName = "ManeuverClass";
                dirAttrMapping.AttributeName = "ManeuverClass";

                // Wrap the DirectionsAttributeMapping object in an Array and add it to the NetworkDirections object.
                IArray damArray = new ArrayClass();
                damArray.Add(dirAttrMapping);
                var networkDirections2 = (INetworkDirections2)networkDirections;
                networkDirections2.AttributeMappings = damArray;
            }

            // Add the NetworkDirections object to the network dataset data element.
            deNetworkDataset.Directions = networkDirections;

            //
            // Create and build the network dataset
            //

            // Get the feature dataset extension and create the network dataset based on the data element.
            var fdxContainer = (IFeatureDatasetExtensionContainer)featureDataset;
            IFeatureDatasetExtension fdExtension = fdxContainer.FindExtension(esriDatasetType.esriDTNetworkDataset);
            var datasetContainer2 = (IDatasetContainer2)fdExtension;
            var deDataset = (IDEDataset)deNetworkDataset;
            var networkDataset = (INetworkDataset)datasetContainer2.CreateDataset(deDataset);

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

            return;
        }
        private void CreateAndBuildNetworkDataset(string outputFileGdbPath, double fgdbVersion, string fdsName, string ndsName,
                                                  bool createNetworkAttributesInMetric, bool createTwoDistanceAttributes,
                                                  string timeZoneIDBaseFieldName, bool directedTimeZoneIDFields, string commonTimeZone,
                                                  bool usesHistoricalTraffic, ITrafficFeedLocation trafficFeedLocation,
                                                  bool usesRSTable, bool usesLTRTable, bool usesLRSTable, string lrsStatsTableName)
        {
            // This code is modified from "How to create a network dataset" in the ArcObjects SDK.

            //
            // Create a network dataset data element
            //

            // Create an empty data element for a buildable network dataset.
            IDENetworkDataset3 deNetworkDataset = new DENetworkDatasetClass();
            deNetworkDataset.Buildable = true;

            // Open the feature dataset and cast to the IGeoDataset interface.
            Type factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory");
            var workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance(factoryType);
            IWorkspace workspace = workspaceFactory.OpenFromFile(outputFileGdbPath, 0);
            var featureWorkspace = (IFeatureWorkspace)workspace;
            IFeatureDataset featureDataset = featureWorkspace.OpenFeatureDataset(fdsName);
            var geoDataset = (IGeoDataset)featureDataset;

            // Copy the feature dataset's extent and spatial reference to the network dataset data element.
            var deGeoDataset = (IDEGeoDataset)deNetworkDataset;
            deGeoDataset.Extent = geoDataset.Extent;
            deGeoDataset.SpatialReference = geoDataset.SpatialReference;

            // Specify the name of the network dataset.
            var dataElement = (IDataElement)deNetworkDataset;
            dataElement.Name = ndsName;

            //
            // Add network sources
            //

            // Specify the network dataset's elevation model.
            deNetworkDataset.ElevationModel = esriNetworkElevationModel.esriNEMElevationFields;

            // Create an EdgeFeatureSource object and point it to the Streets feature class.
            INetworkSource edgeNetworkSource = new EdgeFeatureSourceClass();
            edgeNetworkSource.Name = StreetsFCName;
            edgeNetworkSource.ElementType = esriNetworkElementType.esriNETEdge;

            // Set the edge feature source's connectivity settings.
            var edgeFeatureSource = (IEdgeFeatureSource)edgeNetworkSource;
            edgeFeatureSource.UsesSubtypes = false;
            edgeFeatureSource.ClassConnectivityGroup = 1;
            edgeFeatureSource.ClassConnectivityPolicy = esriNetworkEdgeConnectivityPolicy.esriNECPEndVertex;
            edgeFeatureSource.FromElevationFieldName = "F_ELEV";
            edgeFeatureSource.ToElevationFieldName = "T_ELEV";

            //
            // Specify directions settings for the edge source
            //

            // Create a StreetNameFields object and populate its settings.
            IStreetNameFields streetNameFields = new StreetNameFieldsClass();
            streetNameFields.Priority = 1; // Priority 1 indicates the primary street name.
            streetNameFields.StreetNameFieldName = "NAME";

            // Add the StreetNameFields object to a new NetworkSourceDirections object,
            // then add it to the EdgeFeatureSource created earlier.
            INetworkSourceDirections nsDirections = new NetworkSourceDirectionsClass();
            IArray nsdArray = new ArrayClass();
            nsdArray.Add(streetNameFields);
            nsDirections.StreetNameFields = nsdArray;
            edgeNetworkSource.NetworkSourceDirections = nsDirections;

            //
            // Specify the turn source
            //

            deNetworkDataset.SupportsTurns = true;

            // Create a TurnFeatureSource object and point it to the RestrictedTurns feature class.
            INetworkSource turnNetworkSource = new TurnFeatureSourceClass();
            turnNetworkSource.Name = TurnFCName;
            turnNetworkSource.ElementType = esriNetworkElementType.esriNETTurn;

            //
            // Add all sources to the data element
            //

            IArray sourceArray = new ArrayClass();
            sourceArray.Add(edgeNetworkSource);
            sourceArray.Add(turnNetworkSource);

            deNetworkDataset.Sources = sourceArray;

            //
            // Add the traffic data tables (if applicable)
            //

            if (usesHistoricalTraffic || (trafficFeedLocation != null))
            {
                // Create a new TrafficData object and populate its historical and live traffic settings.
                var traffData = new TrafficDataClass() as ITrafficData2;
                traffData.LengthAttributeName = (createNetworkAttributesInMetric ? "Kilometers" : "Miles");

                // Populate the speed profile table settings.
                var histTraff = traffData as IHistoricalTrafficData2;
                histTraff.ProfilesTableName = ProfilesTableName;
                if (usesHistoricalTraffic)
                {
                    if (fgdbVersion == 10.0)
                    {
                        histTraff.FirstTimeSliceFieldName = "TimeFactor_0000";
                        histTraff.LastTimeSliceFieldName = "TimeFactor_2355";
                    }
                    else
                    {
                        histTraff.FirstTimeSliceFieldName = "SpeedFactor_0000";
                        histTraff.LastTimeSliceFieldName = "SpeedFactor_2355";
                    }
                }
                else
                {
                    histTraff.FirstTimeSliceFieldName = "SpeedFactor_AM";
                    histTraff.LastTimeSliceFieldName = "SpeedFactor_PM";
                }
                histTraff.TimeSliceDurationInMinutes = usesHistoricalTraffic ? 5 : 720;
                histTraff.FirstTimeSliceStartTime = new DateTime(1, 1, 1, 0, 0, 0); // 12 AM
                // Note: the last time slice finish time is implied from the above settings and need not be specified.

                // Populate the street-speed profile join table settings.
                histTraff.JoinTableName = HistTrafficJoinTableName;
                if (usesHistoricalTraffic)
                {
                    if (fgdbVersion == 10.0)
                    {
                        histTraff.JoinTableBaseTravelTimeFieldName = "FreeflowMinutes";
                        histTraff.JoinTableBaseTravelTimeUnits = esriNetworkAttributeUnits.esriNAUMinutes;
                    }
                    else
                    {
                        histTraff.JoinTableBaseSpeedFieldName = "SPFREEFLOW";
                        histTraff.JoinTableBaseSpeedUnits = esriNetworkAttributeUnits.esriNAUKilometersPerHour;
                    }
                }
                else
                {
                    histTraff.JoinTableBaseSpeedFieldName = "KPH";
                    histTraff.JoinTableBaseSpeedUnits = esriNetworkAttributeUnits.esriNAUKilometersPerHour;
                }
                IStringArray fieldNames = new NamesClass();
                fieldNames.Add("PROFILE_1");
                fieldNames.Add("PROFILE_2");
                fieldNames.Add("PROFILE_3");
                fieldNames.Add("PROFILE_4");
                fieldNames.Add("PROFILE_5");
                fieldNames.Add("PROFILE_6");
                fieldNames.Add("PROFILE_7");
                histTraff.JoinTableProfileIDFieldNames = fieldNames;

                // If a traffic feed location was provided, populate the dynamic traffic settings.
                if (trafficFeedLocation != null)
                {
                    var dynTraff = traffData as IDynamicTrafficData;
                    dynTraff.DynamicTrafficTableName = TMCJoinTableName;
                    dynTraff.DynamicTrafficTMCFieldName = "TMC";
                    dynTraff.TrafficFeedLocation = trafficFeedLocation;
                }

                // Add the traffic data to the network dataset data element.
                deNetworkDataset.TrafficData = (ITrafficData)traffData;
            }

            //
            // Add network attributes
            //

            IArray attributeArray = new ArrayClass();

            // Initialize variables reused when creating attributes:
            IEvaluatedNetworkAttribute evalNetAttr;
            INetworkAttribute2 netAttr2;
            INetworkFieldEvaluator netFieldEval;
            INetworkConstantEvaluator netConstEval;

            if (usesRSTable)
            {
                // Add the vehicle-specific network attributes

                evalNetAttr = CreateRSRestrictionAttribute("All Vehicles Restricted", "AllVehicles_Restricted",
                                                           true, fgdbVersion, edgeNetworkSource, turnNetworkSource);
                attributeArray.Add(evalNetAttr);

                evalNetAttr = CreateRSRestrictionAttribute("Driving a Passenger Car", "PassengerCars_Restricted",
                                                           true, fgdbVersion, edgeNetworkSource, turnNetworkSource);
                attributeArray.Add(evalNetAttr);

                evalNetAttr = CreateRSRestrictionAttribute("Driving a Residential Vehicle", "ResidentialVehicles_Restricted",
                                                           false, fgdbVersion, edgeNetworkSource, turnNetworkSource);
                attributeArray.Add(evalNetAttr);

                evalNetAttr = CreateRSRestrictionAttribute("Driving a Taxi", "Taxis_Restricted",
                                                           false, fgdbVersion, edgeNetworkSource, turnNetworkSource);
                attributeArray.Add(evalNetAttr);

                evalNetAttr = CreateRSRestrictionAttribute("Driving a Public Bus", "PublicBuses_Restricted",
                                                           false, fgdbVersion, edgeNetworkSource, turnNetworkSource);
                attributeArray.Add(evalNetAttr);
            }
            else
            {
                // Otherwise, add the generic Oneway and RestrictedTurns restriction attributes

                //
                // Oneway network attribute
                //

                // Create an EvaluatedNetworkAttribute object and populate its settings.
                evalNetAttr = CreateRestrAttrNoEvals("Oneway", fgdbVersion, -1, true, "");

                // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("restricted", "restricted = False\n\r" +
                                           "Select Case UCase([ONEWAY])\n\r" +
                                           "  Case \"N\", \"TF\", \"T\": restricted = True\n\r" +
                                           "End Select");
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("restricted", "restricted = False\n\r" +
                                           "Select Case UCase([ONEWAY])\n\r" +
                                           "  Case \"N\", \"FT\", \"F\": restricted = True\n\r" +
                                           "End Select");
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = false; // False = traversable.
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = false; // False = traversable.
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = false; // False = traversable.
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

                // Add the attribute to the array.
                attributeArray.Add(evalNetAttr);

                //
                // RestrictedTurns network attribute
                //

                // Create an EvaluatedNetworkAttribute object and populate its settings.
                evalNetAttr = CreateRestrAttrNoEvals("RestrictedTurns", fgdbVersion, -1, true, "");

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = true;
                evalNetAttr.set_Evaluator(turnNetworkSource, esriNetworkEdgeDirection.esriNEDNone, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = false;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = false;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = false;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

                // Add the attribute to the array.
                attributeArray.Add(evalNetAttr);
            }

            //
            // Minutes attribute
            //

            // Create an EvaluatedNetworkAttribute object and populate its settings.
            evalNetAttr = new EvaluatedNetworkAttributeClass();
            netAttr2 = (INetworkAttribute2)evalNetAttr;
            netAttr2.Name = "Minutes";
            netAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTCost;
            netAttr2.DataType = esriNetworkAttributeDataType.esriNADTDouble;
            netAttr2.Units = esriNetworkAttributeUnits.esriNAUMinutes;
            netAttr2.UseByDefault = !(usesHistoricalTraffic || (trafficFeedLocation != null));

            // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
            netFieldEval = new NetworkFieldEvaluatorClass();
            netFieldEval.SetExpression("[MINUTES]", "");
            evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

            netFieldEval = new NetworkFieldEvaluatorClass();
            netFieldEval.SetExpression("[MINUTES]", "");
            evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

            // Add the attribute to the array.
            attributeArray.Add(evalNetAttr);

            //
            // Length network attribute(s)
            //

            if (createTwoDistanceAttributes || createNetworkAttributesInMetric)
            {
                evalNetAttr = CreateLengthNetworkAttribute("Kilometers", esriNetworkAttributeUnits.esriNAUKilometers,
                                                           "[METERS] / 1000", edgeNetworkSource);
                // Add the attribute to the array.
                attributeArray.Add(evalNetAttr);
            }
            if (createTwoDistanceAttributes || !createNetworkAttributesInMetric)
            {
                evalNetAttr = CreateLengthNetworkAttribute("Miles", esriNetworkAttributeUnits.esriNAUMiles,
                                                           "[METERS] / 1609.344", edgeNetworkSource);
                // Add the attribute to the array.
                attributeArray.Add(evalNetAttr);
            }

            //
            // Avoid-type network attributes
            //

            evalNetAttr = CreateAvoidNetworkAttribute("Avoid Ferries", "[FEATTYP] = 4130",
                                                      false, fgdbVersion, AvoidMediumFactor, edgeNetworkSource);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateAvoidNetworkAttribute("Avoid Limited Access Roads", "[FOW] = 1 OR [FREEWAY] = 1",
                                                      false, fgdbVersion, AvoidMediumFactor, edgeNetworkSource);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateAvoidNetworkAttribute("Avoid Service Roads", "[FOW] = 11",
                                                      true, fgdbVersion, AvoidMediumFactor, edgeNetworkSource);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateAvoidNetworkAttribute("Avoid Pedestrian Zones", "[FOW] = 14",
                                                      true, fgdbVersion, -1, edgeNetworkSource);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateAvoidNetworkAttribute("Avoid Walkways", "[FOW] = 15",
                                                      true, fgdbVersion, -1, edgeNetworkSource);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateAvoidNetworkAttribute("Avoid Roads for Authorities", "[FOW] = 20",
                                                      true, fgdbVersion, -1, edgeNetworkSource);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateAvoidNetworkAttribute("Avoid Back Roads", "[BACKRD] = 1",
                                                      false, fgdbVersion, AvoidMediumFactor, edgeNetworkSource);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateAvoidTollRoadsNetworkAttribute("Avoid Toll Roads", "TOLLRD",
                                                               false, fgdbVersion, AvoidMediumFactor, edgeNetworkSource);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateAvoidNetworkAttribute("Avoid Unpaved Roads", "[RDCOND] = 2",
                                                      false, fgdbVersion, AvoidMediumFactor, edgeNetworkSource);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateAvoidNetworkAttribute("Avoid Roads in Poor Condition", "[RDCOND] = 3",
                                                      false, fgdbVersion, AvoidMediumFactor, edgeNetworkSource);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateAvoidNetworkAttribute("Avoid Private Roads", "[PRIVATERD] > 0",
                                                      true, fgdbVersion, AvoidMediumFactor, edgeNetworkSource);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateDirectionalAvoidNetworkAttribute("Avoid Roads Under Construction", "CONSTATUS",
                                                                 true, fgdbVersion, -1, edgeNetworkSource);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateAvoidNetworkAttribute("Through Traffic Prohibited", "[NTHRUTRAF] = 1",
                                                      (fgdbVersion >= 10.1), fgdbVersion, AvoidHighFactor, edgeNetworkSource);
            attributeArray.Add(evalNetAttr);

            evalNetAttr = CreateAvoidNetworkAttribute("Avoid Four Wheel Drive Only Roads", "[ROUGHRD] = 1",
                                                      false, fgdbVersion, AvoidMediumFactor, edgeNetworkSource);
            attributeArray.Add(evalNetAttr);

            //
            // RoadClass network attribute
            //

            // Create an EvaluatedNetworkAttribute object and populate its settings.
            evalNetAttr = new EvaluatedNetworkAttributeClass();
            netAttr2 = (INetworkAttribute2)evalNetAttr;
            netAttr2.Name = "RoadClass";
            netAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTDescriptor;
            netAttr2.DataType = esriNetworkAttributeDataType.esriNADTInteger;
            netAttr2.Units = esriNetworkAttributeUnits.esriNAUUnknown;
            netAttr2.UseByDefault = false;

            // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
            string roadClassExpression = "rc = 1          'Local road\n\r" +
                                         "If [FEATTYP] = 4130 Then\n\r" +
                                         "  rc = 4          'Ferry\n\r" +
                                         "Else\n\r" +
                                         "  Select Case [FOW]\n\r" +
                                         "    Case 1: rc = 2          'Highway\n\r" +
                                         "    Case 10: rc = 3          'Ramp\n\r" +
                                         "    Case 4: rc = 5          'Roundabout\n\r" +
                                         "  End Select\n\r" +
                                         "End If";

            netFieldEval = new NetworkFieldEvaluatorClass();
            netFieldEval.SetExpression("rc", roadClassExpression);
            evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

            netFieldEval = new NetworkFieldEvaluatorClass();
            netFieldEval.SetExpression("rc", roadClassExpression);
            evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

            // Add the attribute to the array.
            attributeArray.Add(evalNetAttr);

            if (fgdbVersion >= 10.1)
            {
                //
                // ManeuverClass network attribute
                //

                // Create an EvaluatedNetworkAttribute object and populate its settings.
                evalNetAttr = new EvaluatedNetworkAttributeClass();
                netAttr2 = (INetworkAttribute2)evalNetAttr;
                netAttr2.Name = "ManeuverClass";
                netAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTDescriptor;
                netAttr2.DataType = esriNetworkAttributeDataType.esriNADTInteger;
                netAttr2.Units = esriNetworkAttributeUnits.esriNAUUnknown;
                netAttr2.UseByDefault = false;

                // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                string maneuverClassExpression = "mc = 0          'Default\n\r" +
                                                 "Select Case [PJ]\n\r" +
                                                 "  Case 1: mc = 1          'Intersection Internal\n\r" +
                                                 "  Case 3: mc = 2          'Maneuver\n\r" +
                                                 "End Select";

                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("mc", maneuverClassExpression);
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized,
                                          (INetworkEvaluator)netFieldEval);

                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("mc", maneuverClassExpression);
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized,
                                          (INetworkEvaluator)netFieldEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge,
                                                 (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction,
                                                 (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn,
                                                 (INetworkEvaluator)netConstEval);

                // Add the attribute to the array.
                attributeArray.Add(evalNetAttr);
            }

            if (usesHistoricalTraffic)
            {
                //
                // WeekdayFallbackTravelTime network attribute
                //

                // Create an EvaluatedNetworkAttribute object and populate its settings.
                evalNetAttr = new EvaluatedNetworkAttributeClass();
                netAttr2 = (INetworkAttribute2)evalNetAttr;
                netAttr2.Name = "WeekdayFallbackTravelTime";
                netAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTCost;
                netAttr2.DataType = esriNetworkAttributeDataType.esriNADTDouble;
                netAttr2.Units = esriNetworkAttributeUnits.esriNAUMinutes;
                netAttr2.UseByDefault = false;

                // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("[FT_WeekdayMinutes]", "");
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("[TF_WeekdayMinutes]", "");
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

                // Add the attribute to the array.
                attributeArray.Add(evalNetAttr);

                //
                // WeekendFallbackTravelTime network attribute
                //

                // Create an EvaluatedNetworkAttribute object and populate its settings.
                evalNetAttr = new EvaluatedNetworkAttributeClass();
                netAttr2 = (INetworkAttribute2)evalNetAttr;
                netAttr2.Name = "WeekendFallbackTravelTime";
                netAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTCost;
                netAttr2.DataType = esriNetworkAttributeDataType.esriNADTDouble;
                netAttr2.Units = esriNetworkAttributeUnits.esriNAUMinutes;
                netAttr2.UseByDefault = false;

                // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("[FT_WeekendMinutes]", "");
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("[TF_WeekendMinutes]", "");
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

                // Add the attribute to the array.
                attributeArray.Add(evalNetAttr);

                //
                // AverageTravelTime network attribute
                //

                // Create an EvaluatedNetworkAttribute object and populate its settings.
                evalNetAttr = new EvaluatedNetworkAttributeClass();
                netAttr2 = (INetworkAttribute2)evalNetAttr;
                netAttr2.Name = "AverageTravelTime";
                netAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTCost;
                netAttr2.DataType = esriNetworkAttributeDataType.esriNADTDouble;
                netAttr2.Units = esriNetworkAttributeUnits.esriNAUMinutes;
                netAttr2.UseByDefault = false;

                // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("[FT_AllWeekMinutes]", "");
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("[TF_AllWeekMinutes]", "");
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

                // Add the attribute to the array.
                attributeArray.Add(evalNetAttr);

                //
                // TravelTime network attribute
                //

                // Create an EvaluatedNetworkAttribute object and populate its settings.
                evalNetAttr = new EvaluatedNetworkAttributeClass();
                netAttr2 = (INetworkAttribute2)evalNetAttr;
                netAttr2.Name = "TravelTime";
                netAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTCost;
                netAttr2.DataType = esriNetworkAttributeDataType.esriNADTDouble;
                netAttr2.Units = esriNetworkAttributeUnits.esriNAUMinutes;
                netAttr2.UseByDefault = true;

                // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                IHistoricalTravelTimeEvaluator histTravelTimeEval = new NetworkEdgeTrafficEvaluatorClass();
                histTravelTimeEval.WeekdayFallbackAttributeName = "WeekdayFallbackTravelTime";
                histTravelTimeEval.WeekendFallbackAttributeName = "WeekendFallbackTravelTime";
                histTravelTimeEval.TimeNeutralAttributeName = "AverageTravelTime";
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)histTravelTimeEval);

                histTravelTimeEval = new NetworkEdgeTrafficEvaluatorClass();
                histTravelTimeEval.WeekdayFallbackAttributeName = "WeekdayFallbackTravelTime";
                histTravelTimeEval.WeekendFallbackAttributeName = "WeekendFallbackTravelTime";
                histTravelTimeEval.TimeNeutralAttributeName = "AverageTravelTime";
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)histTravelTimeEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

                // Add the attribute to the array.
                attributeArray.Add(evalNetAttr);
            }
            else if (trafficFeedLocation != null)
            {
                //
                // TravelTime network attribute
                //

                // Create an EvaluatedNetworkAttribute object and populate its settings.
                evalNetAttr = new EvaluatedNetworkAttributeClass();
                netAttr2 = (INetworkAttribute2)evalNetAttr;
                netAttr2.Name = "TravelTime";
                netAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTCost;
                netAttr2.DataType = esriNetworkAttributeDataType.esriNADTDouble;
                netAttr2.Units = esriNetworkAttributeUnits.esriNAUMinutes;
                netAttr2.UseByDefault = true;

                // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                IHistoricalTravelTimeEvaluator histTravelTimeEval = new NetworkEdgeTrafficEvaluatorClass();
                histTravelTimeEval.WeekdayFallbackAttributeName = "Minutes";
                histTravelTimeEval.WeekendFallbackAttributeName = "Minutes";
                histTravelTimeEval.TimeNeutralAttributeName = "Minutes";
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)histTravelTimeEval);

                histTravelTimeEval = new NetworkEdgeTrafficEvaluatorClass();
                histTravelTimeEval.WeekdayFallbackAttributeName = "Minutes";
                histTravelTimeEval.WeekendFallbackAttributeName = "Minutes";
                histTravelTimeEval.TimeNeutralAttributeName = "Minutes";
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)histTravelTimeEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

                // Add the attribute to the array.
                attributeArray.Add(evalNetAttr);
            }

            //
            // Hierarchy network attribute
            //

            // Create an EvaluatedNetworkAttribute object and populate its settings.
            evalNetAttr = new EvaluatedNetworkAttributeClass();
            netAttr2 = (INetworkAttribute2)evalNetAttr;
            netAttr2.Name = "Hierarchy";
            netAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTHierarchy;
            netAttr2.DataType = esriNetworkAttributeDataType.esriNADTInteger;
            netAttr2.Units = esriNetworkAttributeUnits.esriNAUUnknown;
            netAttr2.UseByDefault = true;

            // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
            string hierarchyExpression = "h = [NET2CLASS] + 1\n\r" +
                                         "If h > 5 Then h = 5";

            netFieldEval = new NetworkFieldEvaluatorClass();
            netFieldEval.SetExpression("h", hierarchyExpression);
            evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

            netFieldEval = new NetworkFieldEvaluatorClass();
            netFieldEval.SetExpression("h", hierarchyExpression);
            evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

            netConstEval = new NetworkConstantEvaluatorClass();
            netConstEval.ConstantValue = 0;
            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

            // Add the attribute to the array.
            attributeArray.Add(evalNetAttr);

            // Since this is the hierarchy attribute, also set it as the hierarchy cluster attribute.
            deNetworkDataset.HierarchyClusterAttribute = (INetworkAttribute)evalNetAttr;

            // Specify the ranges for the hierarchy levels.
            deNetworkDataset.HierarchyLevelCount = 3;
            deNetworkDataset.set_MaxValueForHierarchy(1, 2); // level 1: up to 2
            deNetworkDataset.set_MaxValueForHierarchy(2, 4); // level 2: 3 - 4
            deNetworkDataset.set_MaxValueForHierarchy(3, 5); // level 3: 5 and higher (the values of h only go up to 5)

            //
            // Create and specify the time zone attribute (if applicable)
            //

            if (timeZoneIDBaseFieldName != "" || commonTimeZone != "")
            {
                string timeZoneAttrName = timeZoneIDBaseFieldName;
                if (timeZoneIDBaseFieldName == "")
                {
                    timeZoneAttrName = "TimeZoneID";

                    // Create the time zone table with the common time zone
                    TimeZoneUtilities.CreateTimeZoneTable(outputFileGdbPath, commonTimeZone);
                }

                //
                // TimeZoneID network attribute
                //

                // Create an EvaluatedNetworkAttribute object and populate its settings.
                evalNetAttr = new EvaluatedNetworkAttributeClass();
                netAttr2 = (INetworkAttribute2)evalNetAttr;
                netAttr2.Name = timeZoneAttrName;
                netAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTDescriptor;
                netAttr2.DataType = esriNetworkAttributeDataType.esriNADTInteger;
                netAttr2.Units = esriNetworkAttributeUnits.esriNAUUnknown;
                netAttr2.UseByDefault = false;

                // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                if (timeZoneIDBaseFieldName == "")
                {
                    netConstEval = new NetworkConstantEvaluatorClass();
                    netConstEval.ConstantValue = 1;
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netConstEval);

                    netConstEval = new NetworkConstantEvaluatorClass();
                    netConstEval.ConstantValue = 1;
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netConstEval);
                }
                else if (directedTimeZoneIDFields)
                {
                    netFieldEval = new NetworkFieldEvaluatorClass();
                    netFieldEval.SetExpression("[FT_" + timeZoneIDBaseFieldName + "]", "");
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                    netFieldEval = new NetworkFieldEvaluatorClass();
                    netFieldEval.SetExpression("[TF_" + timeZoneIDBaseFieldName + "]", "");
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);
                }
                else
                {
                    netFieldEval = new NetworkFieldEvaluatorClass();
                    netFieldEval.SetExpression("[" + timeZoneIDBaseFieldName + "]", "");
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                    netFieldEval = new NetworkFieldEvaluatorClass();
                    netFieldEval.SetExpression("[" + timeZoneIDBaseFieldName + "]", "");
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);
                }

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

                // Set this as the time zone attribute, and specify the time zone table.
                deNetworkDataset.TimeZoneAttributeName = timeZoneAttrName;
                deNetworkDataset.TimeZoneTableName = "TimeZones";

                // Add the attribute to the array.
                attributeArray.Add(evalNetAttr);
            }

            #region Add Logistics Truck Route and Logistics Restrictions network attributes

            //
            // Add Logistics Truck Route network attributes
            //

            if (usesLTRTable)
            {
                if (fgdbVersion >= 10.1)
                {
                    evalNetAttr = CreateLTRRestrictionAttribute("Prefer National Route Access Roads", PreferLowFactor,
                                                                "NationalRouteAccess", fgdbVersion, edgeNetworkSource);
                    attributeArray.Add(evalNetAttr);

                    //
                    // Prefer National (STAA) Route Roads network attribute
                    //

                    // Create an EvaluatedNetworkAttribute object and populate its settings.
                    evalNetAttr = CreateRestrAttrNoEvals("Prefer National (STAA) Route Roads", fgdbVersion, PreferMediumFactor, false, "");

                    // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                    netFieldEval = new NetworkFieldEvaluatorClass();
                    netFieldEval.SetExpression("[NationalSTAARoute] = \"Y\"", "");
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                    netFieldEval = new NetworkFieldEvaluatorClass();
                    netFieldEval.SetExpression("[NationalSTAARoute] = \"Y\"", "");
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);

                    netConstEval = new NetworkConstantEvaluatorClass();
                    netConstEval.ConstantValue = false; // False = traversable.
                    evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

                    netConstEval = new NetworkConstantEvaluatorClass();
                    netConstEval.ConstantValue = false; // False = traversable.
                    evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

                    netConstEval = new NetworkConstantEvaluatorClass();
                    netConstEval.ConstantValue = false; // False = traversable.
                    evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

                    // Add the attribute to the array.
                    attributeArray.Add(evalNetAttr);

                    //
                    // Prefer National (STAA) Route and Locally Designated Truck Route Roads network attribute
                    //

                    // Create an EvaluatedNetworkAttribute object and populate its settings.
                    evalNetAttr = CreateRestrAttrNoEvals("Prefer National (STAA) Route and Locally Designated Truck Route Roads",
                                                         fgdbVersion, PreferMediumFactor, false, "");

                    // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                    netFieldEval = new NetworkFieldEvaluatorClass();
                    netFieldEval.SetExpression("[NationalSTAARoute] = \"Y\" Or [DesignatedTruckRoute] = \"Y\"", "");
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                    netFieldEval = new NetworkFieldEvaluatorClass();
                    netFieldEval.SetExpression("[NationalSTAARoute] = \"Y\" Or [DesignatedTruckRoute] = \"Y\"", "");
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);

                    netConstEval = new NetworkConstantEvaluatorClass();
                    netConstEval.ConstantValue = false; // False = traversable.
                    evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

                    netConstEval = new NetworkConstantEvaluatorClass();
                    netConstEval.ConstantValue = false; // False = traversable.
                    evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

                    netConstEval = new NetworkConstantEvaluatorClass();
                    netConstEval.ConstantValue = false; // False = traversable.
                    evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

                    // Add the attribute to the array.
                    attributeArray.Add(evalNetAttr);

                    //
                    // Prefer National (STAA) Route and Locally Designated Truck Route and Bypass Roads network attribute
                    //

                    // Create an EvaluatedNetworkAttribute object and populate its settings.
                    evalNetAttr = CreateRestrAttrNoEvals("Prefer National (STAA) Route and Locally Designated Truck Route and Bypass Roads",
                                                         fgdbVersion, PreferMediumFactor, false, "");

                    // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                    netFieldEval = new NetworkFieldEvaluatorClass();
                    netFieldEval.SetExpression("[NationalSTAARoute] = \"Y\" Or [DesignatedTruckRoute] = \"Y\" Or [TruckBypassRoad] = \"Y\"", "");
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                    netFieldEval = new NetworkFieldEvaluatorClass();
                    netFieldEval.SetExpression("[NationalSTAARoute] = \"Y\" Or [DesignatedTruckRoute] = \"Y\" Or [TruckBypassRoad] = \"Y\"", "");
                    evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);

                    netConstEval = new NetworkConstantEvaluatorClass();
                    netConstEval.ConstantValue = false; // False = traversable.
                    evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

                    netConstEval = new NetworkConstantEvaluatorClass();
                    netConstEval.ConstantValue = false; // False = traversable.
                    evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

                    netConstEval = new NetworkConstantEvaluatorClass();
                    netConstEval.ConstantValue = false; // False = traversable.
                    evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

                    // Add the attribute to the array.
                    attributeArray.Add(evalNetAttr);
                }

                evalNetAttr = CreateLTRRestrictionAttribute("Prohibit No Commercial Vehicles Roads", -1,
                                                            "NoCommercialVehicles", fgdbVersion, edgeNetworkSource);
                attributeArray.Add(evalNetAttr);

                evalNetAttr = CreateLTRRestrictionAttribute("Avoid Immediate Access Only Roads", AvoidHighFactor,
                                                            "ImmediateAccessOnly", fgdbVersion, edgeNetworkSource);
                attributeArray.Add(evalNetAttr);

                evalNetAttr = CreateLTRRestrictionAttribute("Avoid Trucks Restricted Roads", AvoidMediumFactor,
                                                            "TrucksRestricted", fgdbVersion, edgeNetworkSource);
                attributeArray.Add(evalNetAttr);
            }

            //
            // Add Logistics Restrictions network attributes
            //

            if (usesLRSTable)
            {
                // Open the lrsStatsTable and find the fields we need
                ITable lrsStatsTable = featureWorkspace.OpenTable(lrsStatsTableName);
                int restrTypField = lrsStatsTable.FindField("RESTRTYP");
                int vtField = lrsStatsTable.FindField("VT");
                int restrValField = lrsStatsTable.FindField("RESTRVAL");

                // Loop through the lrsStatsTable
                ICursor cur = lrsStatsTable.Search(null, true);
                IRow statsTableRow = null;
                while ((statsTableRow = cur.NextRow()) != null)
                {
                    // Get the RESTRTYP, VT, and RESTRVAL field values
                    string restrTyp = (string)(statsTableRow.get_Value(restrTypField));
                    short vt = (short)(statsTableRow.get_Value(vtField));
                    short restrVal = (short)(statsTableRow.get_Value(restrValField));

                    // Determine the restriction usage factor
                    double restrictionUsageFactor;
                    switch (restrVal)
                    {
                        case 1:
                            restrictionUsageFactor = -1;
                            break;
                        case 2:
                            restrictionUsageFactor = AvoidHighFactor;
                            break;
                        case 3:
                            restrictionUsageFactor = AvoidMediumFactor;
                            break;
                        case 4:
                            restrictionUsageFactor = PreferMediumFactor;
                            break;
                        default:
                            restrictionUsageFactor = 1.0;
                            break;
                    }

                    // Create new network attribute(s) for this restriction
                    if (restrTyp == null || restrTyp.Trim().Length == 0)
                        continue;
                    switch (restrTyp.Remove(1))
                    {
                        case "!":
                            // Determine attribute and parameter names to be used
                            string limitAttrName = MakeLogisticsLimitAttributeName(restrTyp, vt, restrVal, createNetworkAttributesInMetric);
                            string restrAttrName = MakeLogisticsRestrictionAttributeName(restrTyp, vt, restrVal);
                            string paramName = MakeLogisticsAttributeParameterName(restrTyp, createNetworkAttributesInMetric);

                            //
                            // A "dimensional" limit attribute
                            //

                            // Create an EvaluatedNetworkAttribute object and populate its settings.
                            evalNetAttr = new EvaluatedNetworkAttributeClass();
                            netAttr2 = (INetworkAttribute2)evalNetAttr;
                            netAttr2.Name = limitAttrName;
                            netAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTDescriptor;
                            netAttr2.DataType = esriNetworkAttributeDataType.esriNADTDouble;
                            netAttr2.Units = esriNetworkAttributeUnits.esriNAUUnknown;
                            netAttr2.UseByDefault = false;

                            string conversionExpr = "";
                            if (createNetworkAttributesInMetric)
                            {
                                switch (restrTyp)
                                {
                                    case "!A":
                                    case "!B":
                                    case "!C":
                                    case "!D":
                                    case "!E":
                                    case "!F":
                                        // convert tons to metric tons
                                        conversionExpr = " * 0.90718474";
                                        break;
                                    default:
                                        // convert feet to meters
                                        conversionExpr = " * 0.3048";
                                        break;
                                }
                            }

                            // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                            netFieldEval = new NetworkFieldEvaluatorClass();
                            netFieldEval.SetExpression("[" + MakeLogisticsFieldName(restrTyp, vt, restrVal) + "]" + conversionExpr, "");
                            evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                            netFieldEval = new NetworkFieldEvaluatorClass();
                            netFieldEval.SetExpression("[" + MakeLogisticsFieldName(restrTyp, vt, restrVal) + "]" + conversionExpr, "");
                            evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);

                            netConstEval = new NetworkConstantEvaluatorClass();
                            netConstEval.ConstantValue = 0;
                            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

                            netConstEval = new NetworkConstantEvaluatorClass();
                            netConstEval.ConstantValue = 0;
                            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

                            netConstEval = new NetworkConstantEvaluatorClass();
                            netConstEval.ConstantValue = 0;
                            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

                            // Add the attribute to the array.
                            attributeArray.Add(evalNetAttr);

                            //
                            // A "dimensional" restriction attribute
                            //

                            // Create an EvaluatedNetworkAttribute object and populate its settings.
                            evalNetAttr = CreateRestrAttrNoEvals(restrAttrName, fgdbVersion, restrictionUsageFactor, false, paramName);

                            // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                            INetworkFunctionEvaluator netFuncEval = new NetworkFunctionEvaluatorClass();
                            netFuncEval.FirstArgument = limitAttrName;
                            netFuncEval.Operator = "<";
                            netFuncEval.SecondArgument = paramName;
                            evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFuncEval);

                            netFuncEval = new NetworkFunctionEvaluatorClass();
                            netFuncEval.FirstArgument = limitAttrName;
                            netFuncEval.Operator = "<";
                            netFuncEval.SecondArgument = paramName;
                            evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFuncEval);

                            netConstEval = new NetworkConstantEvaluatorClass();
                            netConstEval.ConstantValue = 0;
                            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

                            netConstEval = new NetworkConstantEvaluatorClass();
                            netConstEval.ConstantValue = 0;
                            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

                            netConstEval = new NetworkConstantEvaluatorClass();
                            netConstEval.ConstantValue = 0;
                            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

                            // Add the attribute to the array.
                            attributeArray.Add(evalNetAttr);
                            break;
                        case "@":
                            //
                            // A "load" restriction attribute
                            //

                            // Create an EvaluatedNetworkAttribute object and populate its settings.
                            evalNetAttr = CreateRestrAttrNoEvals(MakeLogisticsRestrictionAttributeName(restrTyp, vt, restrVal),
                                                                 fgdbVersion, restrictionUsageFactor, false, "");

                            // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                            netFieldEval = new NetworkFieldEvaluatorClass();
                            netFieldEval.SetExpression("[" + MakeLogisticsFieldName(restrTyp, vt, restrVal) + "] = \"Y\"", "");
                            evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                            netFieldEval = new NetworkFieldEvaluatorClass();
                            netFieldEval.SetExpression("[" + MakeLogisticsFieldName(restrTyp, vt, restrVal) + "] = \"Y\"", "");
                            evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);

                            netConstEval = new NetworkConstantEvaluatorClass();
                            netConstEval.ConstantValue = 0;
                            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

                            netConstEval = new NetworkConstantEvaluatorClass();
                            netConstEval.ConstantValue = 0;
                            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

                            netConstEval = new NetworkConstantEvaluatorClass();
                            netConstEval.ConstantValue = 0;
                            evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

                            // Add the attribute to the array.
                            attributeArray.Add(evalNetAttr);
                            break;
                        default:
                            continue;    // Only process dimensional (!_) and load (@_) restrictions
                    }
                }

                //
                // TruckTravelTime attribute
                //

                // Create an EvaluatedNetworkAttribute object and populate its settings.
                evalNetAttr = new EvaluatedNetworkAttributeClass();
                netAttr2 = (INetworkAttribute2)evalNetAttr;
                netAttr2.Name = "TruckTravelTime";
                netAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTCost;
                netAttr2.DataType = esriNetworkAttributeDataType.esriNADTDouble;
                netAttr2.Units = esriNetworkAttributeUnits.esriNAUMinutes;
                netAttr2.UseByDefault = false;

                string truckSpeedExpression = "sp = [RecommendedSpeed_KPH_AllTrucks]\n" +
                                              "If IsNull(sp) Then sp = [MaximumSpeed_KPH_AllTrucks]\n" +
                                              "If IsNull(sp) Then sp = [KPH]\n" +
                                              "If sp > [KPH] Then sp = [KPH]";

                // Create evaluator objects and set them on the EvaluatedNetworkAttribute object.
                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("[METERS] * 0.06 / sp", truckSpeedExpression);
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)netFieldEval);

                netFieldEval = new NetworkFieldEvaluatorClass();
                netFieldEval.SetExpression("[METERS] * 0.06 / sp", truckSpeedExpression);
                evalNetAttr.set_Evaluator(edgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)netFieldEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, (INetworkEvaluator)netConstEval);

                netConstEval = new NetworkConstantEvaluatorClass();
                netConstEval.ConstantValue = 0;
                evalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, (INetworkEvaluator)netConstEval);

                // Add the attribute to the array.
                attributeArray.Add(evalNetAttr);
            }
            #endregion

            //
            // Add all attributes to the data element
            //

            deNetworkDataset.Attributes = attributeArray;

            if (fgdbVersion >= 10.1)
            {
                //
                // Add travel modes
                //

                IArray travelModeArray = new ArrayClass();

                // Initialize variables reused when creating travel modes:
                INetworkTravelMode2 travelMode;
                string timeAttributeName;
                string distanceAttributeName;
                IStringArray restrictionsArray;
                IArray paramValuesArray;
                INetworkTravelModeParameterValue tmParamValue;

                //
                // Driving Time travel mode
                //

                // Create a NetworkTravelMode object and populate its settings.
                travelMode = new NetworkTravelModeClass();
                travelMode.Name = "Driving Time";
                timeAttributeName = (usesHistoricalTraffic ? "TravelTime" : "Minutes");
                distanceAttributeName = (createNetworkAttributesInMetric ? "Kilometers" : "Miles");
                travelMode.ImpedanceAttributeName = timeAttributeName;
                travelMode.TimeAttributeName = timeAttributeName;
                travelMode.DistanceAttributeName = distanceAttributeName;
                travelMode.UseHierarchy = true;
                travelMode.RestrictUTurns = esriNetworkForwardStarBacktrack.esriNFSBAtDeadEndsAndIntersections;
                travelMode.OutputGeometryPrecision = 10;
                travelMode.OutputGeometryPrecisionUnits = esriUnits.esriMeters;
                travelMode.Type = "AUTOMOBILE";
                travelMode.Description = "Models the movement of cars and other similar small automobiles, such as pickup trucks, and finds solutions that optimize travel time. " +
                                         "Travel obeys one-way roads, avoids illegal turns, and follows other rules that are specific to cars. " +
                                         "Dynamic travel speeds based on traffic are used where it is available when you specify a start time.";

                // Populate the restriction attributes to use.
                restrictionsArray = new StrArrayClass();
                if (usesRSTable)
                {
                    restrictionsArray.Add("All Vehicles Restricted");
                    restrictionsArray.Add("Driving a Passenger Car");
                }
                else
                {
                    restrictionsArray.Add("Oneway");
                    restrictionsArray.Add("RestrictedTurns");
                }
                restrictionsArray.Add("Avoid Service Roads");
                restrictionsArray.Add("Avoid Pedestrian Zones");
                restrictionsArray.Add("Avoid Walkways");
                restrictionsArray.Add("Avoid Roads for Authorities");
                restrictionsArray.Add("Avoid Private Roads");
                restrictionsArray.Add("Avoid Roads Under Construction");
                restrictionsArray.Add("Through Traffic Prohibited");
                travelMode.RestrictionAttributeNames = restrictionsArray;

                // Add the travel mode to the array.
                travelModeArray.Add(travelMode);

                //
                // Driving Distance travel mode
                //

                // Create a NetworkTravelMode object and populate its settings.
                travelMode = new NetworkTravelModeClass();
                travelMode.Name = "Driving Distance";
                timeAttributeName = (usesHistoricalTraffic ? "TravelTime" : "Minutes");
                distanceAttributeName = (createNetworkAttributesInMetric ? "Kilometers" : "Miles");
                travelMode.ImpedanceAttributeName = distanceAttributeName;
                travelMode.TimeAttributeName = timeAttributeName;
                travelMode.DistanceAttributeName = distanceAttributeName;
                travelMode.UseHierarchy = true;
                travelMode.RestrictUTurns = esriNetworkForwardStarBacktrack.esriNFSBAtDeadEndsAndIntersections;
                travelMode.OutputGeometryPrecision = 10;
                travelMode.OutputGeometryPrecisionUnits = esriUnits.esriMeters;
                travelMode.Type = "AUTOMOBILE";
                travelMode.Description = "Models the movement of cars and other similar small automobiles, such as pickup trucks, and finds solutions that optimize travel distance. " +
                                         "Travel obeys one-way roads, avoids illegal turns, and follows other rules that are specific to cars.";

                // Populate the restriction attributes to use.
                restrictionsArray = new StrArrayClass();
                if (usesRSTable)
                {
                    restrictionsArray.Add("All Vehicles Restricted");
                    restrictionsArray.Add("Driving a Passenger Car");
                }
                else
                {
                    restrictionsArray.Add("Oneway");
                    restrictionsArray.Add("RestrictedTurns");
                }
                restrictionsArray.Add("Avoid Service Roads");
                restrictionsArray.Add("Avoid Pedestrian Zones");
                restrictionsArray.Add("Avoid Walkways");
                restrictionsArray.Add("Avoid Roads for Authorities");
                restrictionsArray.Add("Avoid Private Roads");
                restrictionsArray.Add("Avoid Roads Under Construction");
                restrictionsArray.Add("Through Traffic Prohibited");

                travelMode.RestrictionAttributeNames = restrictionsArray;

                // Add the travel mode to the array.
                travelModeArray.Add(travelMode);

                if (usesLTRTable)
                {
                    //
                    // Trucking Time travel mode
                    //

                    // Create a NetworkTravelMode object and populate its settings.
                    travelMode = new NetworkTravelModeClass();
                    travelMode.Name = "Trucking Time";
                    timeAttributeName = "TruckTravelTime";
                    distanceAttributeName = (createNetworkAttributesInMetric ? "Kilometers" : "Miles");
                    travelMode.ImpedanceAttributeName = timeAttributeName;
                    travelMode.TimeAttributeName = timeAttributeName;
                    travelMode.DistanceAttributeName = distanceAttributeName;
                    travelMode.UseHierarchy = true;
                    travelMode.RestrictUTurns = esriNetworkForwardStarBacktrack.esriNFSBNoBacktrack;
                    travelMode.OutputGeometryPrecision = 10;
                    travelMode.OutputGeometryPrecisionUnits = esriUnits.esriMeters;
                    travelMode.Type = "TRUCK";
                    travelMode.Description = "Models basic truck travel by preferring designated truck routes, and finds solutions that optimize travel time. " +
                                             "Routes must obey one-way roads, avoid illegal turns, and so on.";

                    // Populate attribute parameter values to use.
                    paramValuesArray = new ArrayClass();
                    tmParamValue = new NetworkTravelModeParameterValueClass();
                    tmParamValue.AttributeName = "Prefer National (STAA) Route and Locally Designated Truck Route and Bypass Roads";
                    tmParamValue.ParameterName = "Restriction Usage";
                    tmParamValue.Value = PreferHighFactor;
                    paramValuesArray.Add(tmParamValue);

                    // Populate the restriction attributes to use.
                    restrictionsArray = new StrArrayClass();
                    if (usesRSTable)
                    {
                        restrictionsArray.Add("All Vehicles Restricted");
                    }
                    else
                    {
                        restrictionsArray.Add("Oneway");
                        restrictionsArray.Add("RestrictedTurns");
                    }
                    restrictionsArray.Add("Avoid Service Roads");
                    restrictionsArray.Add("Avoid Pedestrian Zones");
                    restrictionsArray.Add("Avoid Walkways");
                    restrictionsArray.Add("Avoid Roads for Authorities");
                    restrictionsArray.Add("Avoid Private Roads");
                    restrictionsArray.Add("Avoid Roads Under Construction");
                    restrictionsArray.Add("Through Traffic Prohibited");
                    restrictionsArray.Add("Prefer National (STAA) Route and Locally Designated Truck Route and Bypass Roads");
                    restrictionsArray.Add("Prohibit No Commercial Vehicles Roads");
                    restrictionsArray.Add("Avoid Immediate Access Only Roads");
                    restrictionsArray.Add("Avoid Trucks Restricted Roads");

                    travelMode.RestrictionAttributeNames = restrictionsArray;
                    travelMode.AttributeParameterValues = paramValuesArray;

                    // Add the travel mode to the array.
                    travelModeArray.Add(travelMode);

                    //
                    // Trucking Distance travel mode
                    //

                    // Create a NetworkTravelMode object and populate its settings.
                    travelMode = new NetworkTravelModeClass();
                    travelMode.Name = "Trucking Distance";
                    timeAttributeName = "TruckTravelTime";
                    distanceAttributeName = (createNetworkAttributesInMetric ? "Kilometers" : "Miles");
                    travelMode.ImpedanceAttributeName = distanceAttributeName;
                    travelMode.TimeAttributeName = timeAttributeName;
                    travelMode.DistanceAttributeName = distanceAttributeName;
                    travelMode.UseHierarchy = true;
                    travelMode.RestrictUTurns = esriNetworkForwardStarBacktrack.esriNFSBNoBacktrack;
                    travelMode.OutputGeometryPrecision = 10;
                    travelMode.OutputGeometryPrecisionUnits = esriUnits.esriMeters;
                    travelMode.Type = "TRUCK";
                    travelMode.Description = "Models basic truck travel by preferring designated truck routes, and finds solutions that optimize travel distance. " +
                                             "Routes must obey one-way roads, avoid illegal turns, and so on.";

                    // Populate attribute parameter values to use.
                    paramValuesArray = new ArrayClass();
                    tmParamValue = new NetworkTravelModeParameterValueClass();
                    tmParamValue.AttributeName = "Prefer National (STAA) Route and Locally Designated Truck Route and Bypass Roads";
                    tmParamValue.ParameterName = "Restriction Usage";
                    tmParamValue.Value = PreferHighFactor;
                    paramValuesArray.Add(tmParamValue);

                    // Populate the restriction attributes to use.
                    restrictionsArray = new StrArrayClass();
                    if (usesRSTable)
                    {
                        restrictionsArray.Add("All Vehicles Restricted");
                    }
                    else
                    {
                        restrictionsArray.Add("Oneway");
                        restrictionsArray.Add("RestrictedTurns");
                    }
                    restrictionsArray.Add("Avoid Service Roads");
                    restrictionsArray.Add("Avoid Pedestrian Zones");
                    restrictionsArray.Add("Avoid Walkways");
                    restrictionsArray.Add("Avoid Roads for Authorities");
                    restrictionsArray.Add("Avoid Private Roads");
                    restrictionsArray.Add("Avoid Roads Under Construction");
                    restrictionsArray.Add("Through Traffic Prohibited");
                    restrictionsArray.Add("Prefer National (STAA) Route and Locally Designated Truck Route and Bypass Roads");
                    restrictionsArray.Add("Prohibit No Commercial Vehicles Roads");
                    restrictionsArray.Add("Avoid Immediate Access Only Roads");
                    restrictionsArray.Add("Avoid Trucks Restricted Roads");

                    travelMode.RestrictionAttributeNames = restrictionsArray;
                    travelMode.AttributeParameterValues = paramValuesArray;

                    // Add the travel mode to the array.
                    travelModeArray.Add(travelMode);
                }

                //
                // Add all travel modes to the data element
                //

                deNetworkDataset.TravelModes = travelModeArray;
            }

            //
            // Specify directions settings
            //

            // Create a NetworkDirections object and populate its settings.
            INetworkDirections networkDirections = new NetworkDirectionsClass();
            networkDirections.DefaultOutputLengthUnits = createNetworkAttributesInMetric ? esriNetworkAttributeUnits.esriNAUKilometers : esriNetworkAttributeUnits.esriNAUMiles;
            networkDirections.LengthAttributeName = createNetworkAttributesInMetric ? "Kilometers" : "Miles";
            networkDirections.TimeAttributeName = "Minutes";
            networkDirections.RoadClassAttributeName = "RoadClass";
            var netDirSignposts = (ISignposts)networkDirections;
            netDirSignposts.SignpostFeatureClassName = SignpostFCName;
            netDirSignposts.SignpostStreetsTableName = SignpostJoinTableName;

            if (fgdbVersion >= 10.1)
            {
                // Specify the RoadSplits table.
                var netDirRoadSplits = (IRoadSplits)networkDirections;
                netDirRoadSplits.RoadSplitsTableName = RoadSplitsTableName;

                // Create a DirectionsAttributeMapping object for the ManeuverClass mapping.
                IDirectionsAttributeMapping dirAttrMapping = new DirectionsAttributeMappingClass();
                dirAttrMapping.KeyName = "ManeuverClass";
                dirAttrMapping.AttributeName = "ManeuverClass";

                // Wrap the DirectionsAttributeMapping object in an Array and add it to the NetworkDirections object.
                IArray damArray = new ArrayClass();
                damArray.Add(dirAttrMapping);
                var networkDirections2 = (INetworkDirections2)networkDirections;
                networkDirections2.AttributeMappings = damArray;
            }

            // Add the NetworkDirections object to the network dataset data element.
            deNetworkDataset.Directions = networkDirections;

            //
            // Create and build the network dataset
            //

            // Get the feature dataset extension and create the network dataset based on the data element.
            var fdxContainer = (IFeatureDatasetExtensionContainer)featureDataset;
            IFeatureDatasetExtension fdExtension = fdxContainer.FindExtension(esriDatasetType.esriDTNetworkDataset);
            var datasetContainer2 = (IDatasetContainer2)fdExtension;
            var deDataset = (IDEDataset)deNetworkDataset;
            var networkDataset = (INetworkDataset)datasetContainer2.CreateDataset(deDataset);

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

            return;
        }