Better

业精于勤荒于嬉

Android开发中地图坐标系以及调用地图导航

Better's Avatar 2017-04-08 Android

  1. 1. 地图坐标系
    1. 1.1. 转换到百度
    2. 1.2. 转换到高德
    3. 1.3. 转换到腾讯
  2. 2. 调起导航
    1. 2.1. 百度
    2. 2.2. 高德
    3. 2.3. 腾讯

android开发中你会使用到地图,国内常用的地图有高德,百度,腾讯。这里主要谈一下各自的坐标系,以及如何在app里面调起他们的地图app导航。

地图坐标系

地球人共同约定的地图准则。

  1. WGS84:国际通用的地球坐标系。Google地图非中国范围在使用。
  2. GCJ102:WGS84坐标系经加密后的坐标系,又名火星坐标系。Google地图中国范围,高德,腾讯在使用。
  3. BD09:GCJ02坐标系经加密后的坐标系,又名百度坐标系。百度在使用。

国际上最常用的是WGS84,在国内是GCJ102,因为国家地理测绘总局对于出版地图的要求,出版地图必须符合GCJ02坐标系标准了,也就是国家规定不能直接使用WGS84地理坐标系。
所以在你拿到地图的数据时,调起各自的地图app进行导航,就需要将数据进行转换。不然你的点位是有很大的偏差。
在高德,百度,腾讯的地图开发平台都提供了,如何将其他的地图数据转换成自家的。

转换到百度

链接:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 将google地图、soso地图、aliyun地图、mapabc地图和amap地图// 所用坐标转换成百度坐标  
CoordinateConverter converter = new CoordinateConverter();
converter.from(CoordType.COMMON);
// sourceLatLng待转换坐标
converter.coord(sourceLatLng);
LatLng desLatLng = converter.convert();

// 将GPS设备采集的原始GPS坐标转换成百度坐标
CoordinateConverter converter = new CoordinateConverter();
converter.from(CoordType.GPS);
// sourceLatLng待转换坐标
converter.coord(sourceLatLng);
LatLng desLatLng = converter.convert();

转换到高德

链接:

1
2
3
4
5
6
7
CoordinateConverter converter  = new CoordinateConverter(); 
// CoordType.GPS 待转换坐标类型
converter.from(CoordType.GPS);
// sourceLatLng待转换坐标点 LatLng类型
converter.coord(sourceLatLng);
// 执行转换操作
LatLng desLatLng = converter.convert();

转换到腾讯

链接:

1
2
3
4
5
//批量支持坐标个数以HTTP GET方法请求上限为准
//TranslateParam.coord_type(CoordTypeEnum type)参数用于指定输入的坐标类型
TranslateParam param = new TranslateParam().
addLocation(new Location().lat(lat).lng(lng)).
coord_type(CoordTypeEnum.BAIDU);

这样你就必须要集成三家的sdk,项目有点点大。网上也有一些偏方,见文末提供的代码。

调起导航

各自需要发送的intent如下:

百度

链接:

1
2
String intentUri =
"intent://map/direction?origin=latlng:" + 30.575861 + "," + 104.069819 + "|name:起点&destination=latlng:" + 30.654021 + "," + 104.134411 + "|name:目的地" + "&mode=driving&src=yourCompanyName|yourAppName#Intent;scheme=bdapp;package=com.baidu.BaiduMap;end"

高德

链接:

1
2
String intentUri =
"androidamap://route?sourceApplication=com.autonavi.minimap&slat=" + 30.575861 + "&slon=" + 104.069819 + "&sname=起点&dlat=" + 30.654021 + "&dlon=" + 104.134411 + "&dname=目的地&dev=0&m=0&t=1"

腾讯

链接:

1
2
String intentUri =
"qqmap://map/routeplan?type=drive&from=起点&fromcoord=" + 30.575861 + "," + 104.069819+ "&to=目的地&tocoord=" + 30.654021 + "," +104.134411

