最短路径分析属于ArcGIS的网络分析范畴。而ArcGIS的网络分析分为两类,分别是基于几何网络和网络数据集的网络分析。它们都可以实现最短路径功能。下面先介绍基于几何网络的最短路径分析的实现。以后会陆续介绍基于网络数据集的最短路径分析以及这两种方法的区别。
几何网络是一种特殊的特征要素类,由一系列不同类别的点要素和线要素(可以度量并能图形表达)组成的,可在FeatureDataset下面创建, 可进行图形与属性的编辑。包括流向分析和追踪分析两大功能。主要接口是ITraceFlowSolver。我们先在一幅地图上做出一个几何网络才能进行最 短路径分析。下面是主要的一些步骤(ArcMap帮助中琐碎的说明有三四十项,被我省略很多):
1、打开ArcCatalog,连接到包含地图的文件夹。
2、在空白处,右键新建一个“Personal GeoDatabase”。
3、在生成的Personal GeoDatabase上右键新建一个feature dataset。
4、双击Personal GeoDatabase进去,找到刚才new出的feature dataset,右键Import导入Feature Class(Single),选择要建立几何网络的图层或者shape文件。
5、然后再右键新建一个Geometric Network,选择从已存在的图元中建立几何网络。
6、打开ArcMap,把刚才建立的“Personal GeoDatabase Feature Class”添加到地图中,这样几何网络就建立好了。
这样我们就建立好一个几何网络了。我们现在要通过编程来实现最短路径,用到的接口主要有 INetworkCollection,IGeometricNetwork,IPointToEID,ITraceFlowSolverGEN(它实现 了ITraceFlowSolver的接口),INetSchema,IEIDHelper等。主要步骤如下:
1、获取几何网络工作空间
2、定义一个边线旗数组,把离点串最近的网络元素添加进数组
3、设置开始和结束边线的权重
4、进行路径分析
5、得到路径分析的结果
上次介绍了用几何网络实现的“最短路径”,这次用网络数据集实现真正的最短路径功能,跟上次一样,先处理下数据。
1、先打开ArcCatalog,连接到目标文件夹,假定该文件下有一个名为road的道路图层。
2、在road图层上右键新建一个网络数据集,并按照其默认设置直至完成。
3、打开该地图的工作空间,把刚才新建的网络数据集添加工作空间中。
4、在网络分析菜单中选择新建最近设施点。
这时在工作空间里,可以看到多了一个名为“Closest Facility”的图层。它下面还有4个子图层,名字分别为
“Facilities”,“Incidents”,“Barriers”,“Routes”。“Facilities”就是设施点图层,也就是目的
点,“Incidents”的意思就是出发点,“Barriers”是障碍点,意思就是地图某条道路附近有一个障碍点,如果障碍点与道路距离在容限范围
内,则表示此道路不通,“Routes”就是最终的结果。这样我们编程实现最短路径的思路就出现了:
1、添加出发点。
2、添加目的点。
3、生成最优路径,获取结果。
这里的添加出发点或者目的点,是往“Facilities”或“Incidents”图层上添加元素。获取结果也是从“Routes”中获取
Polyline。往“Facilities”或“Incidents”图层上添加元素用到的主要方法是INALocator的
QueryLocationByPoint函数,生成路径主要接口是INASolver和它的Solve方法。获取结果是按属性查找,因为
“Routes”类其实就是一个图层类,只不过只是存在于内存。
CMapControlDefault m_map; IPointCollectionPtr m_ipPointCollection; ILayerPtr ipLayer = m_map.GetLayer(0); // 网络数据集 INALayerPtr ipNaLayer = ipLayer; if (NULL == ipNaLayer) { return; } INAContextPtr ipNaContext; HRESULT hr = ipNaLayer->get_Context(&ipNaContext); INAClassLoaderPtr ipNAClassLoader(CLSID_NAClassLoader); INALocatorPtr ipNALocator = NULL; hr = ipNaContext->get_Locator(&ipNALocator); ipNALocator->put_SnapToleranceUnits(esriMeters); ipNALocator->put_SnapTolerance(200); ipNaContext; hr = ipNAClassLoader->putref_Locator(ipNALocator); INamedSetPtr ipNamedSet = NULL; ipNaContext->get_NAClasses(&ipNamedSet); CString szName = "Facilities"; BSTR bstrName = szName.AllocSysString(); INAClassPtr ipNAFacilitiesClass = NULL; hr = ipNamedSet->get_ItemByName(bstrName, (IUnknown**)&ipNAFacilitiesClass); szName = "Incidents"; bstrName = szName.AllocSysString(); INAClassPtr ipNAIncidentsClass = NULL; hr = ipNamedSet->get_ItemByName(bstrName, (IUnknown**)&ipNAIncidentsClass); szName = "CFRoutes"; bstrName = szName.AllocSysString(); INAClassPtr ipNARoutesClass = NULL; hr = ipNamedSet->get_ItemByName(bstrName, (IUnknown**)&ipNARoutesClass); INALocationPtr ipNALocation1(CLSID_NALocation); INALocationPtr ipNALocation2(CLSID_NALocation); ipNAClassLoader->get_Locator(&ipNALocator); IPointPtr ipBeginPoint(CLSID_Point); m_ipPointCollection->get_Point(0, &ipBeginPoint); IPointPtr ipEndPoint(CLSID_Point); m_ipPointCollection->get_Point(1, &ipEndPoint); IPointPtr ipPoint1(CLSID_Point); IPointPtr ipPoint2(CLSID_Point); double dbLVal = 0.0; ipNALocator->QueryLocationByPoint(ipBeginPoint, &ipNALocation1, &ipPoint1, &dbLVal); ipNALocator->QueryLocationByPoint(ipEndPoint, &ipNALocation2, &ipPoint2, &dbLVal); INALocationObjectPtr ipNALocationObject = NULL; IFeatureClassPtr ipFeatureClass = ipNAIncidentsClass; IFeaturePtr ipFeature = NULL; ipFeatureClass->CreateFeature(&ipFeature); IRowSubtypesPtr ipRowSubtypes = ipFeature; ipRowSubtypes->InitDefaultValues(); ipFeature->putref_Shape(ipBeginPoint); ITablePtr ipTable = NULL; ipFeature->get_Table(&ipTable); long nIndex = 0; szName = "Sequence"; bstrName = szName.AllocSysString(); ipTable->FindField(bstrName, &nIndex); VARIANT var_int; var_int.intVal = 1; var_int.vt = VT_INT; ipFeature->put_Value(nIndex, var_int); szName = "Name"; bstrName = szName.AllocSysString(); ipTable->FindField(bstrName, &nIndex); ipFeature->put_Value(nIndex, COleVariant("Start Point")); ipNALocationObject = ipFeature; ipNALocationObject->put_NALocation(ipNALocation1); ipFeature->Store(); IFieldsPtr ipFields(CLSID_Fields); hr = ipTable->get_Fields(&ipFields); long nFieldCount = 0; hr = ipFields->get_FieldCount(&nFieldCount); for (int k = 0; k < nFieldCount; k++) { IFieldPtr ipField(CLSID_Field); ipFields->get_Field(k, &ipField); BSTR bstrFieldName; ipField->get_Name(&bstrFieldName); CString szFieldName = bstrFieldName; } ipFeatureClass = ipNAFacilitiesClass; ipFeatureClass->CreateFeature(&ipFeature); ipRowSubtypes = ipFeature; ipRowSubtypes->InitDefaultValues(); ipFeature->putref_Shape(ipEndPoint); ipTable = NULL; ipFeature->get_Table(&ipTable); nIndex = 0; szName = "Sequence"; bstrName = szName.AllocSysString(); ipTable->FindField(bstrName, &nIndex); var_int.intVal = 2; ipFeature->put_Value(nIndex, var_int); szName = "Name"; bstrName = szName.AllocSysString(); ipTable->FindField(bstrName, &nIndex); ipFeature->put_Value(nIndex, COleVariant("End Point")); ipNALocationObject = ipFeature; ipNALocationObject->put_NALocation(ipNALocation2); ipFeature->Store(); INAClosestFacilitySolverPtr ipNACFSolver = NULL;