Ejemplo n.º 1
0
        /// <summary>Creates an new (unbuilt) Network Dataset</summary>
        private void CreateBuildableNDS()
        {
            IDENetworkDataset2 deNetworkDataset = new DENetworkDatasetClass();

            deNetworkDataset.Buildable = true;

            ((IDataElement)deNetworkDataset).Name = _ndsName;

            // Copy the feature dataset's extent and spatial reference to the network dataset
            IDEGeoDataset deGeoDataset = (IDEGeoDataset)deNetworkDataset;

            deGeoDataset.Extent           = _extent;
            deGeoDataset.SpatialReference = _spatialReference;

            deNetworkDataset.ElevationModel = esriNetworkElevationModel.esriNEMNone;
            deNetworkDataset.SupportsTurns  = true;

            // General Network Directions
            GeneralNetworkDirectionInfo dirInfo = _xml.GeneralNetworkDirections();

            if (dirInfo != null)
            {
                INetworkDirections netdir = new NetworkDirectionsClass();
                netdir.LengthAttributeName      = dirInfo.LengthAttr;
                netdir.DefaultOutputLengthUnits = dirInfo.LengthUnits;
                netdir.RoadClassAttributeName   = dirInfo.RoadClassAttr;
                netdir.TimeAttributeName        = dirInfo.TimeAttr;

                deNetworkDataset.Directions = netdir;
            }

            IArray sources = new ArrayClass();

            foreach (INetworkSource ns in EnumerateNetworkSources())
            {
                sources.Add(ns);
            }

            IArray attrs = new ArrayClass();

            foreach (var na in _networkAttrs)
            {
                attrs.Add(na);
            }

            deNetworkDataset.Sources    = sources;
            deNetworkDataset.Attributes = attrs;

            // Get the feature dataset extension and create the network dataset from the data element.
            IFeatureDatasetExtension fdExtension = ((IFeatureDatasetExtensionContainer)_osmDataset).FindExtension(esriDatasetType.esriDTNetworkDataset);

            _networkDataset = (INetworkDataset)((IDatasetContainer2)fdExtension).CreateDataset((IDEDataset)deNetworkDataset);
        }
