原始GPS坐标转换为百度坐标

GPS经纬度标准及转换算法

几个问题

坐标体系是否遵循国家对地理信息保密要求?

  百度对外接口的坐标系,都是经过国家测绘局加密处理,符合国家测绘局对地理信息保密要求.   

百度采用何种坐标体系?

  百度地图api中采用两种坐标体系,经纬度坐标系和墨卡托投影坐标系。前者单位是度,后者单位是米,具体定义可以参见百科词条解释.   

百度坐标为何有偏移?

  国际经纬度坐标标准为WGS-84,国内必须至少使用国测局制定的GCJ- 02,对地理位置进行首次加密。百度坐标在此基础上,进行了BD-09二次加密措施,更加保护了个人隐私。百度对外接口的坐标系并不是GPS采集的真实经 纬度,需要通过坐标转换接口进行转换。         

如何从其他体系的坐标迁移到百度坐标?

  坐标转换接口非公开。
  也就是说由于受到国家一些法律法规限制,所有的电子地图服务提供商都需要给地图 数据加上偏移和加密,所谓的地图数据加密偏移,其实就是用一个偏移算法对地图的经纬度做一个加减偏移量,从而达到与实际地图不一致。这个偏移算法本身是没 有什么规律可言的,每家地图服务商都有一套自己的加密偏移算法,既然算法上没有什么规律可言,但是对于算法中生成的偏移量是否有规律呢?这个是可以肯定 的,但是偏移算法中生成的偏移量是有规律而言的。偏移量的规律很难得到,要是能拿到这个偏移量,就可以说是破解了某一个地图服务商的地图加密。
   所以百度对外提供的坐标系是百度自己的坐标系,而手机GPS获得的是原始坐标,两者不在一个坐标系上,所以有很大的误差,我测试了一下,误差在千米之 外。所以必须得把两者换成统一坐标系。换成原始GPS坐标在国内原则上是违法的,所以只能统一成各个地图运营商自己的坐标系,比如百度坐标系或者 google坐标系。
  百度地图坐标转换接口如下:  

1
  BMap.Convertor.translate(gpsPoint,0,translateCallback); //真实经纬度转成百度坐标

其中gpsPoint var gpsPoint = new BMap.Point(经度,纬度); ( GPS坐标) 0:代表GPS,也可以是2:google坐标 translateCallback:回调函数

百度坐标转换

链接:百度提供API调用demo

"da"

下面是坐标转换的JS源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 百度地图API功能
//GPS坐标
var x = 116.32715863448607;
var y = 39.990912172420714;
var ggPoint = new BMap.Point(x,y);
//地图初始化
var bm = new BMap.Map("allmap");
bm.centerAndZoom(ggPoint, 15);
bm.addControl(new BMap.NavigationControl());
//添加gps marker和label
var markergg = new BMap.Marker(ggPoint);
bm.addOverlay(markergg); //添加GPS marker
var labelgg = new BMap.Label("未转换的GPS坐标(错误)",{offset:new BMap.Size(20,-10)});
markergg.setLabel(labelgg); //添加GPS label
//坐标转换完之后的回调函数
translateCallback = function (data){
if(data.status === 0) {
var marker = new BMap.Marker(data.points[0]);
bm.addOverlay(marker);
var label = new BMap.Label("转换后的百度坐标(正确)",{offset:new BMap.Size(20,-10)});
marker.setLabel(label); //添加百度label
bm.setCenter(data.points[0]);
}
}
setTimeout(function(){
var convertor = new BMap.Convertor();
var pointArr = [];
pointArr.push(ggPoint);
convertor.translate(pointArr, 1, 5, translateCallback)
}, 1000);

百度的转换接口是异步调用,若要实现批量转换,输出的结果可能会乱。因此可以采用本地转换代替异步的回调函数。

下面贴出本地转换算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/**
* 坐标系转换函数
* WGS->GCJ
* WGS->BD09
* GCJ->BD09
*/
function Convertor(ak) {
this.stepCount = 100;
this.pointCount = [];
this.Result = [];
this.NoisIndex = [];
this.Time = new Date();
this.AK = ak;
this.M_PI = 3.14159265358979324;
this.A = 6378245.0;
this.EE = 0.00669342162296594323;
this.X_PI = this.M_PI * 3000.0 / 180.0;
}
Convertor.prototype.outofChine = function(p) {
if (p.lng < 72.004 || p.lng > 137.8347) {
return true;
}
if (p.lat < 0.8293 || p.lat > 55.8271) {
return true;
}
return false;
}
;
Convertor.prototype.WGS2GCJ_lat = function(x, y) {
var ret1 = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
ret1 += (20.0 * Math.sin(6.0 * x * this.M_PI) + 20.0 * Math.sin(2.0 * x * this.M_PI)) * 2.0 / 3.0;
ret1 += (20.0 * Math.sin(y * this.M_PI) + 40.0 * Math.sin(y / 3.0 * this.M_PI)) * 2.0 / 3.0;
ret1 += (160.0 * Math.sin(y / 12.0 * this.M_PI) + 320 * Math.sin(y * this.M_PI / 30.0)) * 2.0 / 3.0;
return ret1;
}
;
Convertor.prototype.WGS2GCJ_lng = function(x, y) {
var ret2 = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
ret2 += (20.0 * Math.sin(6.0 * x * this.M_PI) + 20.0 * Math.sin(2.0 * x * this.M_PI)) * 2.0 / 3.0;
ret2 += (20.0 * Math.sin(x * this.M_PI) + 40.0 * Math.sin(x / 3.0 * this.M_PI)) * 2.0 / 3.0;
ret2 += (150.0 * Math.sin(x / 12.0 * this.M_PI) + 300.0 * Math.sin(x / 30.0 * this.M_PI)) * 2.0 / 3.0;
return ret2;
}
;
Convertor.prototype.WGS2GCJ = function(poi) {
if (this.outofChine(poi)) {
return;
}
var poi2 = {};
var dLat = this.WGS2GCJ_lat(poi.lng - 105.0, poi.lat - 35.0);
var dLon = this.WGS2GCJ_lng(poi.lng - 105.0, poi.lat - 35.0);
var radLat = poi.lat / 180.0 * this.M_PI;
var magic = Math.sin(radLat);
magic = 1 - this.EE * magic * magic;
var sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((this.A * (1 - this.EE)) / (magic * sqrtMagic) * this.M_PI);
dLon = (dLon * 180.0) / (this.A / sqrtMagic * Math.cos(radLat) * this.M_PI);
poi2.lat = poi.lat + dLat;
poi2.lng = poi.lng + dLon;
return poi2;
}
;
Convertor.prototype.GCJ2BD09 = function(poi) {
var poi2 = {};
var x = poi.lng
, y = poi.lat;
var z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * this.X_PI);
var theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * this.X_PI);
poi2.lng = z * Math.cos(theta) + 0.0065;
poi2.lat = z * Math.sin(theta) + 0.006;
return poi2;
}
;
/**
* WGS->百度坐标系
*/
Convertor.prototype.WGS2BD09 = function(poi) {
//WGS->GCJ
var poi2 = this.WGS2GCJ(poi);
if (typeof poi2 === "undefined") {
return;
}
//GCJ->百度坐标系
return this.GCJ2BD09(poi2);
}
//TEST
var c=new Convertor();
var r1=c.WGS2BD09({lng:123,lat:38});
console.log(r1);

转换函数可以改写为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function convert(JD,WD)
{
var convertor = new Convertor();
var Point = new BMap.Point(JD,WD);
var marker= new BMap.Marker(point);
map.addOverlay(marker);
var copoint=convertor.WGS2BD09(point);
var marker = new BMap.Marker(copoint);
map.addOverlay(marker);
var templng=copoint.lng.toFixed(6);
var templat=copoint.lat.toFixed(6);
convert_result=templng+","+templat+";";
// alert(convert_result);
return convert_result; }
}