偷懶了一個月,今天終于重新修改了mapeasy中的球平算法應(yīng)用。
以前的mapeasy中使用google map data的例子不能正確使用經(jīng)緯度,現(xiàn)在終于可以了。

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()非常重要,他們表示了從經(jīng)緯度和pixel之間的轉(zhuǎn)換算法。
??
?? google做了一個默認(rèn)的實現(xiàn)GMercatorProjection,使用的是麥卡托算法,google map提供的地圖數(shù)據(jù),就是根據(jù)這個算法投影轉(zhuǎn)換而來的。
?? 如果你需要使用自己的投影地圖,記得一定要自己實現(xiàn)GProjection接口。
??
?? google使用的麥卡托算法很有意思,它并沒有把整個地球都投影出來,只能投影緯度在85度內(nèi)的地圖。也就是說,最北極和最南極的那部分(緯度85以上),在google地圖中是找不到的:)
???
??? 你可以運行一下這句代碼:
alert(map.getCurrentMapType().getProjection().fromLatLngToPixel(new?GLatLng(85,0),map.getZoom()));
?? 你會發(fā)現(xiàn),對應(yīng)的Y坐標(biāo)就是0了:)

??? 如果運行:
alert(map.getCurrentMapType().getProjection().fromLatLngToPixel(new?GLatLng(90,0),map.getZoom()));
??? 那么,Y坐標(biāo)將為負(fù)數(shù):)

??? 如果你只是希望使用google實現(xiàn)好的麥卡托算法,你還可以直接繞過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轉(zhuǎn)換成自己應(yīng)用的坐標(biāo)系中的坐標(biāo)。例如,在我的mapeasy中,坐標(biāo)系范圍是x:[-180,180], y:[-90,90],因此我使用如下的代碼進行坐標(biāo)轉(zhuǎn)換:
/**
?*?
@param?lat?經(jīng)度
?*?
@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:根據(jù)google提供的Mercator算法算出來的Pixel的
????var?merX=gm.fromLatLngToPixel(latLan,zoom).x;
????var?merY
=gm.fromLatLngToPixel(latLan,zoom).y;

???
//google使用的麥卡托投影法,并沒有把整個地球投影出來,只是投影出緯度在85度以內(nèi)的地球,也就是說,北緯85度的點,就是最北邊的點。而最北極和最南極的那部分地圖(緯度85以上),在google提供的地圖中是找不到的:)
???????
//在zome=0時,如果地圖的左上角的點對應(yīng)的緯經(jīng)度為:(85,-180),右下角對應(yīng)的緯經(jīng)度為(-85,180),此時,使用google提供的Mercator算法算出來的對應(yīng)的坐標(biāo)系?范圍為:x[0,256],y[0,256],

????
//坐標(biāo)系的放大倍數(shù)
????var?scale=Math.pow(2,zoom);
????
????var?merXMin
=0;
????var?merXMax
=256*scale;
???? var?merYCenter=128*scale;

????
//meX,meY:MapEasyPoint中的x,y
????
//MapEasy默認(rèn)的坐標(biāo)系范圍為x:[-180,180],y:[-90,90],因此需要進行轉(zhuǎn)換
????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();
}

??? 這次寫這段代碼,才發(fā)現(xiàn)google中GLatLan類的distanceFrom(other)函數(shù),實現(xiàn)了計算兩個經(jīng)緯坐標(biāo)間距離(米為單位)的算法,簡單試用了一下,還8錯。

???? 忘了交代 了,我參考的google map api的版本是maps2.48.api.js

?btw:
??? 今天還是偷懶,沒有仔細(xì)研究GMercatorProjection的實現(xiàn)代碼,留給team中有空的伙伴去研究吧。
??? 這兒有個Mercator不錯的說明:http://en.wikipedia.org/wiki/Mercator_projection

?? 有興趣的朋友可以來逛逛http://mapeasy.sf.net。項目問題還好多,包括javascript的memory leakage至今也還沒去解決。項目組的成員最近都好忙,也不知道有沒有朋友有興趣加入的。