本文要求讀者具有以下知識和技術背景:java
1 熟悉Java開發,知道如何正確的編譯運行Java代碼;git
2 知道GIS的基本概念,知道地圖導航的基本概念;github
3 對GeoTools有必定的認識。算法
一開始先來明確咱們的任務:在基本的路徑查詢基礎上url
1 實現單行道限制spa
2 實現左右拐彎限制blog
3 實現動態路況限制ip
4 選擇最短距離和最短期開發
圖和圖的搜索get
要想了解路徑查詢的算法,首先得了解一下它的數學模型「圖」。簡而言之,圖就是一系列的點和點之間的鏈接關係。【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 實現左右拐彎限制
在實現單行線的基礎上就能夠實現拐彎限制,可是須要在數據製做上作文章:
咱們不能用一條線來表明一個路段,而應該用並行且方向相反的兩條線,這樣拐彎的地方也天然變成了單行線的一部分了。
3 實現動態路況限制
這個在上一節介紹圖的時候已經說明了不在贅述。
4 選擇最短距離和最短期
這個在上一節介紹圖的時候已經說明了不在贅述。
代碼實現
改程序要求:
1 路網數據是Shapfile格式保存的線段數據
2 屬性必須提供兩個:
id 整數
type 整數 只有三個值 1:正向通行;-1:反向通行;0:雙向通行
程序採用Java編寫,利用GeoTools 11軟件包中的graph擴展實現圖的搜索。程序啓動後須要先選擇路網數據,而後可見主界面,在主界面地圖上點擊設置起止位置。不一樣方向會選擇不一樣道路,如圖: