【百度地图API】如何根据摩卡托坐标进行POI查询,和计算两点距离

摘要:javascript

百度地图API有两种坐标系,一种是百度经纬度,一种是摩卡托坐标系。在本章你将学会:html

一、如何相互转换这两种坐标;java

二、使用该坐标进行反地址解析;api

三、坐标附近所有POI的查询;ide

四、计算两点间的距离。工具

------------------------------------------------------------------------------ui

最终画面效果图this

 

百度地图API经常使用两种坐标系,一是球面坐标系,又称百度坐标,即point;第二就是平面坐标系,又称摩卡托坐标,即pixel。spa

为了方便用户调用,API中的参数大多为百度经纬度,又称球面坐标。而在后台计算时,为了加快运算速度,通常采起摩卡托坐标系,即平面坐标。(有了平面坐标,用户能本身快速海量地计算两点的距离。)code

 

 

一、百度经纬度和摩卡托坐标的相互转换

MercatorProjection类,经过MapType的getProjection方法得到实例。类参考:

 

百度经纬度转换为摩卡托(worldCoordinate.x和worldCoordinate.y就是平面坐标的x和y)

     projection1 = map.getMapType().getProjection();
     worldCoordinate = projection1.lngLatToPoint(pt);


摩卡托转换为百度经纬度(LngLat.lng和LngLat.lat就是经纬度)

     projection2 = map.getMapType().getProjection();
     LngLat = projection2.pointToLngLat(mctXY);

 

 

 

二、使用坐标进行反地址解析

因为百度地图API只支持百度经纬度的反地址解析,因此,必须先将摩卡托坐标转换为百度经纬度,再使用以下方法。

 gc =  BMap.Geocoder();    
gc.getLocation(point, (rs){
         addComp = rs.addressComponents;
        alert(addComp.province + ", " + addComp.city + ", " + addComp.district + ", " + addComp.street + ", " + addComp.streetNumber);
    });        
});

反地址解析能够返回以下数据:



 

三、坐标附近所有POI的查询

详细教程请参照文章《【百度地图API】如何用圆形搜索获取中心点周围100米内所有关键点?如天安门附近全部的餐厅、加油站、宾馆、大厦等》:http://www.cnblogs.com/milkmap/archive/2011/09/16/2178907.html

 

 

四、计算两点间距离的三种方法

经过本章介绍的经纬度转换的工具,咱们获得以下的一组数据。

起点:
摩卡托坐标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(new BMap.Point(108.312241,22.787823),new BMap.Point(108.323308,22.811744)));

 

 

(B) 本身利用球面坐标计算两点距离的方法:(能够本身后台运算

设地球半径为R,地心为0,球面上两点A、B的球面坐标为A(α1,β1),B(α2,β2),α一、α2∈[-π,π],β一、β2∈[-π/2,π/2 ], 

AB =R愠爀挀挀漀猀嬀挀漀猀β1cosβ2cos(α1-α2)+sinβ1sinβ2] 
利用勾股定理与正弦定理则可求出AB两点间的直线距离,在利用正弦定理可求出AB两点与地球0点夹角的度数,再利用以下公式:角EOD的度数/360度=E与D之间的球面距离/大圆周长,则可求出AB的球面距离。

注意,R = 6370996.81米。

(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">
//如下两句话为建立地图
var map = new BMap.Map("container");
map.centerAndZoom(new BMap.Point(108.318421,22.800617), 15);
//鱼骨控件
map.addControl(new BMap.NavigationControl()); 

//点击地图进行地址解析
var gc = new BMap.Geocoder();
map.addEventListener("click", function(e){
    var pt = e.point;
    document.getElementById("pointX").innerHTML = "经纬度lng: " + pt.lng;
    document.getElementById("pointY").innerHTML = "经纬度lat: " + pt.lat;
    
    var projection1 = this.getMapType().getProjection();
    var worldCoordinate = 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){
        var addComp = rs.addressComponents;
        document.getElementById("entertaiment").innerHTML = addComp.province + ", " + addComp.city + ", " + addComp.district + ", " + addComp.street + ", " + addComp.streetNumber;
        
        var allPois = 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(new BMap.Marker(allPois[i].point));                
        }
    },mOption);
});

//摩卡托反地址解析
var mOption = {
    poiRadius : 500,           //半径为1000米内的POI,默认100米
    numPois : 12//列举出50个POI,默认10个
}
function mctGeo(){
    map.clearOverlays();
    document.getElementById("panel").innerHTML = "";
    
    var mctXX = document.getElementById("mctX").value;
    var mctYY = document.getElementById("mctY").value;    
    var mctXY = new BMap.Pixel(mctXX,mctYY);    
    
    var projection2 = map.getMapType().getProjection();
    var LngLat = projection2.pointToLngLat(mctXY);    
    
    document.getElementById("pointX").innerHTML = "经纬度lng: " + LngLat.lng;
    document.getElementById("pointY").innerHTML = "经纬度lat: " + LngLat.lat;

    gc.getLocation(LngLat, function(rs){
        var addComp = rs.addressComponents;
        document.getElementById("entertaiment").innerHTML = addComp.province + ", " + addComp.city + ", " + addComp.district + ", " + addComp.street + ", " + addComp.streetNumber;
        
        var allPois = 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(new BMap.Marker(allPois[i].point));                
        }
    },mOption);
}
</script>