最佳路径分析是交通网络分析中最常用的一种分析功能。功能实现的是找出网络中两点之间阻力最小的路径,如果是对多个结点进行最佳路径分析,必须按照结点的选择顺序依次访问。阻力最小有多种含义,如基于单因素考虑的时间最短、费用最低、路况最佳、收费站最少等,或者基于多因素综合考虑的、路况最好且收费站最少等。
那么在SuperMap中,我们怎么来实现最佳路径分析呢?下面就跟着小编来一起看一看吧。
我们需要做什么准备?
首先,我们要理解在地理信息世界中,公共基础设施(电力设施、电信与有线电视网络、道路交通、水网等)被抽象为“网络系统”。网络系统是指有许多相互连接的线段构成的网状系统,网络模型是对现实世界中网络系统的抽象表达。例如在城市交通网中,道路等线状地物被抽象为线段,在网络中称为网络弧段;而十字路口、公交站点等点状地物被抽象为点,在网络中称为网络结点。在网络模型中,资源和信息能够沿着弧段,从一个结点到达另外一个结点。可以这么理解,网络就是边(线)和交汇点(结点)等元素共同组成的,表示了从一个位置到另外一个位置的可能路径。
我们必须要理解的基本概念
网络是由一组相互关联弧段、结点和它们的属性所组成的模型。网络用于表达现实世界中的道路、管线等。
如上图所示,网络不仅具有一般网络的弧段与结点间的抽象拓扑关系,还具有 GIS 空间数据的几何定位特征和地理属性特征(拓扑关系时地理对象在空间位置上的相互关系,如结点与线、线与面之间的连接关系)。
结点
结点是网络中弧段相连接的地方,如上图所示。结点可以表示现实中的道路交叉口、河流交汇点等点要素。结点和弧段各自对应一个属性表,它们的邻接关系通过属性表的字段来关联。
弧段
弧段就是网络中的一条边,弧段通过结点和其它的弧段相连接。弧段可用于表示现实世界运输网络中的高速路、铁路、电网中的传输线和水文网络中的河流等。弧段之间的相互联系是具有拓扑结构的。
网络阻力
现实生活中,从起点出发,经过一系列的道路和路口抵达目的地,必然会产生一定的花费。这个花费可以用距离、时间、货币等度量。在网络模型中,把通过结点或弧段的花费抽象成网络阻力,并将该信息存储在属性字段中,称为阻力字段。
障碍边和障碍点
城市中的交通堵塞问题随处可见,交通拥堵是没有规律可循、随机且动态变化的过程。为了实时地反映交通网络的现状,需要让交通堵塞的弧段具有暂时禁止通行的特性,同时在交通恢复正常后,弧段属性也能实时恢复正常。障碍边、障碍点概念的提出可以很好地解决上述问题。障碍边、障碍点引入的好处是障碍设置与否与现有的网络环境参数无关,具有相对独立的特性。
理解了关于网络数据集以及网络数据集相关的一些基本概念,我们就需要提前先来准备一套网络数据集。网络数据集怎么制作,可以参考之前的博客:https://blog.csdn.net/supermapsupport/article/details/100132171
注意:这里可能有人会有疑问,为什么明明是基于SuperMap C++实现最佳路径分析,但是上面博客中制作网络数据集的内容却是关于在iDesktop中构建网络数据集,这里统一解释一下,由于前期的数据处理,可能不仅仅涉及到构建网络数据集,包括数据导入、数据拓扑检查,对象属性修改编辑等等操作,如果所有操作都在组件开发层面去实现,会有一定的难度,而且没有必要,所以我们通常都是使用SuperMap提供的专门用于前期处理数据的iDesktop软件工作进行数据的入库,处理。使用其他功能的时候也是同样的道理,会先在桌面软件中,将数据制作完成,地图配图,保存为工作空间文件(*.smwu),组件开发直接打开数据即可,程序开发只实现业务需求。
关于如何打开数据,这里可以参考之前的博客:
环境配置(windows环境VS + Qt):SuperMap iObjects for C++ 入门详解(VS + Qt)_supermapsupport的博客-CSDN博客
环境配置(windows+MFC):SuperMap iObjects C++之MFC快速入门_supermapsupport的博客-CSDN博客_sumpermap c++配置
环境配置(Qt Creator):https://blog.csdn.net/supermapsupport/article/details/52609945
数据源管理:SuperMap iObjects C++之数据源管理_supermapsupport的博客-CSDN博客_supermap怎么打开udb数据源
好啦,到这里,我就假装你们都已经准备好了所需的网络数据集,接来下就看看具体的最佳路径在代码逻辑上是如何实现的吧。
下面以一个简单的代码例子来进行说明:
- 首先,从数据源里面拿到网络数据集,网络数据集的对象类型也是矢量数据集UGDatasetVector。
- 确定参加分析的站点,可以是两个点,也可以是多个点。数量大于等于2。
- 确定耗费字段,如果有其他耗费字段,可以自行新建一个字段,并且将对应的耗费值设置到网络弧段数据属性表里面,如果是直接根据距离来进行分析,可以直接使用系统字段smlength。
最佳路径分析的关键类:
UGNetworkAnalyst:网络分析基类,主要用于构造一个网络分析环境,设置用于参加分析的网络数据集,弧段标识字段、弧段起始结点 ID 的字段,容限等等环境参数;
UGPathAnalyst:交通网络分析类。 该类用于提供路径分析、旅行商分析、服务区分析、多旅行商(物流配送)分析、最近设施查找和选址分区分析等交通网络分析的功能。
UGAnalyseParams:交通网络参数及结果类,设置权重字段,以及返回结果类型等等参数。
最佳分析关键代码如下:
传入的参数:
netDataset:上面第一点所说的网络数据集;
Points:参加分析的点串数据;
costFiled:耗费字段,这里直接添加字段名称即可。
最后的返回值:就是最佳路径的线对象。
具体实现代码参考:
UGGeoLine* MMapControl::FindPathByNetWork(UGDatasetVector* netDataset, UGPoint2Ds Points,UGString costFiled)
{
try {
UGGeoLine* geoline_result = new UGGeoLine();
//构造一个最佳路径分析环境设置对象
UGNetworkAnalyst* pUGTrafficAnalyst = new UGNetworkAnalyst();
//构造一个最佳路径分析对象
UGPathAnalyst* pUGPathAnalyst = new UGPathAnalyst(pUGTrafficAnalyst);
//权重字段信息
UGCostFields CostFiled;
UGArray<UGCostFields> strCostFiledName;
strCostFiledName.SetSize(1);
CostFiled.strCostName = costFiled;
CostFiled.strFTField = costFiled;
CostFiled.strTFField = costFiled;
strCostFiledName.SetAt(0, CostFiled);
//设置网络数据集
pUGTrafficAnalyst->SetDatasetNetwork(netDataset);
//设置网络数据集中标志结点ID的字段
pUGTrafficAnalyst->SetNodeIDField(_U("SmNodeID"));
//设置网络数据集中标志弧段 ID 的字段
pUGTrafficAnalyst->SetArcIDField(_U("SmEdgeID"));
//设置网络数据集中标识弧段起始结点 ID 的字段
pUGTrafficAnalyst->SetFNodeIDField(_U("SmFNode"));
//设置网络数据集中标志弧段终止结点 ID 的字段
pUGTrafficAnalyst->SetTNodeIDField(_U("SmTNode"));
//设置点到弧段的距离容限
pUGTrafficAnalyst->SetNodeInterval(50);
//设置一个阻力别名为耗费
pUGTrafficAnalyst->SetCostFields(strCostFiledName);
//创建邻接矩阵
pUGTrafficAnalyst->DeleteAdjMatrix();
if (!pUGTrafficAnalyst->CreateAdjMatrix())
{
//TRACE("创建邻接矩阵失败");
return NULL;
}
//TRACE("创建邻接矩阵成功");
//参数设置
UGAnalyseParams AnalyseParams;
//设置权值字段
UGString strCostName = pUGTrafficAnalyst->GetFirstCostName();
AnalyseParams.strCostName = strCostName;
//设置结果结构,返回路由及途径节点
AnalyseParams.nOptions = -1;
//设置分析点
AnalyseParams.arrViaPoints = Points;
//结果信息存储
UGResultInfo ResInfoOut;
ResInfoOut.Clear();
//最佳路径分析
if (!pUGPathAnalyst->FindPath(AnalyseParams, ResInfoOut, false))
{
//TRACE("最佳路径分析失败");
return NULL;
}
//TRACE("最佳路径分析成功");
UGArray<UGGeoLineM> arrLineM = ResInfoOut.arrLineM;
//UGGeoLine geoline;
UGGeoLineM lineM = arrLineM.GetAt(0);
lineM.ConvertToLine(*geoline_result, 10);
return geoline_result;
} catch (double d) {
//return NULL;
}
}
分析结果:
拿到结果的geoline后,我们可以将结果对象添加到跟踪图层进行临时展示。
注意:
- 站点必须位于网络弧段和网络结点上,或者在设定的容限范围的区域。可以在“分析环境”窗口中,对结点捕捉容限进行设置,修改合适的容限大小。
- 如果存在障碍点,可以在分析的时候,设置障碍点参数AnalyseParams.arrBarrierNodeID。
- 如果存在障碍边,也就是有一条弧段数据是不通的情况下,就可以将这条弧段设置为障碍边,分析的时候,设置障碍边参数AnalyseParams.arrBarrierArcID。