最短路径 ae中最短路径分析

最短路径
ae中最短路径分析

 

构建网络有两种方式,分别是网络数据集NetworkDataset和几何网络Geometric Network,这个网络结构数据的创建直接在Catalog中实现创建,进行最短路径分析,为了直接使用ArcGIS提供的功能,我选用的是NetworkDataset,主要记录下考虑单双行的最短路径的设计与实现(理想状态,不考虑转弯等要素)。
(A)对数据编辑的要求有一下几点:
(1) 添加属性字段,名称为Oneway,类型Text,默认值为空。

最短路径
ae中最短路径分析

(2) 道路数据电子矢量化 
(3) 对于单行线、禁行以及无限制通行方向道路属性值设置的要求:
由东往西或由北往南通行的单行路段,Oneway字段值设为:FT
由西往东或由南往北通行的单行路段,Oneway字段值设为:TF
禁止通行的路段,Oneway字段值为:N
双向通行的路段,Oneway字段值为:空字符 
(B)路径分析的思路分为一下几步:
(1)读取shp文件和网络数据集数据
(2)创建网络分析上下文对象INAContext和网络分析对象INASolver(==IRouteNASolver)
(3)加载位置点图层,创建网络位置
(4)设置Solver参数(输出、容限值等)
(5)进行分析
(6)显示路线及结果信息
PS:对于道路走向不是正南正北,或者很难分辨是东西向还是南北向的,Oneway字段的赋值情况,还没有琢磨出万无一失的方法,有高人熟悉的,请指点。
(C)代码实现部分:
//初始化地图、网络数据集
        private void Initial()
        {
            this.axMapControl1.ActiveView.Clear();
            axMapControl1.ActiveView.Refresh();

            pFeatureWorkspace = OpenWorkspace(ConfigurationManager.ConnectionStrings["MdbPath"].ToString()) as IFeatureWorkspace;
            pNetworkDataset = OpenNetworkDataset_Other(pFeatureWorkspace as IWorkspace, "TestNet_ND", "TestNet");

            pNAContext = CreateNAContext(pNetworkDataset);

            pInputFC = pFeatureWorkspace.OpenFeatureClass("stop");

            pVertexFC = pFeatureWorkspace.OpenFeatureClass("TestNet_ND_Junctions");

            IFeatureLayer pVertexFL = new FeatureLayerClass();
            pVertexFL.FeatureClass = pFeatureWorkspace.OpenFeatureClass("TestNet_ND_Junctions");
            pVertexFL.Name = pVertexFL.FeatureClass.AliasName;
            axMapControl1.AddLayer(pVertexFL, 0);

            IFeatureLayer pRoadFL = new FeatureLayerClass();
            pRoadFL.FeatureClass = pFeatureWorkspace.OpenFeatureClass("道路中心线");
            pRoadFL.Name = pRoadFL.FeatureClass.AliasName;
            axMapControl1.AddLayer(pRoadFL,0);

            ILayer pLayer;
            INetworkLayer pNetworkLayer = new NetworkLayerClass();
            pNetworkLayer.NetworkDataset = pNetworkDataset;
            pLayer = pNetworkLayer as ILayer;
            pLayer.Name = "Network Dataset";
            axMapControl1.AddLayer(pLayer, 0);

            //Create a Network Analysis Layer and add to ArcMap
            INALayer naLayer = pNAContext.Solver.CreateLayer(pNAContext);
            pLayer = naLayer as ILayer;
            pLayer.Name = pNAContext.Solver.DisplayName;
            axMapControl1.AddLayer(pLayer, 0);

            pActiveView = axMapControl1.ActiveView;
            pMap = pActiveView.FocusMap;
            pGraphicsContainer = pMap as IGraphicsContainer;
        }

        //打开工作空间
        private IWorkspace OpenWorkspace(string strMDBName)
        {
            IWorkspaceFactory pWorkspaceFactory = new AccessWorkspaceFactoryClass();
            return pWorkspaceFactory.OpenFromFile(strMDBName, 0);
        }

        //打开网络数据集
        private INetworkDataset OpenNetworkDataset(IWorkspace workspace,string strNDName)
        {
            IWorkspaceExtensionManager pWorkspaceExtensionManager;
            IWorkspaceExtension pWorkspaceExtension;
            IDatasetContainer2 pDatasetContainer2;

            pWorkspaceExtensionManager = workspace as IWorkspaceExtensionManager;
            int iCount = pWorkspaceExtensionManager.ExtensionCount;
            for (int i = 0; i < iCount; i++)
            {
                pWorkspaceExtension = pWorkspaceExtensionManager.get_Extension(i);
                if(pWorkspaceExtension.Name.Equals("Network Dataset"))
                {
                    pDatasetContainer2=pWorkspaceExtension as IDatasetContainer2;
                    return pDatasetContainer2.get_DatasetByName(esriDatasetType.esriDTNetworkDataset, strNDName) as INetworkDataset;
                }                
            }
            return null;

        }

        private INetworkDataset OpenNetworkDataset_Other(IWorkspace workspace, string strNDName,string strRoadFeatureDataset)
        {
            IDatasetContainer3 pDatasetContainer3;
            IFeatureWorkspace pFeatureWorkspace = workspace as IFeatureWorkspace;
            pFeatureDataset = pFeatureWorkspace.OpenFeatureDataset(strRoadFeatureDataset);
            IFeatureDatasetExtensionContainer pFeatureDatasetExtensionContainer = pFeatureDataset as IFeatureDatasetExtensionContainer;
            IFeatureDatasetExtension pFeatureDatasetExtension = pFeatureDatasetExtensionContainer.FindExtension(esriDatasetType.esriDTNetworkDataset);
            pDatasetContainer3 = pFeatureDatasetExtension as IDatasetContainer3;

            if (pDatasetContainer3 == null)
                return null;
            IDataset pDataset = pDatasetContainer3.get_DatasetByName(esriDatasetType.esriDTNetworkDataset, strNDName);
            return pDataset as INetworkDataset;
        }

        //创建网络分析上下文
        private INAContext CreateNAContext(INetworkDataset networkDataset)
        {
            IDENetworkDataset pDENetworkDataset = GetDENetworkDataset(networkDataset);
            INASolver pNASolver = new NARouteSolverClass();
            INAContextEdit pNAContextEdit = pNASolver.CreateContext(pDENetworkDataset, pNASolver.Name) as INAContextEdit;
            pNAContextEdit.Bind(networkDataset,new GPMessagesClass());
            return pNAContextEdit as INAContext;
        }