Ejemplo n.º 2
0
        /// <summary>Creates a temporary network dataset to use during turn feature creation</summary>
        private INetworkDataset CreateTempNDS()
        {
            const string TEMP_NDS_NAME = "TEMP_TURN_NDS";

            IDENetworkDataset2 deNDS = new DENetworkDatasetClass();

            deNDS.Buildable = true;

            ((IDataElement)deNDS).Name = TEMP_NDS_NAME;

            // Copy the feature dataset's extent and spatial reference to the network dataset
            IDEGeoDataset deGeoDataset = (IDEGeoDataset)deNDS;

            deGeoDataset.Extent           = _extent;
            deGeoDataset.SpatialReference = _spatialReference;

            deNDS.ElevationModel = esriNetworkElevationModel.esriNEMNone;
            deNDS.SupportsTurns  = true;

            IArray sources = new ArrayClass();

            foreach (INetworkSource ns in EnumerateNetworkSources())
            {
                sources.Add(ns);
            }

            deNDS.Sources = sources;

            // Get the feature dataset extension and create the network dataset from the data element.
            IFeatureDatasetExtension fdExtension = ((IFeatureDatasetExtensionContainer)_osmDataset).FindExtension(esriDatasetType.esriDTNetworkDataset);
            INetworkDataset          nds         = (INetworkDataset)((IDatasetContainer2)fdExtension).CreateDataset((IDEDataset)deNDS);

            if (nds == null)
            {
                throw new ArgumentNullException("NetworkDataset");
            }

            return(nds);
        }
        /// <summary>Creates an new (unbuilt) Network Dataset</summary>
        private void CreateBuildableNDS()
        {
            IDENetworkDataset2 deNetworkDataset = new DENetworkDatasetClass();
            deNetworkDataset.Buildable = true;

            ((IDataElement)deNetworkDataset).Name = _ndsName;

            // Copy the feature dataset's extent and spatial reference to the network dataset
            IDEGeoDataset deGeoDataset = (IDEGeoDataset)deNetworkDataset;
            deGeoDataset.Extent = _extent;
            deGeoDataset.SpatialReference = _spatialReference;

            deNetworkDataset.ElevationModel = esriNetworkElevationModel.esriNEMNone;
            deNetworkDataset.SupportsTurns = true;

            // General Network Directions
            GeneralNetworkDirectionInfo dirInfo = _xml.GeneralNetworkDirections();
            if (dirInfo != null)
            {
                INetworkDirections netdir = new NetworkDirectionsClass();
                netdir.LengthAttributeName = dirInfo.LengthAttr;
                netdir.DefaultOutputLengthUnits = dirInfo.LengthUnits;
                netdir.RoadClassAttributeName = dirInfo.RoadClassAttr;
                netdir.TimeAttributeName = dirInfo.TimeAttr;

                deNetworkDataset.Directions = netdir;
            }

            IArray sources = new ArrayClass();
            foreach (INetworkSource ns in EnumerateNetworkSources())
                sources.Add(ns);

            IArray attrs = new ArrayClass();
            foreach (var na in _networkAttrs)
                attrs.Add(na);

            deNetworkDataset.Sources = sources;
            deNetworkDataset.Attributes = attrs;

            // Get the feature dataset extension and create the network dataset from the data element.
            IFeatureDatasetExtension fdExtension = ((IFeatureDatasetExtensionContainer)_osmDataset).FindExtension(esriDatasetType.esriDTNetworkDataset);
            _networkDataset = (INetworkDataset)((IDatasetContainer2)fdExtension).CreateDataset((IDEDataset)deNetworkDataset);
        }
        /// <summary>Creates a temporary network dataset to use during turn feature creation</summary>
        private INetworkDataset CreateTempNDS()
        {
            const string TEMP_NDS_NAME = "TEMP_TURN_NDS";

            IDENetworkDataset2 deNDS = new DENetworkDatasetClass();
            deNDS.Buildable = true;

            ((IDataElement)deNDS).Name = TEMP_NDS_NAME;

            // Copy the feature dataset's extent and spatial reference to the network dataset
            IDEGeoDataset deGeoDataset = (IDEGeoDataset)deNDS;
            deGeoDataset.Extent = _extent;
            deGeoDataset.SpatialReference = _spatialReference;

            deNDS.ElevationModel = esriNetworkElevationModel.esriNEMNone;
            deNDS.SupportsTurns = true;

            IArray sources = new ArrayClass();
            foreach (INetworkSource ns in EnumerateNetworkSources())
                sources.Add(ns);

            deNDS.Sources = sources;

            // Get the feature dataset extension and create the network dataset from the data element.
            IFeatureDatasetExtension fdExtension = ((IFeatureDatasetExtensionContainer)_osmDataset).FindExtension(esriDatasetType.esriDTNetworkDataset);
            INetworkDataset nds = (INetworkDataset)((IDatasetContainer2)fdExtension).CreateDataset((IDEDataset)deNDS);
            if (nds == null)
                throw new ArgumentNullException("NetworkDataset");

            return nds;
        }
        private void CreateAndPopulateTurnFeatureClass(string outputFileGdbPath, string fdsName,
                                                       string ProhibRdmsTableName, string tempStatsTableName,
                                                       IGPMessages messages, ITrackCancel trackcancel)
        {
            // Determine the number of AltID fields we need (one more than the MAX_SEQ_NUMBER value).

            Type factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory");
            var wsf = Activator.CreateInstance(factoryType) as IWorkspaceFactory;
            var fws = wsf.OpenFromFile(outputFileGdbPath, 0) as IFeatureWorkspace;
            ITable tempStatsTable = fws.OpenTable(tempStatsTableName);
            short numAltIDFields = 2;
            if (tempStatsTable.RowCount(null) == 1)
                numAltIDFields = (short)(1 + (double)(tempStatsTable.GetRow(1).get_Value(tempStatsTable.FindField("MAX_SEQ_NUMBER"))));

            // Open the Rdms table and find the fields we need

            ITable rdmsTable = fws.OpenTable(ProhibRdmsTableName);
            int seqNumberField = rdmsTable.FindField("SEQ_NUMBER");
            int linkIDFieldOnRdms = rdmsTable.FindField("LINK_ID");
            int manLinkIDField = rdmsTable.FindField("MAN_LINKID");
            int condIDFieldOnRdms = rdmsTable.FindField("COND_ID");
            int endOfLkFieldOnRdms = rdmsTable.FindField("END_OF_LK");

            // Create a temporary template feature class

            var fcd = new FeatureClassDescriptionClass() as IFeatureClassDescription;
            var ocd = fcd as IObjectClassDescription;
            var fieldsEdit = ocd.RequiredFields as IFieldsEdit;
            IField fieldOnRdmsTable = rdmsTable.Fields.get_Field(linkIDFieldOnRdms);  // use the LINK_ID field as a template for the AltID fields
            for (short i = 1; i <= numAltIDFields; i++)
            {
                IFieldEdit newField = new FieldClass();
                newField.Name_2 = "AltID" + i;
                newField.Precision_2 = fieldOnRdmsTable.Precision;
                newField.Scale_2 = fieldOnRdmsTable.Scale;
                newField.Type_2 = fieldOnRdmsTable.Type;
                fieldsEdit.AddField(newField as IField);
            }
            fieldOnRdmsTable = rdmsTable.Fields.get_Field(condIDFieldOnRdms);
            fieldsEdit.AddField(fieldOnRdmsTable);
            var fieldChk = new FieldCheckerClass() as IFieldChecker;
            IEnumFieldError enumFieldErr = null;
            IFields validatedFields = null;
            fieldChk.ValidateWorkspace = fws as IWorkspace;
            fieldChk.Validate(fieldsEdit as IFields, out enumFieldErr, out validatedFields);
            var tempFC = fws.CreateFeatureClass("TheTemplate", validatedFields, ocd.InstanceCLSID, ocd.ClassExtensionCLSID,
                                                esriFeatureType.esriFTSimple, fcd.ShapeFieldName, "") as IDataset;

            // Create the turn feature class from the template, then delete the template

            Geoprocessor gp = new Geoprocessor();
            CreateTurnFeatureClass createTurnFCTool = new CreateTurnFeatureClass();
            string pathToFds = outputFileGdbPath + "\\" + fdsName;
            createTurnFCTool.out_location = pathToFds;
            createTurnFCTool.out_feature_class_name = TurnFCName;
            createTurnFCTool.maximum_edges = numAltIDFields;
            createTurnFCTool.in_template_feature_class = outputFileGdbPath + "\\TheTemplate";
            gp.Execute(createTurnFCTool, trackcancel);
            tempFC.Delete();

            // Open the new turn feature class and find all the fields on it

            IFeatureClass turnFC = fws.OpenFeatureClass(TurnFCName);
            int[] altIDFields = new int[numAltIDFields];
            int[] edgeFCIDFields = new int[numAltIDFields];
            int[] edgeFIDFields = new int[numAltIDFields];
            int[] edgePosFields = new int[numAltIDFields];
            for (short i = 0; i < numAltIDFields; i++)
            {
                altIDFields[i] = turnFC.FindField("AltID" + (i + 1));
                edgeFCIDFields[i] = turnFC.FindField("Edge" + (i + 1) + "FCID");
                edgeFIDFields[i] = turnFC.FindField("Edge" + (i + 1) + "FID");
                edgePosFields[i] = turnFC.FindField("Edge" + (i + 1) + "Pos");
            }
            int edge1endField = turnFC.FindField("Edge1End");
            int condIDFieldOnTurnFC = turnFC.FindField("COND_ID");

            // Look up the FCID of the Streets feature class

            IFeatureClass streetsFC = fws.OpenFeatureClass(StreetsFCName);
            int streetsFCID = streetsFC.FeatureClassID;

            // Set up queries

            var ts = new TableSortClass() as ITableSort;
            ts.Fields = "COND_ID, SEQ_NUMBER";
            ts.set_Ascending("COND_ID", true);
            ts.set_Ascending("SEQ_NUMBER", true);
            ts.QueryFilter = new QueryFilterClass();
            ts.Table = rdmsTable;
            ts.Sort(null);
            ICursor rdmsCursor = ts.Rows;
            IFeatureCursor turnFCCursor = turnFC.Insert(true);
            IFeatureBuffer turnBuffer = turnFC.CreateFeatureBuffer();

            // Write the field values to the turn feature class accordingly

            int numFeatures = 0;
            IRow rdmsRow = rdmsCursor.NextRow();
            while (rdmsRow != null)
            {
                // Transfer the non-edge identifying field values to the buffer
                turnBuffer.set_Value(condIDFieldOnTurnFC, rdmsRow.get_Value(condIDFieldOnRdms));

                // Write the Edge1End field value to the buffer
                switch ((string)(rdmsRow.get_Value(endOfLkFieldOnRdms)))
                {
                    case "N":
                        turnBuffer.set_Value(edge1endField, "Y");
                        break;
                    case "R":
                        turnBuffer.set_Value(edge1endField, "N");
                        break;
                    default:
                        break;    // not expected
                }

                // Write the AltID values to the buffer
                turnBuffer.set_Value(altIDFields[0], rdmsRow.get_Value(linkIDFieldOnRdms));
                short seq = (short)(rdmsRow.get_Value(seqNumberField));
                short lastEntry;
                do
                {
                    lastEntry = seq;
                    turnBuffer.set_Value(altIDFields[lastEntry], rdmsRow.get_Value(manLinkIDField));
                    rdmsRow = rdmsCursor.NextRow();
                    if (rdmsRow == null) break;
                    seq = (short)(rdmsRow.get_Value(seqNumberField));
                } while (seq != 1);

                // Zero-out the unused fields
                for (int i = lastEntry + 1; i < numAltIDFields; i++)
                    turnBuffer.set_Value(altIDFields[i], 0);

                // Write the FCID and Pos field values to the buffer
                for (short i = 0; i < numAltIDFields; i++)
                {
                    int altID = (int)(turnBuffer.get_Value(altIDFields[i]));
                    if (altID != 0)
                    {
                        turnBuffer.set_Value(edgeFCIDFields[i], streetsFCID);
                        turnBuffer.set_Value(edgeFIDFields[i], 1);
                        turnBuffer.set_Value(edgePosFields[i], 0.5);
                    }
                    else
                    {
                        turnBuffer.set_Value(edgeFCIDFields[i], 0);
                        turnBuffer.set_Value(edgeFIDFields[i], 0);
                        turnBuffer.set_Value(edgePosFields[i], 0);
                    }
                }

                // Create the turn feature
                turnFCCursor.InsertFeature(turnBuffer);
                numFeatures++;

                if ((numFeatures % 100) == 0)
                {
                    // check for user cancel

                    if (trackcancel != null && !trackcancel.Continue())
                        throw (new COMException("Function cancelled."));
                }
            }

            // Flush any outstanding writes to the turn feature class
            turnFCCursor.Flush();

            messages.AddMessage("Updating the EdgeFID values...");

            // Create a temporary network dataset for updating the EdgeFID values

            IDENetworkDataset dends = new DENetworkDatasetClass();
            dends.SupportsTurns = true;
            dends.Buildable = true;
            (dends as IDataElement).Name = StreetsFCName;
            (dends as IDEGeoDataset).SpatialReference = (streetsFC as IGeoDataset).SpatialReference;
            IArray sourceArray = new ArrayClass();
            var efs = new EdgeFeatureSourceClass() as IEdgeFeatureSource;
            (efs as INetworkSource).Name = StreetsFCName;
            efs.UsesSubtypes = false;
            efs.ClassConnectivityGroup = 1;
            efs.ClassConnectivityPolicy = esriNetworkEdgeConnectivityPolicy.esriNECPEndVertex;
            sourceArray.Add(efs);
            var tfs = new TurnFeatureSourceClass() as INetworkSource;
            tfs.Name = TurnFCName;
            sourceArray.Add(tfs);
            dends.Sources = sourceArray;
            var fdxc = fws.OpenFeatureDataset(fdsName) as IFeatureDatasetExtensionContainer;
            var dsCont = fdxc.FindExtension(esriDatasetType.esriDTNetworkDataset) as IDatasetContainer2;
            var tempNDS = dsCont.CreateDataset(dends as IDEDataset) as IDataset;

            // Set the EdgeFID field values by running UpdateByAlternateIDFields

            UpdateByAlternateIDFields updateByAltIDTool = new UpdateByAlternateIDFields();
            updateByAltIDTool.in_network_dataset = pathToFds + "\\" + StreetsFCName;
            updateByAltIDTool.alternate_ID_field_name = "LINK_ID";
            gp.Execute(updateByAltIDTool, trackcancel);

            // Delete the temporary network dataset

            tempNDS.Delete();

            // Write the turn geometries

            TurnGeometryUtilities.WriteTurnGeometry(outputFileGdbPath, StreetsFCName, TurnFCName,
                                                    numAltIDFields, 0.3, messages, trackcancel);

            // Index the turn geometries

            messages.AddMessage("Creating spatial index on the turn feature class...");

            AddSpatialIndex addSpatialIndexTool = new AddSpatialIndex();
            addSpatialIndexTool.in_features = pathToFds + "\\" + TurnFCName;
            gp.Execute(addSpatialIndexTool, trackcancel);

            return;
        }
        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;
        }
