基于网络数据集的最短路径

基于网络数据集的最短路径
在网络找了很久还是没有找到关于网络数据集最短路径分析,全是基于几何网络的,昨天参照AE的ClosestFacilitySolver实例和网上网友发布的在内存建立图层的方法完成了网络数据集的最短路径分析,功能还是比较粗糙,对于高手应该很简单,但是对于刚接触AE的朋友也算是抛砖引玉了。

贴出主要函数:
//打开网络数据集
        public INetworkDataset OpenNetworkDataset(IWorkspace networkDatasetWorkspace, System.String networkDatasetName, System.String featureDatasetName)
        {
            if (networkDatasetWorkspace == null || networkDatasetName == "" || featureDatasetName == null)
            {
                return null;
            }

            IDatasetContainer3 datasetContainer3 = null;
            switch (networkDatasetWorkspace.Type)
            {
                case ESRI.ArcGIS.Geodatabase.esriWorkspaceType.esriFileSystemWorkspace:

                    // Shapefile or SDC network dataset workspace
                    IWorkspaceExtensionManager workspaceExtensionManager = networkDatasetWorkspace as ESRI.ArcGIS.Geodatabase.IWorkspaceExtensionManager; // Dynamic Cast
                    ESRI.ArcGIS.esriSystem.UID networkID = new ESRI.ArcGIS.esriSystem.UIDClass();

                    networkID.Value = "esriGeoDatabase.NetworkDatasetWorkspaceExtension";
                    ESRI.ArcGIS.Geodatabase.IWorkspaceExtension workspaceExtension = workspaceExtensionManager.FindExtension(networkID);
                    datasetContainer3 = workspaceExtension as IDatasetContainer3; // Dynamic Cast
                    break;

                case ESRI.ArcGIS.Geodatabase.esriWorkspaceType.esriLocalDatabaseWorkspace:

                // Personal Geodatabase or File Geodatabase network dataset workspace

                case ESRI.ArcGIS.Geodatabase.esriWorkspaceType.esriRemoteDatabaseWorkspace:

                    // SDE Geodatabase network dataset workspace
                    ESRI.ArcGIS.Geodatabase.IFeatureWorkspace featureWorkspace = networkDatasetWorkspace as ESRI.ArcGIS.Geodatabase.IFeatureWorkspace; // Dynamic Cast
                    featureDataset = featureWorkspace.OpenFeatureDataset(featureDatasetName);
                    ESRI.ArcGIS.Geodatabase.IFeatureDatasetExtensionContainer featureDatasetExtensionContainer = featureDataset as ESRI.ArcGIS.Geodatabase.IFeatureDatasetExtensionContainer; // Dynamic Cast
                    ESRI.ArcGIS.Geodatabase.IFeatureDatasetExtension featureDatasetExtension = featureDatasetExtensionContainer.FindExtension(ESRI.ArcGIS.Geodatabase.esriDatasetType.esriDTNetworkDataset);
                    datasetContainer3 = featureDatasetExtension as ESRI.ArcGIS.Geodatabase.IDatasetContainer3; // Dynamic Cast
                    break;
            }

            if (datasetContainer3 == null)
                return null;

            ESRI.ArcGIS.Geodatabase.IDataset dataset = datasetContainer3.get_DatasetByName(ESRI.ArcGIS.Geodatabase.esriDatasetType.esriDTNetworkDataset, networkDatasetName);

            return dataset as ESRI.ArcGIS.Geodatabase.INetworkDataset; // Dynamic Cast
        }

//创建网络分析上下文
        public INAContext CreateSolverContext(INetworkDataset networkDataset)
        {
              IDENetworkDataset deNDS = GetDENetworkDataset(networkDataset);
                        INASolver naSolver;
            naSolver = new NARouteSolver();   
             INAContextEdit contextEdit = naSolver.CreateContext(deNDS, naSolver.Name) as INAContextEdit;
             contextEdit.Bind(networkDataset, new GPMessagesClass());
            return contextEdit as INAContext;
        }