//根据点图层确定最短路径所用经历的点
        private void LoadNANetWorkLocations(string strNAClassName, IFeatureClass inputFC, double dSnapTolerance)
        {
            INAClass pNAClass;
            INamedSet pNamedSet;
            pNamedSet = pNAContext.NAClasses;
            pNAClass = pNamedSet.get_ItemByName(strNAClassName) as INAClass;

            //删除已存在的位置点
            pNAClass.DeleteAllRows();

            //创建NAClassLoader,设置捕捉容限值
            INAClassLoader pNAClassLoader = new NAClassLoaderClass();
            pNAClassLoader.Locator = pNAContext.Locator;
            if (dSnapTolerance > 0)
                pNAClassLoader.Locator.SnapTolerance = dSnapTolerance;
            pNAClassLoader.NAClass = pNAClass;

            //字段匹配
            INAClassFieldMap pNAClassFieldMap = new NAClassFieldMapClass();
            pNAClassFieldMap.CreateMapping(pNAClass.ClassDefinition, inputFC.Fields);
            pNAClassLoader.FieldMap = pNAClassFieldMap;

            //pNAClassFieldMap.set_MappedField("OBJECTID", "OBJECTID");
            //pNAClassLoader.FieldMap = pNAClassFieldMap;

            //加载网络位置点数据
            int iRows=0;
            int iRowsLocated=0;
            IFeatureCursor pFeatureCursor = pInputFC.Search(null, true);
            pNAClassLoader.Load((ICursor)pFeatureCursor, null, ref iRows, ref iRowsLocated);
            ((INAContextEdit)pNAContext).ContextChanged();
        }
          //路径分析
             private void btnSolver_Click(object sender, EventArgs e)
            {
                this.Cursor = Cursors.WaitCursor;
                lstOutput.Items.Clear();
                lstOutput.Items.Add("分析中...");
                LoadNANetWorkLocations("Stops", pInputFC, 80);
                IGPMessages gpMessages = new GPMessagesClass();
                INASolver naSolver = pNAContext.Solver;
                SetSolverSettings();
                pNAContext.Solver.Solve(pNAContext, gpMessages, new CancelTrackerClass());

                if (gpMessages != null)
                {
                    for (int i = 0; i < gpMessages.Count; i++)
                    {
                        switch (gpMessages.GetMessage(i).Type)
                        {

                            case esriGPMessageType.esriGPMessageTypeError:
                                lstOutput.Items.Add("错误 " + gpMessages.GetMessage(i).ErrorCode.ToString() + " " + gpMessages.GetMessage(i).Description);
                                break;
                            case esriGPMessageType.esriGPMessageTypeWarning:
                                lstOutput.Items.Add("警告 " + gpMessages.GetMessage(i).Description);
                                break;
                            default:
                                lstOutput.Items.Add("信息 " + gpMessages.GetMessage(i).Description);
                                break;
                        }
                    }
                }

                axMapControl1.Refresh();
                lstOutput.Items.Add("Successful");
                this.Cursor = Cursors.Default;
             }

