偷懶了一個月,今天終于重新修改了mapeasy中的球平算法應用。
以前的mapeasy中使用
google map data的例子不能正確使用經緯度,現在終于可以了。
google map api中有個很有用的接口:GProjection,官方對這個接口的解釋是:
??? This is the interface for map projections. A map
projection instance is passed to the constructor of
GMapType
. This interface is implemented by the
class GMercatorProjection
, which is used by all
predefined map types. You can implement this interface if you want
to define map types with different map projections.
??? 這個接口最大的作用,就是允許你使用自己的球平算法去投影地圖,其中的fromPixelToLatLng()和fromPixelToLatLng()非常重要,他們表示了從經緯度和pixel之間的轉換算法。
??
?? google做了一個默認的實現
GMercatorProjection,使用的是麥卡托算法,google map提供的地圖數據,就是根據這個算法投影轉換而來的。
?? 如果你需要使用自己的投影地圖,記得一定要自己實現GProjection接口。
??
?? google使用的麥卡托算法很有意思,它并沒有把整個地球都投影出來,只能投影緯度在85度內的地圖。也就是說,最北極和最南極的那部分(緯度85以上),在google地圖中是找不到的:)
???
??? 你可以運行一下這句代碼:
alert(map.getCurrentMapType().getProjection().fromLatLngToPixel(new?GLatLng(85,0),map.getZoom()));
?? 你會發現,對應的Y坐標就是0了:)
??? 如果運行:
alert(map.getCurrentMapType().getProjection().fromLatLngToPixel(new?GLatLng(90,0),map.getZoom()));
??? 那么,Y坐標將為負數:)
??? 如果你只是希望使用google實現好的麥卡托算法,你還可以直接繞過GMap類,直接使用GMercatorProjection類:
??? var zoom=17;
??? var latLan=new? GLatLng(85,180);
??? var?gm=new?GMercatorProjection(zoom+1);?
????var?x=gm.fromLatLngToPixel(latLan,zoom).x;
????var?y=gm.fromLatLngToPixel(latLan,zoom).y;
?? 而后,你就可以把得到的x,y轉換成自己應用的坐標系中的坐標。例如,在我的mapeasy中,坐標系范圍是x:[-180,180], y:[-90,90],因此我使用如下的代碼進行坐標轉換:
/**
?*?@param?lat?經度
?*?@param?lan?緯度
?*?@param?zoom?放大比例
??*/
function?GoogleMapLatLan(lat,lan,zoom){
????this.lat=lat;
????this.lan=lan;
????this.zoom=zoom;
}
GoogleMapLatLan.prototype.fromLatLngToMapEasyPoint=function(){
???var?latLan=new?GLatLng(this.lat,this.lan);
?????var?zoom=this.zoom;
????var?gm=new?GMercatorProjection(zoom+1);?
????//merX,merY:根據google提供的Mercator算法算出來的Pixel的
????var?merX=gm.fromLatLngToPixel(latLan,zoom).x;
????var?merY=gm.fromLatLngToPixel(latLan,zoom).y;
???//google使用的麥卡托投影法,并沒有把整個地球投影出來,只是投影出緯度在85度以內的地球,也就是說,北緯85度的點,就是最北邊的點。而最北極和最南極的那部分地圖(緯度85以上),在google提供的地圖中是找不到的:)
???????//在zome=0時,如果地圖的左上角的點對應的緯經度為:(85,-180),右下角對應的緯經度為(-85,180),此時,使用google提供的Mercator算法算出來的對應的坐標系?范圍為:x[0,256],y[0,256],
????//坐標系的放大倍數
????var?scale=Math.pow(2,zoom);
????
????var?merXMin=0;
????var?merXMax=256*scale;
???? var?merYCenter=128*scale;
????//meX,meY:MapEasyPoint中的x,y
????//MapEasy默認的坐標系范圍為x:[-180,180],y:[-90,90],因此需要進行轉換
????var?meX=((merX-merXMin)-(merXMax-merXMin)/2)*180/((merXMax-merXMin)/2);
????var?meY=(merYCenter-merY)*90/merYCenter;
????return?new?Point(meX,meY);
};
GoogleMapLatLan.prototype.getPoint=function(){
????return?this.fromLatLngToMapEasyPoint();
}
??? 這次寫這段代碼,才發現google中GLatLan類的distanceFrom(
other)函數,實現了計算兩個經緯坐標間距離(米為單位)的算法,簡單試用了一下,還8錯。
???? 忘了交代 了,我參考的google map api的版本是maps2.48.api.js
?btw:
??? 今天還是偷懶,沒有仔細研究GMercatorProjection的實現代碼,留給team中有空的伙伴去研究吧。
??? 這兒有個Mercator不錯的說明:
http://en.wikipedia.org/wiki/Mercator_projection?? 有興趣的朋友可以來逛逛
http://mapeasy.sf.net。項目問題還好多,包括javascript的memory leakage至今也還沒去解決。項目組的成員最近都好忙,也不知道有沒有朋友有興趣加入的。