//得到创建网络分析上下文所需的IDENetworkDataset类型参数
        public IDENetworkDataset GetDENetworkDataset(INetworkDataset networkDataset)
        {
            //QI from the Network Dataset to the DatasetComponent
            IDatasetComponent dsComponent;
            dsComponent = networkDataset as IDatasetComponent;
                        //Get the Data Element
            return dsComponent.DataElement as IDENetworkDataset;
        }


/// <summary>
        /// 在内存中创建图层
        /// </summary>
        /// <param name="DataSetName">数据集名称(所建图层名称)</param>
        /// <param name="AliaseName">别名</param>
        /// <param name="SpatialRef">空间参考</param>
        /// <param name="GeometryType">几何类型</param>
        /// <param name="PropertyFields">属性字段集合</param>
        /// <returns>IfeatureLayer</returns>
        public static IFeatureLayer CreateFeatureLayerInmemeory(string DataSetName, string AliaseName, ISpatialReference SpatialRef, esriGeometryType GeometryType, IFields PropertyFields)
        {
            IWorkspaceFactory workspaceFactory = new InMemoryWorkspaceFactoryClass();
            ESRI.ArcGIS.Geodatabase.IWorkspaceName workspaceName = workspaceFactory.Create("", "MyWorkspace", null, 0);
            ESRI.ArcGIS.esriSystem.IName name = (IName)workspaceName;
            ESRI.ArcGIS.Geodatabase.IWorkspace inmemWor = (IWorkspace)name.Open();

            IField oField = new FieldClass();
            IFields oFields = new FieldsClass();
            IFieldsEdit oFieldsEdit = null;
            IFieldEdit oFieldEdit = null;
            IFeatureClass oFeatureClass = null;
            IFeatureLayer oFeatureLayer = null;

            try
            {
                oFieldsEdit = oFields as IFieldsEdit;
                oFieldEdit = oField as IFieldEdit;

                for (int i = 0; i < PropertyFields.FieldCount; i++)
                {
                    oFieldsEdit.AddField(PropertyFields.get_Field(i));
                }

                //IGeometryDef Interface Provides access to members that return information about the geometry definition
                IGeometryDef geometryDef = new GeometryDefClass();
                //IGeometryDefEdit Provides access to members that modify the geometry definition
                IGeometryDefEdit geometryDefEdit = (IGeometryDefEdit)geometryDef;
                geometryDefEdit.AvgNumPoints_2 = 5;
                geometryDefEdit.GeometryType_2 = GeometryType;
                geometryDefEdit.GridCount_2 = 1;
                geometryDefEdit.HasM_2 = false;
                geometryDefEdit.HasZ_2 = false;
                geometryDefEdit.SpatialReference_2 = SpatialRef;

                oFieldEdit.Name_2 = "SHAPE";
                oFieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry;
                oFieldEdit.GeometryDef_2 = geometryDef;
                oFieldEdit.IsNullable_2 = true;
                oFieldEdit.Required_2 = true;
                oFieldsEdit.AddField(oField);

                oFeatureClass = (inmemWor as IFeatureWorkspace).CreateFeatureClass(DataSetName, oFields, null, null, esriFeatureType.esriFTSimple, "SHAPE", "");
                (oFeatureClass as IDataset).BrowseName = DataSetName;

                oFeatureLayer = new FeatureLayerClass();
                oFeatureLayer.Name = AliaseName;
                oFeatureLayer.FeatureClass = oFeatureClass;
            }
            catch
            {
            }
            finally
            {
                try
                {
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(oField);
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(oFields);
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(oFieldsEdit);
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(oFieldEdit);
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(name);
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(workspaceFactory);
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(workspaceName);
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(inmemWor);
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(oFeatureClass);
                }
                catch { }

                GC.Collect();
            }
            return oFeatureLayer;
        }

//Create fileds
        public IFields CreateFields()
        {
            IFields fields= new FieldsClass();      
            // create the fields using the required fields method
                IObjectClassDescription objectClassDescription = new ObjectClassDescriptionClass();
                fields = objectClassDescription.RequiredFields;
                ESRI.ArcGIS.Geodatabase.IFieldsEdit fieldsEdit = (ESRI.ArcGIS.Geodatabase.IFieldsEdit)fields; // Explicit Cast
                ESRI.ArcGIS.Geodatabase.IField field = new ESRI.ArcGIS.Geodatabase.FieldClass();

                // create a user defined text field
                ESRI.ArcGIS.Geodatabase.IFieldEdit fieldEdit = (ESRI.ArcGIS.Geodatabase.IFieldEdit)field; // Explicit Cast

                // setup field properties
                fieldEdit.Name_2 = "SampleField";
                fieldEdit.Type_2 = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeString;
                fieldEdit.IsNullable_2 = true;
                fieldEdit.AliasName_2 = "Sample Field Column";
                fieldEdit.DefaultValue_2 = "test";
                fieldEdit.Editable_2 = true;
                fieldEdit.Length_2 = 100;

                // add field to field collection
                fieldsEdit.AddField(field);
                fields = (ESRI.ArcGIS.Geodatabase.IFields)fieldsEdit; // Explicit Cast
                return fields;
           //}
            //return null;
        }


        //Get Spatial Reference from Dataset
        public ISpatialReference GetSpatialReferenceFromDataset(IDataset dataset)
        {
            //If the dataset supports IGeoDataset
            if (dataset is IGeoDataset)
            {
                //then grab the spatial reference information and return it.
                IGeoDataset geoDataset = (IGeoDataset)dataset;
                return geoDataset.SpatialReference;
            }
            else
            {
                return null; //otherwise return null
            }
        }


        //在要素类创建要素
        public void CreateFeature(IFeatureClass featureClass, IPointCollection PointCollection)
        {
            // Ensure the feature class contains points.
            if (featureClass.ShapeType != esriGeometryType.esriGeometryPoint)
            {
                return;
            }

            // Build the feature.
            for (int i = 0; i < PointCollection.PointCount; i++)
            {
                IFeature feature = featureClass.CreateFeature();
                feature.Shape = PointCollection.get_Point(i);


                // Apply the appropriate subtype to the feature.
                ISubtypes subtypes = (ISubtypes)featureClass;
                IRowSubtypes rowSubtypes = (IRowSubtypes)feature;
                if (subtypes.HasSubtype)
                {
                    // In this example, the value of 3 represents the Cross subtype.
                    rowSubtypes.SubtypeCode = 3;
                }

                // Initialize any default values the feature has.
                rowSubtypes.InitDefaultValues();

                // Update the value on a string field that indicates who installed the feature.
                //int contractorFieldIndex = featureClass.FindField("CONTRACTOR");
                //feature.set_Value(contractorFieldIndex, "K Johnston");

                // Commit the new feature to the geodatabase.
                feature.Store();
            }
        }

//************************************************************
        //根据点图层在网络拓扑图层上确定用户要查找最优路径所用经历的点
        //************************************************************
        public void LoadNANetworkLocations(string strNAClassName, IFeatureClass inputFC, double snapTolerance)
        {            
            INAClass naClass;            
            INamedSet classes;
            classes = m_NAContext.NAClasses;
            naClass = classes.get_ItemByName(strNAClassName) as INAClass;

            // delete existing Locations except if that a barriers
            naClass.DeleteAllRows();

            // Create a NAClassLoader and set the snap tolerance (meters unit)
            INAClassLoader classLoader = new NAClassLoader();
            classLoader.Locator = m_NAContext.Locator;
            if (snapTolerance > 0) classLoader.Locator.SnapTolerance = snapTolerance;
            classLoader.NAClass = naClass;

            //Create field map to automatically map fields from input class to naclass
            INAClassFieldMap fieldMap;
            fieldMap = new NAClassFieldMap();
            fieldMap.CreateMapping(naClass.ClassDefinition, inputFC.Fields);
            classLoader.FieldMap = fieldMap;

            //Load Network Locations
            int rowsIn = 0;
            int rowsLocated = 0;
            IFeatureCursor featureCursor = inputFC.Search(null, true);
            classLoader.Load((ICursor)featureCursor, null, ref rowsIn, ref rowsLocated);

            //Message all of the network analysis agents that the analysis context has changed
            ((INAContextEdit)m_NAContext).ContextChanged();
        }