(D)上下效果图

最短路径
ae中最短路径分析
最短路径
ae中最短路径分析

构建网络有两种方式,分别是网络数据集NetworkDataset和几何网络Geometric Network,这个网络结构数据的创建直接在Catalog中实现创建,进行最短路径分析,为了直接使用ArcGIS提供的功能,我选用的是NetworkDataset,主要记录下考虑单双行的最短路径的设计与实现(理想状态,不考虑转弯等要素)。
(A)对数据编辑的要求有一下几点:
(1) 添加属性字段,名称为Oneway,类型Text,默认值为空。

最短路径
ae中最短路径分析

(2) 道路数据电子矢量化 
(3) 对于单行线、禁行以及无限制通行方向道路属性值设置的要求:
由东往西或由北往南通行的单行路段,Oneway字段值设为:FT
由西往东或由南往北通行的单行路段,Oneway字段值设为:TF
禁止通行的路段,Oneway字段值为:N
双向通行的路段,Oneway字段值为:空字符 
(B)路径分析的思路分为一下几步:
(1)读取shp文件和网络数据集数据
(2)创建网络分析上下文对象INAContext和网络分析对象INASolver(==IRouteNASolver)
(3)加载位置点图层,创建网络位置
(4)设置Solver参数(输出、容限值等)
(5)进行分析
(6)显示路线及结果信息
PS:对于道路走向不是正南正北,或者很难分辨是东西向还是南北向的,Oneway字段的赋值情况,还没有琢磨出万无一失的方法,有高人熟悉的,请指点。
(C)代码实现部分:
//初始化地图、网络数据集
        private void Initial()
        {
            this.axMapControl1.ActiveView.Clear();
            axMapControl1.ActiveView.Refresh();

            pFeatureWorkspace = OpenWorkspace(ConfigurationManager.ConnectionStrings["MdbPath"].ToString()) as IFeatureWorkspace;
            pNetworkDataset = OpenNetworkDataset_Other(pFeatureWorkspace as IWorkspace, "TestNet_ND", "TestNet");

            pNAContext = CreateNAContext(pNetworkDataset);

            pInputFC = pFeatureWorkspace.OpenFeatureClass("stop");

            pVertexFC = pFeatureWorkspace.OpenFeatureClass("TestNet_ND_Junctions");

            IFeatureLayer pVertexFL = new FeatureLayerClass();
            pVertexFL.FeatureClass = pFeatureWorkspace.OpenFeatureClass("TestNet_ND_Junctions");
            pVertexFL.Name = pVertexFL.FeatureClass.AliasName;
            axMapControl1.AddLayer(pVertexFL, 0);

            IFeatureLayer pRoadFL = new FeatureLayerClass();
            pRoadFL.FeatureClass = pFeatureWorkspace.OpenFeatureClass("道路中心线");
            pRoadFL.Name = pRoadFL.FeatureClass.AliasName;
            axMapControl1.AddLayer(pRoadFL,0);

            ILayer pLayer;
            INetworkLayer pNetworkLayer = new NetworkLayerClass();
            pNetworkLayer.NetworkDataset = pNetworkDataset;
            pLayer = pNetworkLayer as ILayer;
            pLayer.Name = "Network Dataset";
            axMapControl1.AddLayer(pLayer, 0);

            //Create a Network Analysis Layer and add to ArcMap
            INALayer naLayer = pNAContext.Solver.CreateLayer(pNAContext);
            pLayer = naLayer as ILayer;
            pLayer.Name = pNAContext.Solver.DisplayName;
            axMapControl1.AddLayer(pLayer, 0);

            pActiveView = axMapControl1.ActiveView;
            pMap = pActiveView.FocusMap;
            pGraphicsContainer = pMap as IGraphicsContainer;
        }

        //打开工作空间
        private IWorkspace OpenWorkspace(string strMDBName)
        {
            IWorkspaceFactory pWorkspaceFactory = new AccessWorkspaceFactoryClass();
            return pWorkspaceFactory.OpenFromFile(strMDBName, 0);
        }

        //打开网络数据集
        private INetworkDataset OpenNetworkDataset(IWorkspace workspace,string strNDName)
        {
            IWorkspaceExtensionManager pWorkspaceExtensionManager;
            IWorkspaceExtension pWorkspaceExtension;
            IDatasetContainer2 pDatasetContainer2;

            pWorkspaceExtensionManager = workspace as IWorkspaceExtensionManager;
            int iCount = pWorkspaceExtensionManager.ExtensionCount;
            for (int i = 0; i < iCount; i++)
            {
                pWorkspaceExtension = pWorkspaceExtensionManager.get_Extension(i);
                if(pWorkspaceExtension.Name.Equals("Network Dataset"))
                {
                    pDatasetContainer2=pWorkspaceExtension as IDatasetContainer2;
                    return pDatasetContainer2.get_DatasetByName(esriDatasetType.esriDTNetworkDataset, strNDName) as INetworkDataset;
                }                
            }
            return null;

        }

        private INetworkDataset OpenNetworkDataset_Other(IWorkspace workspace, string strNDName,string strRoadFeatureDataset)
        {
            IDatasetContainer3 pDatasetContainer3;
            IFeatureWorkspace pFeatureWorkspace = workspace as IFeatureWorkspace;
            pFeatureDataset = pFeatureWorkspace.OpenFeatureDataset(strRoadFeatureDataset);
            IFeatureDatasetExtensionContainer pFeatureDatasetExtensionContainer = pFeatureDataset as IFeatureDatasetExtensionContainer;
            IFeatureDatasetExtension pFeatureDatasetExtension = pFeatureDatasetExtensionContainer.FindExtension(esriDatasetType.esriDTNetworkDataset);
            pDatasetContainer3 = pFeatureDatasetExtension as IDatasetContainer3;

            if (pDatasetContainer3 == null)
                return null;
            IDataset pDataset = pDatasetContainer3.get_DatasetByName(esriDatasetType.esriDTNetworkDataset, strNDName);
            return pDataset as INetworkDataset;
        }

        //创建网络分析上下文
        private INAContext CreateNAContext(INetworkDataset networkDataset)
        {
            IDENetworkDataset pDENetworkDataset = GetDENetworkDataset(networkDataset);
            INASolver pNASolver = new NARouteSolverClass();
            INAContextEdit pNAContextEdit = pNASolver.CreateContext(pDENetworkDataset, pNASolver.Name) as INAContextEdit;
            pNAContextEdit.Bind(networkDataset,new GPMessagesClass());
            return pNAContextEdit as INAContext;
        }

