http://baixiaozhe.iteye.com/blog/931814
原帖:http://blog.sina.com.cn/s/blog_65bd7eef0100hu5o.html
由於受到國家一些法律法規限制,所有的電子地圖服務提供商都需要給地圖數據加上偏移和加密,因此廣受大家關注的google地圖也不例外。但是作為一些用慣了免費服務的網友們,始終對google MAP上的標注偏移很頭疼,我收集了一些資料,今天在這里和大家一起分享。
所謂的地圖數據加密偏移,其實就是用一個偏移算法對地圖的經緯度做一個加減偏移量,從而達到與實際地圖不一致。這個偏移算法本身是沒有什么規律可言的,每家地圖服務商都有一套自己的加密偏移算法,既然算法上沒有什么規律可言,但是對於算法中生成的偏移量是否有規律呢?這個是可以肯定的,但是偏移算法中生成的偏移量是有規律而言的。偏移量的規律很難得到,要是能拿到這個偏移量,就可以說是破解了某一個地圖服務商的地圖加密。
那我們怎么解決這個偏差呢!我在網上找到了一個強人破解google map偏移的方法
畢竟做地圖開發的都存在衛星圖和地圖的切換,誰不想讓切換以后的地圖對上呢!后來我發現google的地圖服務,ditu.gogle開始的都沒有偏差,maps.google開頭的服務就有偏差,我就開始查找google的取偏移量算法,事前我還是圖破解google手機版本的數據,沒有成功,估計是使用了自己的壓縮或加密算法,最后也沒有找到規律,后來才嘗試破解web版本的不過web版本的接口我對於js不是特別熟悉,所以本次破解放棄了分析源代碼的步驟,而是直接采用排除法那就是把地圖部分訪問的全部地址,一個接一個封殺掉,查找那個起偏移做用的網址 http://ditu.google.cn/maps/vp?spn=0.0,0.0&z=18& vp=39.111195,117.148067 最后找到了就是這個,記住每次測試用清理瀏覽器緩存哦,使用fixfox的fildder和adblock就夠了 然后就是分析每次返回內容的規律,皇天不負有心人啊,我總算是搞定了,下面是我整理的接口
Google 中國地圖偏移接口
1. 接口地址:http://ditu.google.cn/maps/vp?spn=0.0,0.0&z=18&vp=39.111195,117.148067
(注:.cn和.com都可以,我用國內服務器就會選擇.cn用美國服務器就會選擇.com)
2. 返回內容中的有效部分:
3. (39.111195, 117.148067, 18, [9, -2, 18, -4, 37, -8, 74, -16, 149, -33, 298, -67, 596, -135, 1193, -270])
4. Spn參數暫時未知實際意義,但是需要上發spn參數,任意兩個小數用逗號分開Vp參數緯經度值,用逗號分隔,z參數為地圖縮放級別,無實際意義
5. 取回的部分中有效數字為[9, -2, 18, -4, 37, -8, 74, -16, 149, -33, 298, -67, 596, -134, 1192, -268]這個數組總共有8組數字,每兩個為一組,分為別從11級到18級的地圖和衛星圖的偏移像素數量,我們前一組數字精確的等於后一組數字除二,我們為了得到最精確的偏移,故選擇第18級的偏移量1193,-270,1193為x方向上精度的偏移像素,-270為y方向上維度偏移像素
6. 經緯度的偏移轉換我們需要江經緯度39.111195,117.148067轉化為18級像素值25620917 和 55392414,然后分別加上偏移量-270,1193,然后再轉化為經緯度39.11231854918217 和117.15446412563324,即位偏移后的經緯度
google的地圖采用將地球圓表面投影成平面的方式進行貼圖
假設zoom=15;
橫坐標從左至右像素為0-256*2的15次冪,也就是每增加一級,地圖大小橫縱坐標加倍,256為一個標准圖片的大小
顯示-180度到+180的范圍,經度越大x越大
縱坐標從上到下像素為0-256*2的15次冪,顯示+85到-85度的范圍,緯度越小y越大
我們先看一下經度的轉換
經度的轉換,我就不多說了,均勻分布,大家簡單的看一下下面的公式就明白了
經度到像素X值
public static double lngToPixel(double lng, int zoom) {
return (lng + 180) * (256L << zoom) / 360;
}
像素X到經度
public static double pixelToLng(double pixelX, int zoom) {
return pixelX * 360 / (256L << zoom) - 180;
}
緯度到像素Y
public static double latToPixel(double lat, int zoom) {
double siny = Math.sin(lat * Math.PI / 180);
double y = Math.log((1 + siny) / (1 - siny));
return (128 << zoom) * (1 - y / (2 * Math.PI));
}
像素Y到緯度
public static double pixelToLat(double pixelY, int zoom) {
double y = 2 * Math.PI * (1 - pixelY / (128 << zoom));
double z = Math.pow(Math.E, y);
double siny = (z - 1) / (z + 1);
return Math.asin(siny) * 180 / Math.PI;
}
維度的這個轉換,單純去理解不是很好理解,我也沒有太深入的了解,從公式來看,采用了一種非線性變化,也就是靠近赤道的地方單位像素表現的緯度間距大,越靠近兩極越小,可能是因為 經度在靠近兩極的方向均勻變化,導致緯度也要進行拉伸,否則 靠近兩極的地方,地理形狀就該發生變化了,總之上面的轉換公式大家還是可以研究一下的,google維度的表示范圍是-85到+85,這個可以求出來!
上面得到的像素XY是像素的坐標,並非是google地圖取地圖的那個XY那個XY是把像素所標除以256得到的商,也就是每張圖片的大小
