真实地图最短路径规划(A*算法)

article/2025/1/11 3:02:25

本文将研究矢量地图以及A*算法等系统关键的技术支持。在实现的过程中,还引入了高德出行API、聚焦类爬虫、OpenStreetMap开源地图,二叉堆等技术。

通过解析OpenStreetMap提供的地图数据,获取不同类型的交通路网信息。然后将A*算法应用于路网数据中,并引入真实地理距离作为矢量地图的参数权重。最终找到两地之间的最短路径方案,成功的实现预期目标。

流程:

  1. 获取地图数据/路网数据化存储

  2. 不同路网数据获取(公共交通,机动车,自行车道,人行道....)

  3. 应用A*算法于地图中

地图路径规划的本质是遍历地图中的所有节点,然后找到最短路径的过程[8]。算法中的图是由大量节点和连接节点之间的线组成的。这里说的节点指的是现实生活中的每一个分叉路口,只要出现需要选择方向的时候,在地图上呈现的就是一个节点(vertices)[14]。而连接节点的线则是指现实生活中的道路,例如上海的南京西路,它在地图上的数据身份是一个边(edge)。每一条边都带有相对应的权重,即现实世界中的物理距离。图拥有两种类型,即有向图和无向图。有向图指的是带有方向的边,即a指向b的边和b指向a的边是两种不同的边。这两条边,在无向图中则是同一条边。

根据周小镜的描述,最短路径算法的基础是将图中的节点遍历[8]。由于实际路网的复杂性,节点的遍历有可能会出现从某一顶点选择一条边搜索后,该边又与带有该顶点的另一条边相交[8]。从而导致该顶点的重复遍历。因此在遍历地图的过程中,需要对已访问过的节点进行标记,以防重复遍历的出现[8]。

A*算法的关键在于启发函数,即F(n)=G(n)+H(n)。F(n)指代起始节点到目标节点的总代价。G(n)表示当前节点n到起始节点的当前代价。H(n)则表示当前节点n到目标节点的预估代价。依据这个函数,从而使得每一个被搜索的节点n都有一个总代价F(n)。然后选择其中最小的总代价节点作为下一步节点。接着继续计算新加入的节点的F(n),如此,循环。

1.获取地图数据/路网数据化存储

将实际路网信息变成节点和边的数据结构形式并存储。以上海市交通路网为例。首先,通过OpenStreetMap(OSM)提供的Overpass API Query Form获取XML格式的上海市交通路网的信息。

在该XML文件中,可以发现,地理数据的数据结构是带有拓扑性质的数据。地理信息系统的点,线,面以及它们之间的关系通过XML中node,way和relation进行分别描述。各自标签下的tag用于记录其标签的属性信息。

<node>标签记录路网节点信息,它包含经度和纬度,是<way>标签的组成部分。

<way>标签记录路的信息,是一个包含大量<nd>的集合。其属性包含街道,高速公路等信息。 

<relation>标签将<way>和<node>结合在一起用于描述地理事物,例如公交路线和自行车道。

接着,使用ElementTree(元素树)方式对XML文件进行解析。该方式类似一种轻量级的DOM。相对于拥有大量函数的Simple API for XML(SAX)方法和需要将XML数据映射到内存中的树的Document Object Model(DOM)方法。ElementTree可以以更容易被理解的代码形式和更快的速度解析XML。通过ElementTree方法遍历获得搜索所有的<node>和<way>标签并定位。然后,导入Networkx库。下图展示的就是以实例化对象Map中的路网信息所绘制的SVG格式的上海市交通道路路网。 

2.不同路网数据获取

OpenStreetMap提供的XML文件中包含了许多不同类型的道路信息,例如公共交通道路,机动车道路,自行车道路或人行道道路等等。

本段将基于OpenStreetMap提供的数据结构解析出公共交通路线数据。公共交通道路信息主要被存储与<relation>标签中,作为<relation>的子标签。图14中展示的是公共交通路网中某一个<relation>标签的数据结构。根据OSM的官方网站中提供的XML中<relation>标签的数据结构,图15展示的是其<tag>子标签的各类属性和值,图16展示的是其<member>子标签的各类属性和值。<member>标签中的“type”属性node和way分别表示节点和道路,“ref”表示对应的ID号,“role”表示对应的类型是站点或站台。<tag>标签中的“k”表示属性,“v”表示值。当k=“route”是,v中的值可以代表道路类型,即公交车,地铁,人行道,有轨电车,火车等等。通过定位不同的<tag>标签还可以解析获取线路的方向,站点名称等多样化的信息。

图14: 

图15: OpenStreetMap官网上<relation>中<tag>属性值内容解析

图16: OpenStreetMap官网上<relation>中<member>属性值内容解析

解析公共交通路网数据的步骤如下。首先,需要确定当前标签记录的是道路信息,即<tag k=”type” v=”route”>。接着,确定道路的类型,公交,地铁,无轨电车和电车,即<tag k=”route” v=”bus/trolleybus/subway/tram”>。然后,收集<tag>标签中属性为“name”的值,以得到该条公共线路的起始站和终点站的站点信息。其次,遍历该<relation>标签下的<member>子标签中记录着way和node的ID信息并保存。最后,根据存储的ID信息获取对应的way和node的经度和纬度并存储。图17展示的是公共交通路网数据提取步骤的流程图。

TIP: 由于openstreetmap是一款国外的开源地图数据。因此国内路网数据上会存在一些缺失的现象,导致线路信息不完整。 例如,上海的公共交通线路数据,在openstreetmap中仅有少数线路。下图所示:

3.应用A*算法(A*算法应用于真实上海交通路网)

真实的交通路网地图区别于游戏中的栅格地图不同之处在于,真实的交通路网中的子节点扩展方式是找寻该父节点的最近直系节点,而不是节点的上下左右方位上的四个节点。它们之间的距离也不是固定为1,而是需要通过两节点的经度和纬度进行计算。

在寻找的过程中将使用韩忠民提供的两点的经纬度计算距离的近似公式[16]。假设有A, B两地,它们的纬度和经度分别是(lat1, lon1)和(lat2, lon2)。公式中S表示两地之间的距离(千米),a表示AB两地纬度之差(lat1-lat2),b表示AB两地经度之差(lon1-lon2),6378.137表示地球的半径(千米)。使用该公式计算出的距离精度和谷歌地图的距离精度误差在正负0.2米之内[16]。

然后,遍历地图中所有节点的经度和纬度。将其与起始地和目的地的经度和纬度进行距离计算,找出一定范围内的所有节点,并使用起始列表和目的列表分别保存被找到的节点的ID。接着,将起始列表中的所有节点于目的列表中的所有节点进行组合。两节点组合结果将作为Map对象中的起始节点和目的节点代入A*算法中。Map对象中的节点(node)间的地理距离也将使用韩忠民的距离近似函数进行计算,然后作为Map对象中边(edge)的权重。将节点组合代入A*算法中进行最优路径的寻找,如果不存在路径则会抛出异常。但如果两个节点列表中的所有节点组合的经度和纬度都不能通过A*算法找到它们之间的最优路径,则会扩大附近节点的搜索范围,每次增加10米。直到两个节点列表中出现可以找到最优路径的节点组合,搜索范围不再扩大,程序进入下一步运算。随后,将所有没有抛出异常的节点组合存放在字典中,并找到其中路径方案距离最小的节点组合。输出其节点组合中A*算法返回的字典回溯中的节点ID。将这些节点按照输出顺序进行连接,即可得到两节点之间的最短路径。

结束

最终测试:(图中显示的是整理过的路径规划数据,但后续还需再整理)

相比较高德地图app:

该项目的缺点:(亲自测试过的)

  • openstreetmap的数据不完整性。
  • 高德api存在的数据不确定性。
  • openstreetmap中的数据还需要进一步整理(当然了,按照上述方式10米10米的增加,可以解决部分路径规划问题。但这并不是真正的解决方案,具体请翻阅【陈舒燕. 基于OpenStreetMap的出行可达性分析与实现[D].上海师范大学,2010.】,上面有数据整理的方法。
  • 道路两节点之间取的是直线距离,未考虑道路弯曲的情况。

参考文献:

8. 周小镜. 基于改进A*算法的游戏地图寻径的研究[D].西南大学,2011.

14. 严寒冰,刘迎春.基于GIS的城市道路网最短路径算法探讨[J].计算机学报,2000(02):210-215.

16. 韩忠民.知经纬度计算两点精确距离[J].科技传播,2011(11):196+174.


http://chatgpt.dhexx.cn/article/284pC02G.shtml

相关文章

OpenLayers入门,使用OpenLayers叠加多边形、圆形、线段和点要素到地图上

专栏目录: OpenLayers入门教程汇总目录 前言 本章详细介绍一下如何使用OpenLayers叠加多边形、圆形、线段和点要素到地图上,并设置样式。 要叠加这些元素到地图上,首先要理解OpenLayers的结构。就如同photoshop这些图像编辑软件和游戏引擎一样,OpenLayers是基于图层(laye…

unity+高德定位=pokemon go 山寨demo安卓版

这两周尝试了下用高德地理定位和Unity来做个山寨的pokemon go的demo&#xff0c;只能在安卓下使用。 游戏过程视频&#xff1a; http://www.bilibili.com/video/av6836823/ apk下载&#xff1a; http://download.csdn.net/detail/wuyt2008/9665294 源码下载&#xff1a; h…

腾讯位置服务开发应用-使用教程,案例分享,知识总结

文章目录 前言一、腾讯位置服务是什么&#xff1f;二、使用步骤1.uniapp开发map说明介绍markers属性-类型为数组Arraymarker 上的气泡 callout&#xff08;Object类型&#xff09;marker 上的标签 label&#xff08;Object类型&#xff09;polylinepolygoncirclescontrolsposit…

Unity基于GPS获取当前位置并将地图瓦片置于一个平面上

unity版本&#xff1a;2019.1.0f2 1.需要高德地图的key&#xff0c;去官网搞一个就行->高德的静态地图教程 2.然后将脚本挂在一个plane&#xff08;Map_Tile&#xff09;上就行了 3.加一个button&#xff0c;并将Onclick设置为下面的样子就完事了&#xff0c;然后导出&#…

微信小程序获取地理位置失败原因及解决方案

微信小程序获取用户地理位置失败的原因主要有3种情况&#xff1a; 1. 手机系统设置中地理位置未开启 2. 系统未给微信app授权 3. 用户未给小程序授权地理位置信息 所以需要继续完善下定位失败的处理逻辑。 1. 在获取地理位置信息失败后&#xff0c;首先判断用户手机系统定位服务…

百度、高德、腾讯、天地图、谷歌、必应地图切片切图工具 MapCutter(旧名MapTiler),支持超大图、高清切片、webgl、leaflet、maptalk、openlayers、cesium等

# MapCutter MapCutter 是制作覆盖图/瓦片图/金字塔图/游戏地图/切图切片的工具&#xff0c;它支持百度、腾讯、高德、天地图、谷歌、必应地图、MapBox等地图服务&#xff0c;是市面上最易用的同类软件&#xff0c;并支持js、webgl、leaflet、maptalks、openlayers、cesium 等…

java获取输入的地点的经纬度和编码等信息

我的苦衷 对于不规则,无序的数据做数据清洗,使之可以在GIS地图上展示出来数据。在地图上展示出来倒是不难,难的是如何对这些不规则,无序的数据做数据清洗,拿到每个的经纬度呢? 原始数据分析 数据清洗后的数据都有公司名称,还有地点,能到区。那这个就好办了。 既然我…

视频教程-Web前端开发仿美团/饿了吗移动App之高德地图接口对接案例-JavaScript

Web前端开发仿美团/饿了吗移动App之高德地图接口对接案例 互联网编程行业10年开发和授课经验 曾任太极集团&#xff0c;外资企业等一线互联网python高级开发工程师 现任聚焦计算机技术有限公司项目组担任架构师及项目经理 精通&#xff1a;python/php/web前端开发技术以及unity…

大数据之数据清洗之爬取数据后如何根据地名或者公司名获取经纬度信息-地址逆解析经纬度

关于本文章说明: 本文章的想法来源于:爬了大量的数据后,想利用GIS技术把数据展示在地图上。但是爬的数据又没有经纬度坐标,就无法在地图上进行展示了,所以用了百度地图的正/逆地理编码。计算机行业招聘智能分析平台效果

微信小程序地图获取地点信息(打卡签到功能为例)-2020-7-26

目录 微信小程序地图获取地点信息(打卡签到功能为例) 效果图前提步骤 首先需要了解的代码部分 配置性代码功能性代码demo 下载 微信小程序地图获取地点信息(打卡签到功能为例) 解决方案&#xff1a;利用微信小程序的地图组件获取到用户的地理位置信息(经纬度)&#xff0c;再通过…

IOS高德地图逆地理编码定位+网络判断

先说下这功能的流程&#xff0c; 流程:判断用户是否联网--->获取用户地理位置经纬度--->通过经纬度去查询地理位置名称 //高德地图 property (nonatomic, strong) MAMapView *mapView;//高德地图 property (nonatomic, strong) AMapSearchAPI *search; property(nonatom…

如何制作专业的手绘地图(电子地图、智慧导览系统)

一、智慧导览系统介绍 手绘电子地图&#xff0c;就是把手绘地图覆盖到地图上&#xff0c;游客或者普通用户&#xff0c;可以在手机上通过地图的链接&#xff08;或者现在流行的小程序&#xff09;打开使用。是一种使用非常方便&#xff0c;集**“视、听、路径规划、实时导航”*…

js技术调用高德api实现精准定位

我先说下写这个程序的起因&#xff0c;昨天晚上我的一个朋友在淘宝上卖它玩了两年的光遇号。 号给淘宝商家了就不理人也不给钱了&#xff0c;因为没有订单记录淘宝官方不管。这种回收游戏账号的微信账号的十有九骗。在黑猫上就能查到各种回收账号的诈骗案件。 于是我给我朋友写…

vue + 高德精准定位(示例)

鱼弦:CSDN内容合伙人、CSDN新星导师、51CTO(Top红人+专家博主) 、github开源爱好者(go-zero源码二次开发、游戏后端架构 https://github.com/Peakchen) 使用Vue和高德精准定位可以实现基于Vue框架的精准定位功能。下面是对该方法的原理、使用场景、文献材料链接以及当前使…

CocosCreator系列——接入高德地图sdk获取经纬度信息图文详解

CocosCreator接入高德地图sdk获取经纬度信息图文详解 先看效果 1.首先去 高德开放平台.申请key 接下来该获取发布版和调试版的SHA1了&#xff0c;首先打开cmd命令窗口 输入命令&#xff1a;cd .android(首先进入用户系统的安卓文件夹) 然后输入命令&#xff1a;keytool -li…

反应式编程框架设计:如何使得程序调用不阻塞等待

前言&#xff1a; 程序在高并发的情况下&#xff0c;程序容易崩溃。主要的原因是&#xff1a;在高并发的情况下&#xff0c;有大量用户请求需要程序计算处理&#xff0c;而目前的处理方式是&#xff0c;为每个用户请求分配一个线程&#xff0c;当程序内部因为访问数据库等原因…

TensorFlow编程框架基础

一、为什么要使用编程框架 深度学习的算法具有多层结构&#xff0c;每层的运算由一些基本操作构成&#xff0c;这些基本操作中存在大量共性运算&#xff0c;如卷积、池化、激活等。 将这些共性运算操作封装起来&#xff0c;可以提高编程实现效率。 面向这些封装起来的操作&am…

c语言编程框架_编程语言和框架的状态

c语言编程框架 作为专业的软件交付人员&#xff0c;我喜欢掌握技术趋势和“市场可能走向何方”。 在过去的十五年中&#xff0c;已经出现了许多语言和框架&#xff0c;并且几乎没有任何真正的持久力。 为了在“人们想知道的事情”上适销对路&#xff0c;使我知识广博&#xff0…

MFC编程框架总结

简介 MFC是一种C类库&#xff0c;利用面向对象的方法封装了Windows API&#xff0c;为Windows应用程序的开发带来了极大便利。本文总结了使用MFC进行编程的基本方法&#xff0c;编程环境为VS2008 SP1。 搭建MFC开发环境 由于使用MFC应用程序向导后VS会自动生成应用程序框架&am…