//根据点图层确定最短路径所用经历的点
        private void LoadNANetWorkLocations(string strNAClassName, IFeatureClass inputFC, double dSnapTolerance)
        {
            INAClass pNAClass;
            INamedSet pNamedSet;
            pNamedSet = pNAContext.NAClasses;
            pNAClass = pNamedSet.get_ItemByName(strNAClassName) as INAClass;

            //删除已存在的位置点
            pNAClass.DeleteAllRows();

            //创建NAClassLoader,设置捕捉容限值
            INAClassLoader pNAClassLoader = new NAClassLoaderClass();
            pNAClassLoader.Locator = pNAContext.Locator;
            if (dSnapTolerance > 0)
                pNAClassLoader.Locator.SnapTolerance = dSnapTolerance;
            pNAClassLoader.NAClass = pNAClass;

            //字段匹配
            INAClassFieldMap pNAClassFieldMap = new NAClassFieldMapClass();
            pNAClassFieldMap.CreateMapping(pNAClass.ClassDefinition, inputFC.Fields);
            pNAClassLoader.FieldMap = pNAClassFieldMap;

            //pNAClassFieldMap.set_MappedField("OBJECTID", "OBJECTID");
            //pNAClassLoader.FieldMap = pNAClassFieldMap;

            //加载网络位置点数据
            int iRows=0;
            int iRowsLocated=0;
            IFeatureCursor pFeatureCursor = pInputFC.Search(null, true);
            pNAClassLoader.Load((ICursor)pFeatureCursor, null, ref iRows, ref iRowsLocated);
            ((INAContextEdit)pNAContext).ContextChanged();
        }
          //路径分析
             private void btnSolver_Click(object sender, EventArgs e)
            {
                this.Cursor = Cursors.WaitCursor;
                lstOutput.Items.Clear();
                lstOutput.Items.Add("分析中...");
                LoadNANetWorkLocations("Stops", pInputFC, 80);
                IGPMessages gpMessages = new GPMessagesClass();
                INASolver naSolver = pNAContext.Solver;
                SetSolverSettings();
                pNAContext.Solver.Solve(pNAContext, gpMessages, new CancelTrackerClass());

                if (gpMessages != null)
                {
                    for (int i = 0; i < gpMessages.Count; i++)
                    {
                        switch (gpMessages.GetMessage(i).Type)
                        {

                            case esriGPMessageType.esriGPMessageTypeError:
                                lstOutput.Items.Add("错误 " + gpMessages.GetMessage(i).ErrorCode.ToString() + " " + gpMessages.GetMessage(i).Description);
                                break;
                            case esriGPMessageType.esriGPMessageTypeWarning:
                                lstOutput.Items.Add("警告 " + gpMessages.GetMessage(i).Description);
                                break;
                            default:
                                lstOutput.Items.Add("信息 " + gpMessages.GetMessage(i).Description);
                                break;
                        }
                    }
                }

                axMapControl1.Refresh();
                lstOutput.Items.Add("Successful");
                this.Cursor = Cursors.Default;
             }