如何在Google Static Map上顯示超長路徑?

為了讓PrintMyMap的使用者可以感受地圖折好之後的樣子,我利用了Google Static Maps API畫出地圖,再利用CSS3 2d transform把地圖稍作變形,套在預先畫好的背景上。雖然Google Static Maps API解決了我需要將地圖變形的需求,但是有一些限制卻隨之而來。如果有用過Google Static Maps API,就應該會知道它其實只是一張利用URL傳送參數而產生的圖片。雖然Google Static Maps API的文件裡面沒有限制參數的長度,不過既然是使用URL傳送參數就會因為瀏覽器和伺服器端的實作而產生長度限制。
URL長度限制
如果URL長度過長,Google就會吐一個Request-URI Too Large的訊息回來。我用Google Chrome實際測試的結果,長度上限約在1800字元左右。

而這種情況在要顯示超長路徑(如:GPS Tracker紀錄或是路徑規劃產生的路徑)時很容易發生,因為每一個點的經緯度要精確到小數點以下六位,所以每一個點就要將近20個字元,一百個點不到就會超過長度限制。
以下面的這個路徑為例:
path=rgb:0x0000ff,weight:5|40.737102,-73.990318|40.749825,-73.987963|40.752946,-73.987384|40.755823,-73.986397
只有兩個點就已經用掉了110個字元。
比如下面這個路徑規劃的結果,有兩百多個點,在Google Maps API v3上可以正常顯示。

在Google Static Maps API上,我為了不讓URL長度爆掉,只好限制只顯示80個點,就產生了路線不完整的現象。

所以唯一的解法就是簡化路徑,把一些點去除掉,並盡可能保持形狀。簡化路徑最普遍使用的演算法就是道格拉斯-派克爾法(Ramer–Douglas–Peucker algorithm)。
道格拉斯-派克爾法
![]()
credit: 維基百科
道格拉斯-派克爾法的做法就是保留頭尾兩點。將頭尾用一條直線連接,接著找出中間每個點距離這個最大的值b,接著保留這個距離頭尾連接起來的直線最遠的點c。然後設定一個容許值,這個容許值必須小於b。再檢查中間每個點到直線的距離,如果距離大於容許值,就保留這個點。然後用c點,把這條路徑分為兩部分,再依照前面的方法一直做下去。
GDouglasPeuker.js
如果要在Google Maps API或Google Static Maps API上使用道格拉斯-派克爾法,我們可以直接用Bill Chadwick寫好的GDouglasPeuker.js。GDouglasPeuker.js是可以免費使用的,不過如果你覺得它很有用,不妨到Bill Chadwick的網站上去donate一下。
GDouglasPeuker.js內只包含了GDouglasPeucker(source, kink)這個function。
source是LatLng組成的陣列,而kink是容許值(以公尺為單位)。
容許值的設定要特別注意,因為設定得太小,資料量還是很大,不一定能夠顯示。太大的話資料又壓縮過度,無法呈現細節。
以下以成田機場到汐留的開車路線為例,測試容許值。
GDouglasPeucker(route, 10)
壓縮不足,所以還未到終點就已經達到URL長度上限。
GDouglasPeucker(route, 50)
壓縮足夠,已經能夠在URL長度限制內顯示路徑。
GDouglasPeucker(route, 125)
看起來和容許值50時一樣,但資料量更少,因此此容許值比50更好。
GDouglasPeucker(route, 1000)
壓縮更多,路徑稍稍失真。
GDouglasPeucker(route, 2000)
繼續壓縮,路徑失真更嚴重。
GDouglasPeucker(route, 5000)
繼續壓縮,畫出來的路徑幾乎沒有意義。
從以上的測試可以發現容許值125的設定最佳,壓縮程度夠,也能夠忠實呈現原始路徑。
而這個值是怎麼算出來的呢?
我的想法是當兩個座標點被繪製在地圖上並沒有意義,因為地圖上根本會被當成同一個點,因此如果要呈現和未壓縮的路徑完全相同的地圖,最大的容許值就應該是一個像素所代表的實際長度,即地面解析度。
而依照這篇文章對於地面解析度的所推導出來的地面解析度公式為:
ground resolution = (cos(latitude * pi/180) * 2 * pi * 6378137 meters) / (256 * 2level pixels)
換成javascript語法就變成:
Math.cos(map.getCenter().lat() * Math.PI/180) * 2 * Math.PI * 6378137 / (256 * Math.pow(2,map.getZoom()));
套用上面的數值所計算出來的結果為124.13320927642286,這就可以解釋為什麼上面幾個容許值以125最佳了。
Comments
39 Responses to “如何在Google Static Map上顯示超長路徑?”
Leave a Reply


[...] This post was mentioned on Twitter by MacTalks, bluesaturn. bluesaturn said: 分享 http://www.lis186.com/?p=1945 (如何在Google Static Map上顯示超長路徑?) http://plurk.com/p/6iyti6 [...]
哈哈,很有趣,這篇很有意思!
学习了,网上能人辈出,俺可是个菜鸟任务(>_<)
这么远啊 画画就是简单~
果然内涵。。。
仔细看了看你的博客,觉得,还不错。如果有机会在外包领域合作。我很期待。
文章不错,值得顶!!
http://www.gtrip.net
Достаточно интересная и познавательная тема
这个超长路径地图是不是可以在电子导航仪上显示呢?
你好啊,我是璇璇,很高兴能在你这留言。想和你交个朋友!
Думаю, какую полезную информацию можно извлечь из этого материала
云彩从天上飘过,我从这里踩过!
GOOD!很好!
最近如何。咋没回访哦
我来也,看看您的博客,貌似不错,O(∩_∩)O
家好,我是做成人用品网店的,经营各类成人玩具,情趣内衣 、安全套,各类药物,保证 正品,价格公道,欢迎各位光临,淘宝店:http://chengren365.taobao.com 本店专用QQ:1342920373
文章不错,受益匪浅,顶!!
你好,文章写的不错!!
http://www.cne.cc
文章写的很不错。
貌似写的不错,嘿嘿,下次再来~走也~
网站文章写的很不错,RSS已经被我订阅了!
太详细了,谢谢了
文章写的真不错,我要好好向你学习~~~~~~
似乎有点道理
Распланировали свои майские праздники?
空虚的
67T59I akoartfogagb, [url=http://tzlgbyprrlwt.com/]tzlgbyprrlwt[/url], [link=http://fkhhiifzfgmc.com/]fkhhiifzfgmc[/link], http://hijreipdqoxr.com/
XONRHl bxnlhexvheon, [url=http://ssynkvvfrqtr.com/]ssynkvvfrqtr[/url], [link=http://lrfjsaouqasv.com/]lrfjsaouqasv[/link], http://pghapgpyaygr.com/
谢谢分享,又学习了一招了
呵呵,好玩!
低调的飞过
写的很详细
详细,好玩!CUTE!
学习了。。
写的很详细,支持下
很不错啊。。。。
地板中。。。