附上网上的偏方:

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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
public class GPSUtil {
public static double pi = 3.1415926535897932384626;
public static double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
public static double a = 6378245.0;
public static double ee = 0.00669342162296594323;

public static double transformLat(double x, double y) {
double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y
+ 0.2 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
return ret;
}

public static double transformLon(double x, double y) {
double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1
* Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0
* pi)) * 2.0 / 3.0;
return ret;
}
public static double[] transform(double lat, double lon) {
if (outOfChina(lat, lon)) {
return new double[]{lat,lon};
}
double dLat = transformLat(lon - 105.0, lat - 35.0);
double dLon = transformLon(lon - 105.0, lat - 35.0);
double radLat = lat / 180.0 * pi;
double magic = Math.sin(radLat);
magic = 1 - ee * magic * magic;
double sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
double mgLat = lat + dLat;
double mgLon = lon + dLon;
return new double[]{mgLat,mgLon};
}
public static boolean outOfChina(double lat, double lon) {
if (lon < 72.004 || lon > 137.8347)
return true;
if (lat < 0.8293 || lat > 55.8271)
return true;
return false;
}
/**
* 84 to 火星坐标系 (GCJ-02) World Geodetic System ==> Mars Geodetic System
*
* @param lat
* @param lon
* @return
*/
public static double[] gps84_To_Gcj02(double lat, double lon) {
if (outOfChina(lat, lon)) {
return new double[]{lat,lon};
}
double dLat = transformLat(lon - 105.0, lat - 35.0);
double dLon = transformLon(lon - 105.0, lat - 35.0);
double radLat = lat / 180.0 * pi;
double magic = Math.sin(radLat);
magic = 1 - ee * magic * magic;
double sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
double mgLat = lat + dLat;
double mgLon = lon + dLon;
return new double[]{mgLat, mgLon};
}

/**
* * 火星坐标系 (GCJ-02) to 84 * * @param lon * @param lat * @return
* */
public static double[] gcj02_To_Gps84(double lat, double lon) {
double[] gps = transform(lat, lon);
double lontitude = lon * 2 - gps[1];
double latitude = lat * 2 - gps[0];
return new double[]{latitude, lontitude};
}
/**
* 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 将 GCJ-02 坐标转换成 BD-09 坐标
*
* @param lat
* @param lon
*/
public static double[] gcj02_To_Bd09(double lat, double lon) {
double x = lon, y = lat;
double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
double tempLon = z * Math.cos(theta) + 0.0065;
double tempLat = z * Math.sin(theta) + 0.006;
double[] gps = {tempLat,tempLon};
return gps;
}

/**
* * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 * * 将 BD-09 坐标转换成GCJ-02 坐标 * * @param
* bd_lat * @param bd_lon * @return
*/
public static double[] bd09_To_Gcj02(double lat, double lon) {
double x = lon - 0.0065, y = lat - 0.006;
double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
double tempLon = z * Math.cos(theta);
double tempLat = z * Math.sin(theta);
double[] gps = {tempLat,tempLon};
return gps;
}

/**将gps84转为bd09
* @param lat
* @param lon
* @return
*/
public static double[] gps84_To_bd09(double lat,double lon){
double[] gcj02 = gps84_To_Gcj02(lat,lon);
double[] bd09 = gcj02_To_Bd09(gcj02[0],gcj02[1]);
return bd09;
}
public static double[] bd09_To_gps84(double lat,double lon){
double[] gcj02 = bd09_To_Gcj02(lat, lon);
double[] gps84 = gcj02_To_Gps84(gcj02[0], gcj02[1]);
//保留小数点后六位
gps84[0] = retain6(gps84[0]);
gps84[1] = retain6(gps84[1]);
return gps84;
}

/**保留小数点后六位
* @param num
* @return
*/
private static double retain6(double num){
String result = String .format("%.6f", num);
return Double.valueOf(result);
}
}
This article was last updated on days ago, and the information described in the article may have changed.