Ejemplo n.º 7
0
        private INetworkDataset method_1(IFeatureDataset ifeatureDataset_1, string string_1)
        {
            int               num;
            IGeoDataset       dataset          = (IGeoDataset)ifeatureDataset_1;
            ISpatialReference spatialReference = dataset.SpatialReference;
            IDENetworkDataset dataset2         = new DENetworkDatasetClass();
            IDataElement      element          = (IDataElement)dataset2;
            IDEGeoDataset     dataset3         = (IDEGeoDataset)dataset2;

            element.Name              = string_1;
            dataset2.Buildable        = true;
            dataset3.SpatialReference = spatialReference;
            IArray array = new ArrayClass();

            for (num = 0; num < this.FeatureClassWraps.Count; num++)
            {
                if (this.FeatureClassWraps[num].IsUse)
                {
                    INetworkSource source;
                    IFeatureClass  featureClass = this.FeatureClassWraps[num].FeatureClass;
                    if (featureClass.ShapeType == esriGeometryType.esriGeometryPoint)
                    {
                        source = new JunctionFeatureSourceClass
                        {
                            Name = this.FeatureClassWraps[num].ToString()
                        };
                        IJunctionFeatureSource source2 = (IJunctionFeatureSource)source;
                        source2.ClassConnectivityPolicy =
                            (esriNetworkJunctionConnectivityPolicy)
                            this.FeatureClassWraps[num].NetworkConnectivityPolicy;
                        if (this.ModifyConnectivity)
                        {
                            source2.ElevationFieldName = this.FeatureClassWraps[num].ElevationFieldName;
                        }
                        array.Add(source);
                    }
                    else if (featureClass.ShapeType == esriGeometryType.esriGeometryPolyline)
                    {
                        source = new EdgeFeatureSourceClass();
                        IEdgeFeatureSource source3 = (IEdgeFeatureSource)source;
                        source.Name = this.FeatureClassWraps[num].ToString();
                        source3.ClassConnectivityGroup  = 1;
                        source3.ClassConnectivityPolicy =
                            (esriNetworkEdgeConnectivityPolicy)this.FeatureClassWraps[num].NetworkConnectivityPolicy;
                        if (this.ModifyConnectivity)
                        {
                            source3.FromElevationFieldName = this.FeatureClassWraps[num].FromElevationFieldName;
                            source3.ToElevationFieldName   = this.FeatureClassWraps[num].ToElevationFieldName;
                        }
                        array.Add(source);
                    }
                }
            }
            dataset2.Sources = array;
            for (num = 0; num < this.iarray_0.Count; num++)
            {
                dataset2.Attributes.Add(this.iarray_0.get_Element(num));
            }
            dataset2.SupportsTurns = this.bool_2;
            IFeatureDatasetExtensionContainer container = (IFeatureDatasetExtensionContainer)ifeatureDataset_1;
            IDatasetContainer2 container2 =
                (IDatasetContainer2)container.FindExtension(esriDatasetType.esriDTNetworkDataset);

            return((INetworkDataset)container2.CreateDataset((IDEDataset)dataset2));
        }
        private void CreateAndPopulateTurnFeatureClass(string outputFileGdbPath, string fdsName,
                                                       string ProhibMPTableName, string tempStatsTableName,
                                                       IGPMessages messages, ITrackCancel trackcancel)
        {
            // Determine the number of AltID fields we need (the same as the MAX_SEQNR value).

            Type factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory");
            var wsf = Activator.CreateInstance(factoryType) as IWorkspaceFactory;
            var fws = wsf.OpenFromFile(outputFileGdbPath, 0) as IFeatureWorkspace;
            ITable tempStatsTable = fws.OpenTable(tempStatsTableName);
            short numAltIDFields = 2;
            if (tempStatsTable.RowCount(null) == 1)
                numAltIDFields = (short)((double)(tempStatsTable.GetRow(1).get_Value(tempStatsTable.FindField("MAX_SEQNR"))));

            // Open the MP table and find the fields we need

            ITable mpTable = fws.OpenTable(ProhibMPTableName);
            int seqNrField = mpTable.FindField("SEQNR");
            int trpElIDField = mpTable.FindField("TRPELID");
            int idFieldOnMP = mpTable.FindField("ID");
            int mpJnctIDField = mpTable.FindField("JNCTID");

            // Create a temporary template feature class

            var fcd = new FeatureClassDescriptionClass() as IFeatureClassDescription;
            var ocd = fcd as IObjectClassDescription;
            var fieldsEdit = ocd.RequiredFields as IFieldsEdit;
            IField fieldOnMPTable = mpTable.Fields.get_Field(idFieldOnMP);  // use the ID field as a template for the AltID fields
            for (short i = 1; i <= numAltIDFields; i++)
            {
                IFieldEdit newField = new FieldClass();
                newField.Name_2 = "AltID" + i;
                newField.Precision_2 = fieldOnMPTable.Precision;
                newField.Scale_2 = fieldOnMPTable.Scale;
                newField.Type_2 = fieldOnMPTable.Type;
                fieldsEdit.AddField(newField as IField);
            }
            fieldsEdit.AddField(fieldOnMPTable);
            fieldOnMPTable = mpTable.Fields.get_Field(mpJnctIDField);
            fieldsEdit.AddField(fieldOnMPTable);
            var fieldChk = new FieldCheckerClass() as IFieldChecker;
            IEnumFieldError enumFieldErr = null;
            IFields validatedFields = null;
            fieldChk.ValidateWorkspace = fws as IWorkspace;
            fieldChk.Validate(fieldsEdit as IFields, out enumFieldErr, out validatedFields);
            var tempFC = fws.CreateFeatureClass("TheTemplate", validatedFields, ocd.InstanceCLSID, ocd.ClassExtensionCLSID,
                                                esriFeatureType.esriFTSimple, fcd.ShapeFieldName, "") as IDataset;

            // Create the turn feature class from the template, then delete the template

            Geoprocessor gp = new Geoprocessor();
            CreateTurnFeatureClass createTurnFCTool = new CreateTurnFeatureClass();
            string pathToFds = outputFileGdbPath + "\\" + fdsName;
            createTurnFCTool.out_location = pathToFds;
            createTurnFCTool.out_feature_class_name = TurnFCName;
            createTurnFCTool.maximum_edges = numAltIDFields;
            createTurnFCTool.in_template_feature_class = outputFileGdbPath + "\\TheTemplate";
            gp.Execute(createTurnFCTool, trackcancel);
            tempFC.Delete();

            // Open the new turn feature class and find all the fields on it

            IFeatureClass turnFC = fws.OpenFeatureClass(TurnFCName);
            int[] altIDFields = new int[numAltIDFields];
            int[] edgeFCIDFields = new int[numAltIDFields];
            int[] edgeFIDFields = new int[numAltIDFields];
            int[] edgePosFields = new int[numAltIDFields];
            for (short i = 0; i < numAltIDFields; i++)
            {
                altIDFields[i] = turnFC.FindField("AltID" + (i + 1));
                edgeFCIDFields[i] = turnFC.FindField("Edge" + (i + 1) + "FCID");
                edgeFIDFields[i] = turnFC.FindField("Edge" + (i + 1) + "FID");
                edgePosFields[i] = turnFC.FindField("Edge" + (i + 1) + "Pos");
            }
            int edge1endField = turnFC.FindField("Edge1End");
            int idFieldOnTurnFC = turnFC.FindField("ID");
            int turnFCJnctIDField = turnFC.FindField("JNCTID");

            // Look up the FCID of the Streets feature class

            IFeatureClass streetsFC = fws.OpenFeatureClass(StreetsFCName);
            int streetsFCID = streetsFC.FeatureClassID;

            // Set up queries

            var ts = new TableSortClass() as ITableSort;
            ts.Fields = "ID, SEQNR";
            ts.set_Ascending("ID", true);
            ts.set_Ascending("SEQNR", true);
            ts.QueryFilter = new QueryFilterClass();
            ts.Table = mpTable;
            ts.Sort(null);
            ICursor mpCursor = ts.Rows;
            IFeatureCursor turnFCCursor = turnFC.Insert(true);
            IFeatureBuffer turnBuffer = turnFC.CreateFeatureBuffer();

            // Write the field values to the turn feature class accordingly

            turnBuffer.set_Value(edge1endField, "?");  // dummy value; will be updated in a later calculation
            int numFeatures = 0;
            IRow mpRow = mpCursor.NextRow();
            while (mpRow != null)
            {
                // Transfer the non-edge identifying field values to the buffer
                turnBuffer.set_Value(idFieldOnTurnFC, mpRow.get_Value(idFieldOnMP));
                turnBuffer.set_Value(turnFCJnctIDField, mpRow.get_Value(mpJnctIDField));

                // Write the AltID values to the buffer
                int seq = (int)(mpRow.get_Value(seqNrField));
                int lastEntry;
                do
                {
                    lastEntry = seq;
                    turnBuffer.set_Value(altIDFields[lastEntry - 1], mpRow.get_Value(trpElIDField));
                    mpRow = mpCursor.NextRow();
                    if (mpRow == null) break;
                    seq = (int)(mpRow.get_Value(seqNrField));
                } while (seq != 1);

                // Zero-out the unused fields
                for (int i = lastEntry; i < numAltIDFields; i++)
                    turnBuffer.set_Value(altIDFields[i], 0);

                // Write the FCID and Pos field values to the buffer
                for (short i = 0; i < numAltIDFields; i++)
                {
                    double altID = (double)(turnBuffer.get_Value(altIDFields[i]));
                    if (altID != 0)
                    {
                        turnBuffer.set_Value(edgeFCIDFields[i], streetsFCID);
                        turnBuffer.set_Value(edgeFIDFields[i], 1);
                        turnBuffer.set_Value(edgePosFields[i], 0.5);
                    }
                    else
                    {
                        turnBuffer.set_Value(edgeFCIDFields[i], 0);
                        turnBuffer.set_Value(edgeFIDFields[i], 0);
                        turnBuffer.set_Value(edgePosFields[i], 0);
                    }
                }

                // Create the turn feature
                turnFCCursor.InsertFeature(turnBuffer);
                numFeatures++;

                if ((numFeatures % 100) == 0)
                {
                    // check for user cancel

                    if (trackcancel != null && !trackcancel.Continue())
                        throw (new COMException("Function cancelled."));
                }
            }

            // Flush any outstanding writes to the turn feature class
            turnFCCursor.Flush();

            // Update the Edge1End values

            AddMessage("Updating the Edge1End values...", messages, trackcancel);

            MakeFeatureLayer makeFeatureLayerTool = new MakeFeatureLayer();
            makeFeatureLayerTool.in_features = pathToFds + "\\" + TurnFCName;
            makeFeatureLayerTool.out_layer = "Turn_Layer";
            gp.Execute(makeFeatureLayerTool, trackcancel);

            AddJoin addJoinTool = new AddJoin();
            addJoinTool.in_layer_or_view = "Turn_Layer";
            addJoinTool.in_field = "AltID1";
            addJoinTool.join_table = pathToFds + "\\" + StreetsFCName;
            addJoinTool.join_field = "ID";
            gp.Execute(addJoinTool, trackcancel);

            CalculateField calcFieldTool = new CalculateField();
            calcFieldTool.in_table = "Turn_Layer";
            calcFieldTool.field = TurnFCName + ".Edge1End";
            calcFieldTool.expression = "x";
            calcFieldTool.code_block = "Select Case [" + TurnFCName + ".JNCTID]\n  Case [" + StreetsFCName + ".F_JNCTID]: x = \"N\"\n  Case [" + StreetsFCName + ".T_JNCTID]: x = \"Y\"\n  Case Else: x = \"?\"\nEnd Select";
            calcFieldTool.expression_type = "VB";
            gp.Execute(calcFieldTool, trackcancel);

            RemoveJoin removeJoinTool = new RemoveJoin();
            removeJoinTool.in_layer_or_view = "Turn_Layer";
            removeJoinTool.join_name = StreetsFCName;
            gp.Execute(removeJoinTool, trackcancel);

            Delete deleteTool = new Delete();
            deleteTool.in_data = "Turn_Layer";
            gp.Execute(deleteTool, trackcancel);

            AddMessage("Updating the EdgeFID values...", messages, trackcancel);

            // Create a temporary network dataset for updating the EdgeFID values

            IDENetworkDataset dends = new DENetworkDatasetClass();
            dends.SupportsTurns = true;
            dends.Buildable = true;
            (dends as IDataElement).Name = StreetsFCName;
            (dends as IDEGeoDataset).SpatialReference = (streetsFC as IGeoDataset).SpatialReference;
            IArray sourceArray = new ArrayClass();
            var efs = new EdgeFeatureSourceClass() as IEdgeFeatureSource;
            (efs as INetworkSource).Name = StreetsFCName;
            efs.UsesSubtypes = false;
            efs.ClassConnectivityGroup = 1;
            efs.ClassConnectivityPolicy = esriNetworkEdgeConnectivityPolicy.esriNECPEndVertex;
            sourceArray.Add(efs);
            var tfs = new TurnFeatureSourceClass() as INetworkSource;
            tfs.Name = TurnFCName;
            sourceArray.Add(tfs);
            dends.Sources = sourceArray;
            var fdxc = fws.OpenFeatureDataset(fdsName) as IFeatureDatasetExtensionContainer;
            var dsCont = fdxc.FindExtension(esriDatasetType.esriDTNetworkDataset) as IDatasetContainer2;
            var tempNDS = dsCont.CreateDataset(dends as IDEDataset) as IDataset;

            // Set the EdgeFID field values by running UpdateByAlternateIDFields

            UpdateByAlternateIDFields updateByAltIDTool = new UpdateByAlternateIDFields();
            updateByAltIDTool.in_network_dataset = pathToFds + "\\" + StreetsFCName;
            updateByAltIDTool.alternate_ID_field_name = "ID";
            gp.Execute(updateByAltIDTool, trackcancel);

            // Delete the temporary network dataset

            tempNDS.Delete();

            // Write the turn geometries

            TurnGeometryUtilities.WriteTurnGeometry(outputFileGdbPath, StreetsFCName, TurnFCName,
                                                    numAltIDFields, 0.3, messages, trackcancel);

            // Index the turn geometries

            AddMessage("Creating spatial index on the turn feature class...", messages, trackcancel);

            AddSpatialIndex addSpatialIndexTool = new AddSpatialIndex();
            addSpatialIndexTool.in_features = pathToFds + "\\" + TurnFCName;
            gp.Execute(addSpatialIndexTool, trackcancel);

            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;
        }
Ejemplo n.º 10
0
        /// <summary>
        /// 个人数据库的路径,要素数据集的路径,建立网络的名称,参与网络的要素类
        /// </summary>
        /// <param name="_pWsName"></param>
        /// <param name="_pDatasetName"></param>
        /// <param name="_pNetName"></param>
        /// <param name="_pFtName"></param>
        void CreateNetworkDataset(string _pWsName, string _pDatasetName,string _pNetName, string _pFtName)
        {
            IDENetworkDataset2 pDENetworkDataset = new DENetworkDatasetClass();

            pDENetworkDataset.Buildable = true;

            IWorkspace pWs = GetMDBWorkspace(_pWsName);

            IFeatureWorkspace pFtWs = pWs as IFeatureWorkspace;

            IFeatureDataset pFtDataset = pFtWs.OpenFeatureDataset(_pDatasetName);

            // 定义空间参考,负责会出错
            IDEGeoDataset pDEGeoDataset = (IDEGeoDataset)pDENetworkDataset;

             IGeoDataset pGeoDataset = pFtDataset as IGeoDataset;

            pDEGeoDataset.Extent = pGeoDataset.Extent;

             pDEGeoDataset.SpatialReference = pGeoDataset.SpatialReference;

            // 网络数据集的名称
            IDataElement pDataElement = (IDataElement)pDENetworkDataset;

            pDataElement.Name = _pNetName;

            // 参加建立网络数据集的要素类
            INetworkSource pEdgeNetworkSource = new EdgeFeatureSourceClass();
            pEdgeNetworkSource.Name = _pFtName;

            pEdgeNetworkSource.ElementType = esriNetworkElementType.esriNETEdge;

            // 要素类的连通性
            IEdgeFeatureSource pEdgeFeatureSource = (IEdgeFeatureSource)pEdgeNetworkSource;
            pEdgeFeatureSource.UsesSubtypes = false;

            pEdgeFeatureSource.ClassConnectivityGroup = 1;

            pEdgeFeatureSource.ClassConnectivityPolicy =esriNetworkEdgeConnectivityPolicy.esriNECPEndVertex;

            //不用转弯数据
            pDENetworkDataset.SupportsTurns = false;

            IArray pSourceArray = new ArrayClass();
            pSourceArray.Add(pEdgeNetworkSource);

            pDENetworkDataset.Sources = pSourceArray;

            //网络数据集的属性设置

            IArray pAttributeArray = new ArrayClass();

            // Initialize variables reused when creating attributes:
            IEvaluatedNetworkAttribute pEvalNetAttr;
            INetworkAttribute2 pNetAttr2;
            INetworkFieldEvaluator pNetFieldEval;
            INetworkConstantEvaluator pNetConstEval;

            pEvalNetAttr = new EvaluatedNetworkAttributeClass();
            pNetAttr2 = (INetworkAttribute2)pEvalNetAttr;
            pNetAttr2.Name ="Meters";
            pNetAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTCost;
            pNetAttr2.DataType = esriNetworkAttributeDataType.esriNADTDouble;
            pNetAttr2.Units = esriNetworkAttributeUnits.esriNAUMeters;
            pNetAttr2.UseByDefault = false;

            pNetFieldEval = new NetworkFieldEvaluatorClass();
            pNetFieldEval.SetExpression("[METERS]", "");
            //方向设置
            pEvalNetAttr.set_Evaluator(pEdgeNetworkSource,
                esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)pNetFieldEval);
            pEvalNetAttr.set_Evaluator(pEdgeNetworkSource,
                esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)
                pNetFieldEval);

            pNetConstEval = new NetworkConstantEvaluatorClass();
            pNetConstEval.ConstantValue = 0;
            pEvalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge,
                (INetworkEvaluator)pNetConstEval);
            pEvalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction,
                (INetworkEvaluator)pNetConstEval);
            pEvalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn,
                (INetworkEvaluator)pNetConstEval);

            // 一个网络数据集可以有多个属性,我只添加了一个
            pAttributeArray.Add(pEvalNetAttr);

            pDENetworkDataset.Attributes = pAttributeArray;

            // 创建网络数据集,注意在创建几何网络的时候会锁定相应的要素类,因此不要用ArcMap或者catalog等打开参相应的数据

              INetworkDataset pNetworkDataset = Create(pFtDataset, pDENetworkDataset);

            //建立网络

            INetworkBuild pNetworkBuild = (INetworkBuild)pNetworkDataset;

            pNetworkBuild.BuildNetwork(pGeoDataset.Extent);
        }