百度地圖API中如何用好摩卡托坐標
百度地圖API有兩種坐標系,一種是百度經緯度,一種是摩卡托坐標系。在本章你將學會:
1、如何相互轉換這兩種坐標;
2、使用該坐標進行反地址解析;
3、坐標附近全部POI的查詢;
4、計算兩點間的距離。
最終畫面效果圖
百度地圖API常用兩種坐標系,一是球面坐標系,又稱百度坐標,即point;第二就是平面坐標系,又稱摩卡托坐標,即pixel。
為了方便用戶調用,API中的參數大多為百度經緯度,又稱球面坐標。而在后臺計算時,為了加快運算速度,一般采取摩卡托坐標系,即平面坐標。(有了平面坐標,用戶能自己快速而海量地計算兩點的距離。)
1、百度經緯度和摩卡托坐標的相互轉換
MercatorProjection類,通過MapType的getProjection方法獲得實例。類參考:
百度經緯度轉換為摩卡托(worldCoordinate.x和worldCoordinate.y就是平面坐標的x和y)
varprojection1 = map.getMapType().getProjection();
varworldCoordinate = projection1.lngLatToPoint(pt);
摩卡托轉換為百度經緯度(LngLat.lng和LngLat.lat就是經緯度)
- varprojection2 = map.getMapType().getProjection();
- varLngLat = projection2.pointToLngLat(mctXY);
2、使用坐標進行反地址解析
由于百度地圖API只支持百度經緯度的反地址解析,所以,必須先將摩卡托坐標轉換為百度經緯度,再使用如下方法。
- vargc = newBMap.Geocoder();
- gc.getLocation(point, function(rs){
- varaddComp = rs.addressComponents;
- alert(addComp.province + ", " + addComp.city + ", " + addComp.district + ", " + addComp.street + ", " + addComp.streetNumber);
- });
- });
反地址解析可以返回如下數據:
3、坐標附近全部POI的查詢
詳細教程請參照文章《【百度地圖API】如何用圓形搜索獲取中心點周圍100米內全部關鍵點?如天安門附近所有的餐廳、加油站、賓館、大廈等》:http://www.cnblogs.com/milkmap/archive/2011/09/16/2178907.html
4、計算兩點間距離的三種方法
通過本章介紹的經緯度轉換的工具,我們得到如下的一組數據。
起點:
摩卡托坐標x:12057394.71
摩卡托坐標y:2589680.88
經緯度lng: 108.312241
經緯度lat: 22.787823
終點:
摩卡托坐標x:12058626.7
摩卡托坐標y:2592552.85
經緯度lng: 108.323308
經緯度lat: 22.811744
(A) 通過百度地圖API調用(這里只能使用百度經緯度),map.getDistance(pointA,pointB),可以得到距離為:
alert(map.getDistance(newBMap.Point(108.312241,22.787823),newBMap.Point(108.323308,22.811744)));
(B) 自己利用球面坐標計算兩點距離的方法:
設地球半徑為R,地心為0,球面上兩點A、B的球面坐標為A(α1,β1),B(α2,β2),α1、α2∈[-π,π],β1、β2∈[-π/2,π/2 ],
AB =R·arccos[cosβ1cosβ2cos(α1-α2)+sinβ1sinβ2]
利用勾股定理與正弦定理則可求出AB兩點間的直線距離,在利用正弦定理可求出AB兩點與地球0點夾角的度數,再利用如下公式:角EOD的度數/360度=E與D之間的球面距離/大圓周長,則可求出AB的球面距離。
(C) 自己利用平面坐標系計算兩點距離的方法:(可以自己后臺運算)
由百度經緯度得到摩卡托坐標后,能輕松計算出X和Y的值。***用勾股定理求得Z。
alert(Math.sqrt(Math.pow((12057394.71 - 12058626.7),2) + Math.pow((2589680.88 - 2592552.85),2)));
全部源代碼:
- <!DOCTYPE html>
- <html>
- <head>
- <meta http-equiv="Content-Type"content="text/html; charset=gb2312"/>
- <title>摩卡托坐標的反地址解析</title>
- <script type="text/javascript"src="http://api.map.baidu.com/api?v=1.2"></script>
- </head>
- <body>
- <div style="width:400px;height:650px;border:1px solid gray;float:left;"id="container"></div>
- <div style="width:500px;height:270px;float:left;margin:0 0 0 10px;">
- <p>摩卡托坐標x:<input type="text"value="12059034.69"id="mctX"/></p>
- <p>摩卡托坐標y:<input type="text"value="2590880.82"id="mctY"/></p>
- <p id="pointX"></p>
- <p id="pointY"></p>
- <p id="entertaiment"></p>
- <p><input style="width:240px;height:130px;font-size:30px;"type="button"value="MCT反地址解析"onclick="mctGeo();"/></p>
- <div id="panel"></div>
- </div>
- </body>
- </html>
- <script type="text/javascript">
- //以下兩句話為創建地圖
- varmap =newBMap.Map("container");
- map.centerAndZoom(newBMap.Point(108.318421,22.800617), 15);//魚骨控件
- map.addControl(newBMap.NavigationControl()); //點擊地圖進行地址解析
- vargc =newBMap.Geocoder();
- map.addEventListener("click", function(e){varpt =e.point;
- document.getElementById("pointX").innerHTML ="經緯度lng: "+pt.lng;
- document.getElementById("pointY").innerHTML ="經緯度lat: "+pt.lat;varprojection1 =this.getMapType().getProjection();varworldCoordinate =projection1.lngLatToPoint(pt);
- document.getElementById("mctX").value =worldCoordinate.x;
- document.getElementById("mctY").value =worldCoordinate.y;
- map.clearOverlays();
- document.getElementById("panel").innerHTML ="";
- gc.getLocation(pt, function(rs){varaddComp =rs.addressComponents;
- document.getElementById("entertaiment").innerHTML =addComp.province +", "+addComp.city +", "+addComp.district +", "+addComp.street +", "+addComp.streetNumber;varallPois =rs.surroundingPois; //獲取全部POI(該點半徑為100米內有6個POI點)
- for(i=0;i<allPois.length;++i){
- document.getElementById("panel").innerHTML +="<p style='font-size:12px;'>"+(i+1) +"、"+allPois[i].title +",地址:"+allPois[i].address +"</p>";
- map.addOverlay(newBMap.Marker(allPois[i].point));
- }
- },mOption);
- });//摩卡托反地址解析
- varmOption ={
- poiRadius : 500, //半徑為1000米內的POI,默認100米
- numPois : 12//列舉出50個POI,默認10個
- }functionmctGeo(){
- map.clearOverlays();
- document.getElementById("panel").innerHTML ="";varmctXX =document.getElementById("mctX").value;varmctYY =document.getElementById("mctY").value; varmctXY =newBMap.Pixel(mctXX,mctYY); varprojection2 =map.getMapType().getProjection();varLngLat =projection2.pointToLngLat(mctXY);
- document.getElementById("pointX").innerHTML ="經緯度lng: "+LngLat.lng;
- document.getElementById("pointY").innerHTML ="經緯度lat: "+LngLat.lat;
- gc.getLocation(LngLat, function(rs){varaddComp =rs.addressComponents;
- document.getElementById("entertaiment").innerHTML =addComp.province +", "+addComp.city +", "+addComp.district +", "+addComp.street +", "+addComp.streetNumber;varallPois =rs.surroundingPois; //獲取全部POI(該點半徑為100米內有6個POI點)
- for(i=0;i<allPois.length;++i){
- document.getElementById("panel").innerHTML +="<p style='font-size:12px;'>"+(i+1) +"、"+allPois[i].title +",地址:"+allPois[i].address +"</p>";
- map.addOverlay(newBMap.Marker(allPois[i].point));
- }
- },mOption);
- }</script>
原文鏈接:http://www.cnblogs.com/milkmap/archive/2012/01/31/2333875.html
【編輯推薦】