IOS中GPS定位偏移纠正(适用于Google地图)
在这个神奇的国度里,我们总得学习一些有中国特色的东东,例如“火星坐标”。也许有人还不知道这是什么玩意,我就简要介绍一下吧。 如果你有带GPS模块的智能手机,打开定位功能,然后访问Google地图。只要你身处中国大陆,你就会发现定位不准,大概有几百米的偏差。然而运行一些导航软件,你又会发现定位很准确,说明手机的GPS模块确实是正常的。 这种现象是怎么造成的呢?答案是人为造成的。简单来说,GPS模块获取到的坐标是WGS84坐标系的,中国政府出于种种目的的考虑,不允许中国的地图使用国际通用的WGS84坐标系,而非要加上一些偏移,这样的坐标系就俗称“火星坐标系”。而Google地图采用的也是加偏移过的火星坐标系,但GPS模块传给它的坐标却没有加偏移,于是就出现几百米的偏差了。这样的后果就是没法做需要很高精度的地理位置的应用了,就像那个悲剧的Google地图一样,你迷路时无法指望它告诉你正确的位置。 经过不懈的努力, 终于发现一位牛人用C语言写了一个算法, 不过他要用到一个数据文件, 而且比较大, 放在手机客户端一跑就内存崩溃了, 所以觉得不可取, 于是把他的C代码转化为C#的WebService服务. 代码如下, 供大家参考.希望对大家有所帮助!
- class Program
- {
- const double M_PI = 3.14159265358979323846264338327950288;
- const double M_E = 2.71828182845904523536028747135266250;
- public class MapCoord
- {
- public int lng { set; get; } //12151表示121.51
- public int lat { set; get; } //3130表示31.30
- public int x_off { set; get; } //地图x轴偏移像素值
- public int y_off { set; get; } //地图y轴偏移像素值
- }
- /// <summary>
- /// 自定义比较类
- /// </summary>
- public class myReverserClass : IComparer
- {
- public int Compare(object x, object y)
- {
- MapCoord data1 = (MapCoord)x, data2 = (MapCoord)y;
- int det_lng = data1.lng - data2.lng;
- if (det_lng != 0)
- return det_lng;
- else
- return data1.lat - data2.lat;
- }
- }
- //这就需要一个把经纬度转换成地图xy轴坐标的算法:
- private static double lngToPixel(double lng, int zoom)
- {
- return (lng + 180) * (256L << zoom) / 360;
- }
- private static double latToPixel(double lat, int zoom)
- {
- double siny = Math.Sin(lat * M_PI / 180);
- double y = Math.Log((1 + siny) / (1 - siny));
- return (128 << zoom) * (1 - y / (2 * M_PI));
- }
- //xy轴坐标加上对应的地图xy轴的偏移量,最后还要反过来将最终正确的地图xy轴坐标转换成正确的经纬度
- private static double pixelToLng(double pixelX, int zoom)
- {
- return pixelX * 360 / (256L << zoom) - 180;
- }
- private static double pixelToLat(double pixelY, int zoom)
- {
- double y = 2 * M_PI * (1 - pixelY / (128 << zoom));
- double z = Math.Pow(M_E, y);
- double siny = (z - 1) / (z + 1);
- return Math.Asin(siny) * 180 / M_PI;
- }
- /// <summary>
- /// 将字节转化为具体的数据对象
- /// </summary>
- /// <param name="buf"></param>
- /// <returns></returns>
- private static MapCoord getMapCoordFromBytes(byte[] buf)
- {
- //数据文档结构是八字节为一个坐标及其偏移量,分别为经度,纬度,x偏移量,y偏移量; 每两字节为一个数据
- MapCoord coord = new MapCoord();
- byte[] b1 = new byte[2], b2 = new byte[2], b3 = new byte[2], b4 = new byte[2];
- Array.Copy(buf, 0, b1, 0, 2);
- Array.Copy(buf, 2, b2, 0, 2);
- Array.Copy(buf, 4, b3, 0, 2);
- Array.Copy(buf, 6, b4, 0, 2);
- coord.lng = System.BitConverter.ToInt16(b1, 0);
- coord.lat = System.BitConverter.ToInt16(b2, 0);
- coord.x_off = System.BitConverter.ToInt16(b3, 0);
- coord.y_off = System.BitConverter.ToInt16(b4, 0);
- return coord;
- }
- /// <summary>
- /// WGS84(GPS)坐标转火星坐标
- /// </summary>
- /// <param name="lat">纬度</param>
- /// <param name="lng">经度</param>
- public static void WGS2Mars(double lat, double lng)
- {
- //读取数据文件
- //这里读取文件的地方可以单独提出来, 读一次之后保存到内存里, 读取时比较耗时间. 或者放到数据库中去.
- FileStream fs = new FileStream("offset.dat", FileMode.OpenOrCreate, FileAccess.Read);
- BinaryReader br = new BinaryReader(fs);
- int size = (int)fs.Length / 8;
- ArrayList array = new ArrayList();
- for (int i = 0; i < size; i ++)
- {
- //按八个字节八个字节来读取, 放在MapCoord对象中,并添加到ArrayList中
- byte[] source = br.ReadBytes(8);
- array.Add(getMapCoordFromBytes(source));
- }
- br.Close();
- fs.Close();
- //将要查找的坐标放置在MapCoord对象中
- MapCoord search = new MapCoord();
- search.lat = (int)(lat * 100);
- search.lng = (int)(lng * 100);
- myReverserClass rc = new myReverserClass();
- //执行查找, 查询结果将返回array中的索引值
- int x = array.BinarySearch(0, array.Count, search, rc);
- //取得查找到的结果并进行计算
- MapCoord ret = (MapCoord)array[x];
- double pixY = latToPixel(lat, 18);
- double pixX = lngToPixel(lng, 18);
- pixY += ret.y_off;
- pixX += ret.x_off;
- lat = pixelToLat(pixY, 18);
- lng = pixelToLng(pixX, 18);
- //输出校正后的结果
- Console.WriteLine("欢迎来到火星,坐标: lat:{0},lng:{1} !!!", lat, lng);
- }
- static void Main(string[] args)
- {
- //测试一下
- WGS2Mars(30.283780,120.116356);
- Console.ReadLine();
- }
- }
class Program { const double M_PI = 3.14159265358979323846264338327950288; const double M_E = 2.71828182845904523536028747135266250;public class MapCoord {public int lng { set; get; } //12151表示121.51public int lat { set; get; } //3130表示31.30public int x_off { set; get; } //地图x轴偏移像素值public int y_off { set; get; } //地图y轴偏移像素值 }/// <summary> /// 自定义比较类 /// </summary> public class myReverserClass : IComparer {public int Compare(object x, object y){MapCoord data1 = (MapCoord)x, data2 = (MapCoord)y;int det_lng = data1.lng - data2.lng;if (det_lng != 0)return det_lng;elsereturn data1.lat - data2.lat;} }//这就需要一个把经纬度转换成地图xy轴坐标的算法:private static double lngToPixel(double lng, int zoom) {return (lng + 180) * (256L << zoom) / 360; }private static double latToPixel(double lat, int zoom) {double siny = Math.Sin(lat * M_PI / 180);double y = Math.Log((1 + siny) / (1 - siny));return (128 << zoom) * (1 - y / (2 * M_PI)); }//xy轴坐标加上对应的地图xy轴的偏移量,最后还要反过来将最终正确的地图xy轴坐标转换成正确的经纬度 private static double pixelToLng(double pixelX, int zoom) {return pixelX * 360 / (256L << zoom) - 180; }private static double pixelToLat(double pixelY, int zoom) {double y = 2 * M_PI * (1 - pixelY / (128 << zoom));double z = Math.Pow(M_E, y);double siny = (z - 1) / (z + 1);return Math.Asin(siny) * 180 / M_PI; }/// <summary> /// 将字节转化为具体的数据对象 /// </summary> /// <param name="buf"></param> /// <returns></returns> private static MapCoord getMapCoordFromBytes(byte[] buf) {//数据文档结构是八字节为一个坐标及其偏移量,分别为经度,纬度,x偏移量,y偏移量; 每两字节为一个数据MapCoord coord = new MapCoord();byte[] b1 = new byte[2], b2 = new byte[2], b3 = new byte[2], b4 = new byte[2];Array.Copy(buf, 0, b1, 0, 2);Array.Copy(buf, 2, b2, 0, 2);Array.Copy(buf, 4, b3, 0, 2);Array.Copy(buf, 6, b4, 0, 2);coord.lng = System.BitConverter.ToInt16(b1, 0);coord.lat = System.BitConverter.ToInt16(b2, 0);coord.x_off = System.BitConverter.ToInt16(b3, 0);coord.y_off = System.BitConverter.ToInt16(b4, 0);return coord; }/// <summary> /// WGS84(GPS)坐标转火星坐标 /// </summary> /// <param name="lat">纬度</param> /// <param name="lng">经度</param> public static void WGS2Mars(double lat, double lng) {//读取数据文件//这里读取文件的地方可以单独提出来, 读一次之后保存到内存里, 读取时比较耗时间. 或者放到数据库中去.FileStream fs = new FileStream("offset.dat", FileMode.OpenOrCreate, FileAccess.Read);BinaryReader br = new BinaryReader(fs);int size = (int)fs.Length / 8;ArrayList array = new ArrayList();for (int i = 0; i < size; i ++){//按八个字节八个字节来读取, 放在MapCoord对象中,并添加到ArrayList中byte[] source = br.ReadBytes(8);array.Add(getMapCoordFromBytes(source));}br.Close();fs.Close();//将要查找的坐标放置在MapCoord对象中MapCoord search = new MapCoord();search.lat = (int)(lat * 100);search.lng = (int)(lng * 100);myReverserClass rc = new myReverserClass();//执行查找, 查询结果将返回array中的索引值int x = array.BinarySearch(0, array.Count, search, rc);//取得查找到的结果并进行计算MapCoord ret = (MapCoord)array[x];double pixY = latToPixel(lat, 18);double pixX = lngToPixel(lng, 18);pixY += ret.y_off;pixX += ret.x_off;lat = pixelToLat(pixY, 18);lng = pixelToLng(pixX, 18);//输出校正后的结果Console.WriteLine("欢迎来到火星,坐标: lat:{0},lng:{1} !!!", lat, lng); }static void Main(string[] args) {//测试一下WGS2Mars(30.283780,120.116356);Console.ReadLine(); }}
OK,大功告成,火星人民欢迎您!!
参考资料: 原C语言帖 http://xcodev.com/wordpress/?p=131
原文地址: http://freshflower.iteye.com/blog/1606960
- offset.rar (2 MB)
转载于:https://www.cnblogs.com/lovewx/p/4146906.html
IOS中GPS定位偏移纠正(适用于Google地图)相关推荐
- GPS纠偏算法,适用于google,高德体系的地图
GPS纠偏算法,适用于google,高德体系的地图,精确度还比较高.我试了一下比高德本身的纠偏还精确点. /*** gps纠偏算法,适用于google,高德体系的地图* @author Adminis ...
- LBS位置服务中GPS定位、基站定位、wifi定位的区别
1.卫星定位 其原理是接收机接收卫星广播,通过解析可见卫星的位置.距离等信息以及相应算法得出自己的位置信息,误差在15米范围内,当前可视卫星数量将影响定位精度,可见卫星数量越多,精度越高,实际测试中在 ...
- android 百度坐标 gps,Android中gps定位不返回经纬度的解决方案
定位,算是android应用中一个非常常见的功能了吧,并且大部分的应用里基本也都会用到地图,所以以前的做法基本都是直接接入了百度.高德这些第三方定位,也没遇到过什么问题. 然而,最近的工作基本上都是做 ...
- U880纯GPS定位综合解决方案,支持谷歌地图老虎地图百度地图
一,背景篇 1. 在天国,我们都是不需要谷歌服务的,所有的国行都是没有谷歌服务的.但有太多的机油觉得也许天国之外的东西不一定坏,所以我们需要谷歌服务包(GMS). 我的第一个安卓机是摩托的里程碑,水货 ...
- 中国区GPS偏移纠正(适用于Google地图)
在做iOS开发时,用到一个获取当前位置周边商家的功能.当时每次我在获取从iPhone里GPS返回过来的数据到Google Place API上获取时总是发现,获取的商家并不是最近的,而是几百米以外的. ...
- android app gps 定位权限,uniapp 打开[ios/安卓]GPS定位权限
如何检测GPS有没有开启我是写在高德地图API接口中fail函数里的 openGps(){ let system = uni.getSystemInfoSync();// 获取系统信息 if (sys ...
- 在ios中fixed定位元素丢失,Date兼容NaN
Aphorism Preface 差不多有半年没有更新blog了, 现在在新的公司适应了,最近喜得一千金,也慢慢适应了新的生活. 今天更新一篇关于最近遇到的 ios fixed定位元素丢失 bug i ...
- IOS将GPS定位经纬度转换为高德地图经纬度
https://github.com/JackZhouCn/JZLocationConverter http://www.eoeandroid.com/forum.php?mod=viewthread ...
- uniapp | 打开iOS和Android实现GPS定位权限
原来真的有人,删掉手机里所有的娱乐软件,不管不顾任何东西,没日没夜的学习,就只是为了回到原来那个眼里有光被赋予希望的自己. 你要坚信每一个你想学习的念头,都是未来在向你求救! 懒惰是一个特别奇怪的东西 ...
最新文章
- C# Trim 的使用
- 【POJ】3268 Silver Cow Party (将有向图的边反转)
- NOIP2011 提高组 Day1
- Google 发布浏览器3D插件 O3D API
- C++ Primer 5th笔记(9)chapter9 顺序容器 get insert delete
- JQUERY设置或返回属性值attr
- php mysql 云虚拟机_虚拟机+apache+php+mysql 环境安装配置
- jQuery入门:认识jQuery
- springboot 统一异常处理
- linux 进入shell命令,linux或者shell进入vi命令
- cocos2dx[3.2](21)——观察者模式NotificationCenter
- bzoj1997 [Hnoi2010]Planar——2-SAT
- 数据+人工智能+模型——北京市新一代交通仿真模型框架
- 那些一出口就很Low的话
- mysql 查询活跃人数_查询活跃用户的数量SQL
- Intel VT学习笔记(八)—— 开启EPT
- 无人驾驶车辆纵向速度PID控制
- 数字货币&区块链动态
- C语言结构体变量 指针以及对结构体成员的访问
- java gis地图开发视频_开源GIS视频教程
热门文章
- UIGestureRecognizer手势介绍
- (0028)iOS 开发之Xcode使用技巧
- 一张图搞定iOS学习路线
- linux 超级权限图标,Linux下使用iconv库出错,急!!!
- oracle建表权限问题和JSP连接oracle数据库基本操作
- Ubuntu15.04 网站服务器环境搭建,php/html/css等学习环境搭建教程
- .NET学习之Foreach……
- 【原创】BI解决方案选型之ETL数据整合工具对比
- hadoop过程中遇到的错误与解决方法
- 解决ssh登录linux速度慢的问题(以centos7为例)