偷懶了一個月,今天終于重新修改了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;
??? 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();
}
?*?@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至今也還沒去解決。項目組的成員最近都好忙,也不知道有沒有朋友有興趣加入的。
地圖學(xué),
數(shù)據(jù)結(jié)構(gòu)
成圖算法
中間件等
然后才是開發(fā)人員考慮的二次開發(fā),web,界面,ajax.....
c/s的控件...
zkjbeyond好像是做Gis的吧?有機會多交流。
我對您這個Mapeasy很感興趣,也研究了一段時間,能否能更了解您這個項目嗎?等待回復(fù)!!!