//*********************************************************************************
        // Set Solver Settings设置阻抗属性等
        //*********************************************************************************
        public void SetSolverSettings()
        {
            //Set Route specific Settings
            INASolver naSolver = m_NAContext.Solver;

            INARouteSolver cfSolver = naSolver as INARouteSolver;
            /*if (txtCutOff.Text.Length > 0 && IsNumeric(txtCutOff.Text.Trim()))
                cfSolver.DefaultCutoff = txtCutOff.Text;
            else
                cfSolver.DefaultCutoff = null;

            if (txtTargetFacility.Text.Length > 0 && IsNumeric(txtTargetFacility.Text))
                cfSolver.DefaultTargetFacilityCount = int.Parse(txtTargetFacility.Text);
            else
                cfSolver.DefaultTargetFacilityCount = 1;*/

            cfSolver.OutputLines = esriNAOutputLineType.esriNAOutputLineTrueShapeWithMeasure;
            cfSolver.CreateTraversalResult =true ;
            cfSolver.UseTimeWindows = false;
            cfSolver.FindBestSequence = false;
            cfSolver.PreserveFirstStop = false;
            cfSolver.PreserveLastStop = false;

            // Set generic solver settings设置Solver属性,设置路径分析阻抗属性
            // Set the impedance attribute
            INASolverSettings naSolverSettings;
            naSolverSettings = naSolver as INASolverSettings;
            naSolverSettings.ImpedanceAttributeName = cboCostAttribute.Text;

            // Set the OneWay Restriction if necessary设置单行限制
            IStringArray restrictions;
            restrictions = naSolverSettings.RestrictionAttributeNames;
            restrictions.RemoveAll();
            if (chkUseRestriction.Checked)
                restrictions.Add("oneway");

            naSolverSettings.RestrictionAttributeNames = restrictions;

            //Restrict UTurns限制U型转向限制
            naSolverSettings.RestrictUTurns = esriNetworkForwardStarBacktrack.esriNFSBNoBacktrack;
            naSolverSettings.IgnoreInvalidLocations = true;

            // Set the Hierachy attribute设置层次属性
            naSolverSettings.UseHierarchy = chkUseHierarchy.Checked;
            if (naSolverSettings.UseHierarchy)
            {
                naSolverSettings.HierarchyAttributeName = "hierarchy";
                naSolverSettings.HierarchyLevelCount = 3;
                naSolverSettings.set_MaxValueForHierarchy(1, 1);
                naSolverSettings.set_NumTransitionToHierarchy(1, 9);

                naSolverSettings.set_MaxValueForHierarchy(2, 2);
                naSolverSettings.set_NumTransitionToHierarchy(2, 9);
            }

            // Do not forget to update the context after you set your impedance
            naSolver.UpdateContext(m_NAContext, GetDENetworkDataset(m_NAContext.NetworkDataset), new GPMessagesClass());
        }

//*********************************************************************************
        // Solve the problem 进行最短路径分析
        //*********************************************************************************
        public string Solve(INAContext naContext, IGPMessages gpMessages)
        {
            string errStr = "";
            try
            {
                //Solving the Problem
                errStr = "Error when solving";
                bool isPartialSolution = naContext.Solver.Solve(naContext, gpMessages, null);

                if (!isPartialSolution)
                    errStr = "OK";
                else
                    errStr = "Partial Solution";
            }
            catch (Exception e)
            {
                errStr += " Error Description " + e.Message;
            }
            return errStr;
        }
posted @ 2009-05-22 00:39  MYGIS_3  阅读(2326)  评论(3)    收藏  举报