偷懶了一個月,今天終于重新修改了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至今也還沒去解決。項目組的成員最近都好忙,也不知道有沒有朋友有興趣加入的。