在这个神奇的国度里,我们总得学习一些有中国特色的东东,例如“火星坐标”。也许有人还不知道这是什么玩意,我就简要介绍一下吧。
如果你有带GPS模块的智能手机,打开定位功能,然后访问 Google地图 。只要你身处中国大陆,你就会发现定位不准,大概有几百米的偏差。然而运行一些导航软件,你又会发现定位很准确,说明手机的GPS模块确实是正常的。
这种现象是怎么造成的呢?答案是人为造成的。简单来说,GPS模块获取到的坐标是WGS84坐标系的,中国政府出于种种目的的考虑,不允许中国的地图使用国际通用的WGS84坐标系,而非要加上一些偏移,这样的坐标系就俗称“火星坐标系”。而Google地图采用的也是加偏移过的火星坐标系,但GPS模块传给它的坐标却没有加偏移,于是就出现几百米的偏差了。
这样的后果就是没法做需要很高精度的地理位置的应用了,就像那个悲剧的Google地图一样,你迷路时无法指望它告诉你正确的位置。
不过上有政策,下有对策。首先要说的是不加偏的地图肯定是没有的,就算有也是机密,只能掌握在美国佬手里。所以只能考虑如何将WGS84坐标转换成火星坐标了。遗憾的是这种转换不是线性的,没有一个简单的换算公式,而且每个地图提供商采用的加偏算法都不相同(也就是有很多种火星坐标系)。
然而勤劳智慧的中国屁民们很快就找到了解决办法:用大量的采样点覆盖这960万平方公里的土地,把对应的WGS84坐标和火星坐标一一记录起来,做成一个偏移数据库,然后直接查询即可。缺点就是统计麻烦,随着精度的提高,数据库占用的空间也会增大,而且地图商一换坐标系(一般几年一次),数据库就失效了。
还有一些更聪明的人就用matlab来分析这些采样点,拟合出了加偏函数的曲线,然后直接计算即可。
不过我属于那种很懒又不会matlab的人,所以上述方案都被我否决了(还有个原因就是那样做是违法的)。
后来我无意中想起Google地图的数据来自MapABC,何不去MapABC看看呢?于是搜索了一下,发现了 MapABC地图API 。在MapABC API for iOS文档里我找到了 GPSToOffSetByPoint: 方法,用途就是查询偏移后的坐标!
于是赶紧注册账号,获取 移动版API KEY ,并下载iOS API SDK和文档。搞定这些后就可以开启Xcode来试验了。
先做个获取WGS84坐标的应用出来:
如果你有带GPS模块的智能手机,打开定位功能,然后访问 Google地图 。只要你身处中国大陆,你就会发现定位不准,大概有几百米的偏差。然而运行一些导航软件,你又会发现定位很准确,说明手机的GPS模块确实是正常的。
这种现象是怎么造成的呢?答案是人为造成的。简单来说,GPS模块获取到的坐标是WGS84坐标系的,中国政府出于种种目的的考虑,不允许中国的地图使用国际通用的WGS84坐标系,而非要加上一些偏移,这样的坐标系就俗称“火星坐标系”。而Google地图采用的也是加偏移过的火星坐标系,但GPS模块传给它的坐标却没有加偏移,于是就出现几百米的偏差了。
这样的后果就是没法做需要很高精度的地理位置的应用了,就像那个悲剧的Google地图一样,你迷路时无法指望它告诉你正确的位置。
不过上有政策,下有对策。首先要说的是不加偏的地图肯定是没有的,就算有也是机密,只能掌握在美国佬手里。所以只能考虑如何将WGS84坐标转换成火星坐标了。遗憾的是这种转换不是线性的,没有一个简单的换算公式,而且每个地图提供商采用的加偏算法都不相同(也就是有很多种火星坐标系)。
然而勤劳智慧的中国屁民们很快就找到了解决办法:用大量的采样点覆盖这960万平方公里的土地,把对应的WGS84坐标和火星坐标一一记录起来,做成一个偏移数据库,然后直接查询即可。缺点就是统计麻烦,随着精度的提高,数据库占用的空间也会增大,而且地图商一换坐标系(一般几年一次),数据库就失效了。
还有一些更聪明的人就用matlab来分析这些采样点,拟合出了加偏函数的曲线,然后直接计算即可。
不过我属于那种很懒又不会matlab的人,所以上述方案都被我否决了(还有个原因就是那样做是违法的)。
后来我无意中想起Google地图的数据来自MapABC,何不去MapABC看看呢?于是搜索了一下,发现了 MapABC地图API 。在MapABC API for iOS文档里我找到了 GPSToOffSetByPoint: 方法,用途就是查询偏移后的坐标!
于是赶紧注册账号,获取 移动版API KEY ,并下载iOS API SDK和文档。搞定这些后就可以开启Xcode来试验了。
先做个获取WGS84坐标的应用出来:
// MapDemoViewController.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
@interface MapDemoViewController : UIViewController <CLLocationManagerDelegate> {
UITextField *wgsText;
UITextField *marsText;
CLLocationManager *locationManager;
}
@property (nonatomic, retain) IBOutlet UITextField *wgsText;