首页 > 代码库 > 如何实现复杂的导航功能

如何实现复杂的导航功能

本文要求读者具备如下知识和技术背景:

1 熟悉Java开发,知道如何正确的编译运行Java代码;

2 知道GIS的基本概念,知道地图导航的基本概念;

3 对GeoTools有一定的认识

 

一开始先来明确我们的任务:在基本的路径查询基础上

1 实现单行道限制

2 实现左右拐弯限制

3 实现动态路况限制

4 选择最短距离和最短时间

 

图和图的搜索

    要想了解路径查询的算法,首先得了解一下它的数学模型“图”。简而言之,图就是一系列的点和点之间的连接关系。【Graph】

    所谓路径查询,可以简化成对一个图的搜索。例如:从点6到点1的最短路径是,6-4-5-1,或者6-4-3-2-1,又或者6-4-5-2-3-4-5-1。如你所见,从6到1之间可以有许多条路径,其中第一条和第二条我们认为是合理的,第三条是不合理的,因为它有重复路段。所以查询节点间路径的算法就显得至关重要了。经典的查询算法有:Dijkstra和它的改进版本A*。这两个算法的实现各种语言都有,也很成熟了,我们不需要自己去写,但是最为一种训练,有兴趣的读者可以自己试着实现。

    我在这里只介绍一下基本概念。从前面的例子我们看到两点间可以有多条路径,但是实际上我们一般只关心一条路径,就拿开车来说,我们关心驾驶时间最少的路。一般情况下,实际距离短驾驶时间就少,所以我们先从实际距离入手。作为搜索算法如何确定距离最短呢。6-4-5-1一定比6-4-3-2-1距离短吗。显然我们不能仅仅根据节点的个数来判断距离。事实是我们除了拥有点和点之间的连接外,还需要连接的属性,这里就是距离。用上面的例子我们来指定距离:

6-4距离10

4-5距离7

5-1距离6

4-3距离2

3-2距离4

2-1距离1

6-4-5-1距离10+7+6=23

6-4-3-2-1距离10+2+4+1=17

    显然第二条路虽然节点多但是距离短。这里需要引人一个概念“开销”,在这个例子中目前我们使用路径距离来代表开销。我们总是选择开销小的路径。现实中影响驾驶时间的因素除了距离还有道路拥堵情况,所以我们增加属性,叫拥堵系数,假设距离乘上系数才是我们需要的开销:

6-4距离10  拥堵1

4-5距离7   拥堵2

5-1距离6   拥堵1

4-3距离2   拥堵13

3-2距离4   拥堵11

2-1距离1  拥堵11

6-4-5-1距离10*1+7*2+6*1=30

6-4-3-2-1距离10*1+2*13+4*11+1*11=91

    可以看到,虽然第二条路的实际距离短,但是由于拥堵情况严重,它的开销远大于第一条路。在这种情况下我们应该选择实际距离长的第一条路。我们可以不断对上面的计算进行完善,增加更多的属性来应对更复杂的实际情况。

 

分析任务

    有了上面的知识我们来看看我们的任务:

1 实现单行道限制

    我们可以给连接增加属性叫“行驶方向限制”,有三个值,分别是:“正向通行”,“反向通行”,“双向通行”。然后在计算开销的时候,判断当前方向是否与连接节点的方向一致,然后根据“行驶方向限制”的值来决定是否允许通行,如果不允许则返回一个极大值代表开销。

2 实现左右拐弯限制

    在实现单行线的基础上就可以实现拐弯限制,但是需要在数据制作上做文章:image

我们不能用一条线来代表一个路段,而应该用并行且方向相反的两条线,这样拐弯的地方也自然变成了单行线的一部分了。

3 实现动态路况限制

这个在上一节介绍图的时候已经说明了不在赘述。

4 选择最短距离和最短时间

这个在上一节介绍图的时候已经说明了不在赘述。

 

代码实现

代码  路网数据

改程序要求:

1 路网数据是Shapfile格式保存的线段数据

2 属性必须提供两个:

  id  整数

  type 整数  只有三个值 1:正向通行;-1:反向通行;0:双向通行

程序采用Java编写,利用GeoTools 11软件包中的graph扩展实现图的搜索。程序启动后需要先选择路网数据,然后可见主界面,在主界面地图上点击设置起止位置。不同方向会选择不同道路,如图:

image image