WGS84坐标转火星坐标(iOS篇)

2023-11-02

WGS84坐标转火星坐标(iOS篇)

--转自:keakon的涂鸦馆 http://www.keakon.net/2011/07/02/WGS84%E5%9D%90%E6%A0%87%E8%BD%AC%E7%81%AB%E6%98%9F%E5 

 

在这个神奇的国度里,我们总得学习一些有中国特色的东东,例如“火星坐标”。也许有人还不知道这是什么玩意,我就简要介绍一下吧。

如果你有带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;
@property (nonatomic, retain) IBOutlet UITextField *marsText;
@property (nonatomic, retain) CLLocationManager *locationManager;

@end

//  MapDemoViewController.m

#import "MapDemoViewController.h"

@implementation MapDemoViewController

@synthesize wgsText;
@synthesize marsText;
@synthesize locationManager;

- (void)viewDidLoad {
    [super viewDidLoad];
    
    if ([CLLocationManager locationServicesEnabled]) { // 检查定位服务是否可用
        locationManager = [[CLLocationManager alloc] init];
        locationManager.delegate = self;
        [locationManager startUpdatingLocation]; // 开始定位
    }
}

// 定位成功时调用
- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
           fromLocation:(CLLocation *)oldLocation {
    CLLocationCoordinate2D coordinate = newLocation.coordinate;
    CLLocationDegrees latitude = coordinate.latitude;
    CLLocationDegrees longitude = coordinate.longitude;
    wgsText.text = [NSString stringWithFormat:@"%f,%f", latitude, longitude];
}

// 定位失败时调用
- (void)locationManager:(CLLocationManager *)manager
       didFailWithError:(NSError *)error {
    wgsText.text = [error localizedDescription];
    marsText.text = @"";
}

- (void)viewDidUnload {
    self.wgsText = nil;
    self.marsText = nil;
    self.locationManager = nil;
}

- (void)dealloc {
    [wgsText release];
    [marsText release];
    [locationManager release];
    [super dealloc];
}

@end
构建前别忘了在Framework里加上CoreLocation.framework。这个例子只能在真机上运行,因为模拟器没有定位功能,肯定会失败。
如果没出现什么差错的话,你可以看到wgsText对应的文本框里会显示你的WGS84坐标了,不过marsText还是空白。

接下来把SDK中的include文件夹复制到项目的Classes文件夹下,再创建一个lib文件夹,把libiMapSDKLib.a复制进去(因为模拟器没用,所以直接复制release版的),再将这些文件全部添加到项目里。
接着在Framework里加上libstdc++.dylib(一共有5个,貌似随便选一个即可)。
然 后打开项目设置,把“Other Linker Flag”设为“-liMapSDKLib”(也就是去掉库文件名前后的lib和.a,并在前面加上-l参数)。再将“Header Search Path”设为“$(SRCROOT)/include”,Recursive打钩;“Library Search Path”设为“$(SRCROOT)/lib”。
这样设置就完成了,build一下,如果没error就表示正常。

接下来要创建一个MSearch对象,由于需要持久存在,将其作为MapDemoViewController的属性。
而这个对象的delegate属性需要实现MSearchDelegate和GPSToOffsetByPoint_Delegate协议,于是也给MapDemoViewController加上。
GPSToOffsetByPoint_Delegate协议还包含了MLONLAT poiXY和MCOORDINATESEARCHOPTIONS options这2个属性(都是结构,无需retain),因此也得加上。
最后别忘了加上“#import "MSearch.h"”。

定义完成后,就可以开始创建MSearch对象了。这个对象初始化时需要与MapABC服务器通信,验证API KEY是否有效。
这个验证过程是异步的,当验证完成后才能使用它,因此当检查到定位服务可用时,就可以立刻创建它了:
self.search = [MSearch MSearchWithKey:@"你申请的API KEY" delegate:self];

而在获取到WGS84坐标后,就可以查询火星坐标了:
poiXY.X = longitude; // 经度
poiXY.Y = latitude; // 维度
[search GPSToOffSetByPoint:self];
这里不需要设置options属性,使用初始值即可。GPSToOffSetByPoint:方法会返回SEARCH_THREAD_ID,由于不需要停止线程,因此无视。

当获取到火星坐标后,就会调用GPSToOffsetResponse:方法了。这个方法的lonlat参数就是火星坐标了:
-(void) GPSToOffsetResponse:(MLONLAT)lonlat {
    marsText.text = [NSString stringWithFormat:@"%f,%f", lonlat.Y, lonlat.X];
}

现在build一下,你会发现出来一堆error了。一看发现是无法识别template语法,于是把2个.m文件重命名成.mm文件,使其可以混用C++。
再 次build,仍然会出现“___restore_vfp_d8_d15_regs”之类完全看不懂的error。不过最后一行有提到 “symbol(s) not found for architecture armv6”什么的,于是在项目设置里改成只编译ARMv7的,这下终于成功了。(支持ARMv6的解决办法暂时没找到,不知道是不是这库的限制。)

于是立刻尝试了一番,检验是否有效。
先用iPhone自带的地图应用定位,位置准确:

再用刚写的应用来定位,找到火星坐标:

最后到Google地图搜索这个火星坐标,与地图应用的定位吻合:


OK,大功告成,欢迎来到火星~


2011年11月27日更新:

刚发现MKLocationManager这个私有类有个_applyChinaLocationShift方法可以解决偏移,于是尝试了一番:
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>

@class MKLocationManager;

@interface ViewController : UIViewController <CLLocationManagerDelegate> {
    UITextField *wgsText;
    UITextField *marsText;
    CLLocationManager *locationManager;
    MKLocationManager *shiftLocationManager;
}

@property (nonatomic, retain) IBOutlet UITextField *wgsText;
@property (nonatomic, retain) IBOutlet UITextField *marsText;
@property (nonatomic, retain) CLLocationManager *locationManager;
@property (nonatomic, retain) MKLocationManager *shiftLocationManager;

@end


#import <MapKit/MapKit.h>
#import "ViewController.h"

@interface MKLocationManager : NSObject
- (CLLocation*)_applyChinaLocationShift:(CLLocation*)arg;
- (BOOL)chinaShiftEnabled;
+ (id)sharedLocationManager;
@end

@implementation ViewController

@synthesize wgsText;
@synthesize marsText;
@synthesize locationManager;
@synthesize shiftLocationManager;

- (void)viewDidLoad
{
    [super viewDidLoad];
    if ([CLLocationManager locationServicesEnabled]) {
        locationManager = [[CLLocationManager alloc] init];
        locationManager.delegate = self;
        [locationManager startUpdatingLocation];
        
        self.shiftLocationManager = MKLocationManager.sharedLocationManager;
        if (shiftLocationManager.chinaShiftEnabled) {
            [[[MKMapView alloc] init] release]; // 必须初始化一个MKMapView对象,否则调用_applyChinaLocationShift:时会出错
        } else {
            self.shiftLocationManager = nil;
        }
    }
}

- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
           fromLocation:(CLLocation *)oldLocation {
    CLLocationCoordinate2D coordinate = newLocation.coordinate;
    wgsText.text = [NSString stringWithFormat:@"%f,%f", coordinate.latitude, coordinate.longitude];

    if (shiftLocationManager) {
        newLocation = [shiftLocationManager _applyChinaLocationShift:newLocation]; // 获得偏移后的坐标
        coordinate = newLocation.coordinate;
        marsText.text = [NSString stringWithFormat:@"%f,%f", coordinate.latitude, coordinate.longitude];
    } 
}

// ...

@end
接着添加CoreLocation和MapKit这2个框架,就可以构建了。
测 试时发现这个函数也需要联网,否则拿到的坐标为{0.0,0.0};不过获取到一次后,就可以断开网络了,这时候也能正常地偏移,而且不是线性的,看来是 有内置的算法。经嗅探发现是要往http://www.google.cn/glm/mmap发送2次POST请求,不过都是二进制的数据,看不懂。
不过和其他私有API一样,模拟器上是没法用的,而且要冒被Apple拒绝的危险。
最后,据说iOS 5上要改用GEOLocationShiftProvider,不过我找不到相应资料,完全不会用…而且因为要使用GMM这个私有框架,很容易被Apple查出来。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WGS84坐标转火星坐标(iOS篇) 的相关文章

  • Java 加解密技术系列之 MD5

    序 上一篇文章中 介绍了最基础的编码方式 BASE64 也简单的提了一下编码的原理 这篇文章继续加解密的系列 当然也是介绍比较基础的加密方式 MD5 MD5 属于单向加密算法 是不可逆的加密方式 也就是说 采用了 MD5 加密方式加密之后
  • 什么是Base64?

    Base64概念 什么是Base64 按照RFC2045的定义 Base64被定义为 Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式 The Base64 Content Transfer Encod
  • java IDEA加密/解密 源码

    package tool import org apache commons codec binary Base64 import org bouncycastle jce provider BouncyCastleProvider imp
  • 流氓ONU问题分析和处理

    1 流氓ONU问题分析和处理 1 1 故障现象描述 故障现象为 1 设备被判定为流氓ONU 2 同一PON口下其他设备都在反复掉线 只有这一台设备一直正常注册 3 设备下所有ONU都在反复上下线 上下线时间没有规律 4 只有几台设备能正常注
  • “陷阱”病毒源代码大揭密

    7月初在我国出现了一种名叫 陷阱 Trap 的新型恶性病毒 并在7月5日全面爆发 目前国内已有不少的网站和用户遭受 陷阱 的袭击 造成网络系统瘫痪 文件丟失现象严重 该病毒是一种网络脚本语言病毒 并是同时使用了VBScript 和 Java
  • m3u8加密文件原理及下载脚本

    一 加密ts文件解密 EXTM3U EXT X VERSION 3 EXT X MEDIA SEQUENCE 0 EXT X ALLOW CACHE YES EXT X TARGETDURATION 13 EXT X KEY METHOD
  • vue-router路由中对query中的参数进行加密

    vue router路由中对query中的参数进行加密 源码地址在文末 在创建路由的时候 添加两个方法 stringifyQuery 序列化传入的query参数 方法可以接收一个对象参数 在new Router的时候传递这个属性 在序列化q
  • 在OpenSSL中添加自定义加密算法

    在OpenSSL中添加自定义加密算法 1 加密算法的加载 1 2 密码算法接口的定义 4 3 示例 8 1 加密算法的加载 在调用加密算法之前 通过调用OpenSSL add all algorithms来加载加密算法函数和单向散列算法函数
  • APK反编译破解方法与加密措施

    所谓APK指的是Android操作系统的应用程序安装文件 所谓Crack 简单地理解为 破解 我具体指的是反编译APK文件进行汇编级的代码分析 并修改或插入自己的代码 重新签名打包为APK文件 以达到改变程序原有行为的目的 由以上的说明可知
  • MD5算法分析及逆向详解

    题外话 最近在看加密与解密 看到加密算法部分 感觉对于初次接触的新手还是有些难度的 故写下该篇文章 算作一个引导吧 新手飘过 老鸟勿笑 基本原理 MD5的典型应用是对一段信息 Message 产生信息摘要 Message Digest 以防
  • 如何评估加解密代码?

    在不深入研究代码的具体实现的情况下 如何评估加解密代码的有效性 强度 背景 迫于无赖 项目组只能安排1位新手设计一系列的加密算法 用于对本地文件和二进制代码的加密 幸运的是 对加密强度并没有过高的要求 但也希望能够有效的评估代码 并实现自动
  • 可加密解密的MD5算法

    public class MD5andKL MD5加码 32位 public static String MD5 String inStr MessageDigest md5 null try md5 MessageDigest getIn
  • 关于火星坐标系统

    转载 关于火星坐标系统 2011 09 08 23 11 57 分类 默认分类 字号 订阅 偶然得知中国有一种火星坐标系统 其原理是这样的 保密局开发了一个系统 能将实际的坐标转换成虚拟的坐标 所有在中国销售的数字地图必须使用这个系统进行坐
  • rdp协议解读

    转自 http blog csdn net jiangtao killer article details 6940346 一 前言 RDP 远程显示协议 Remote Display Protocol 简称RDP 提供了客户和服务器之间的
  • CTF中那些脑洞大开的编码和加密

    0x00 前言 正文开始之前先闲扯几句吧 玩CTF的小伙伴也许会遇到类似这样的问题 表哥 你知道这是什么加密吗 其实CTF中脑洞密码题 非现代加密方式 一般都是各种古典密码的变形 一般出题者会对密文进行一些处理 但是会给留一些线索 所以写此
  • Android AES加密算法工具类

    1 AES加密工具类 本篇文章使用PKCS5Padding加密方式 package com example aesdemo import java io UnsupportedEncodingException import javax c
  • shell脚本中嵌入二进制文件

    最近有人问我 一个集群监控软件的安装文件特别 诡异 说脚本里有 乱码 却能执行 是怎么回事 我看了才发现这个东西原来是典型的脚本嵌套代码的模式 这里就讲讲吧 反正好久没写东西了 某些比较 拽 的单位在发布Linux软件时以一种特殊的形式发布
  • 9.2 流程分析

    介绍了系统文件加密和文件解密的流程 那么我们本例主要涉及两个核心函数个函数Encrypt File和Decrypt File 使用Encrypt File函数完成文件加密功能 Decrypt File函数完成文件解密功能 下面介绍这两个函数
  • 使用 Oracle的存储过程实现数据加密和解密

    我们都知道 几乎所有的数据库都有存储过程 但在实际开发中 它有什么用途了 下面使用Oracle的存储过程 采用Oracle自带的dbms obfuscation toolkit desencrypt对数据进行加密 需要注意的是密码的长度必须
  • TLSv1.2抓包解密分析过程之ECDHE_RSA_WITH_AES_128_CBC_SHA256

    ECDHE RSA WITH AES 128 CBC SHA256模式下 RSA只用于身份验证 不用于加密 加密密钥是通过有限域的椭圆曲线算法交换的 需要拿到ECDH的私钥才能解密 本文的demo样本使用了特殊方法来获取这些参数 椭圆曲线加

随机推荐

  • 电机的堵转检测及处理

    基于L298N控制的电机的堵转检测及其处理 一 L298N原理 二 电机堵转检测 三 电机堵转处理 一 L298N原理 1 L298N datasheet 2 使用须知 工作电压高 最高工作电压可达46V 输出电流大 瞬间峰值电流可达3A
  • jeesite框架分析理解

    前文 jeesite代码生成器的使用 实例 报销表 地址 http blog csdn net m0 38021128 article details 68490920 前文中使用了jeesite框架的代码生成功能实现了一个小实例 但是实际
  • STM32CubeMX—串口空闲中断+DMA接收

    一 串口中断通信 串口中断方式的特点 发送数据时 将一字节数据放入数据寄存器DR 接收数据时 将DR的内容存放到用户存储区 中断方式不必等待数据的传输过程 只需要在每字节数据收发完成后 由中断标志位触发中断 在中断服务程序中放入新的一字数据
  • iOS 微信发布 8.0.12 正式版,寂寞来袭

    今天微信突然更新8 0 12正式版 我马上更新 更新完后并没有发现什么新功能 我就赶紧发文告诉大家 大家快去更新 更新看看这次更新了什么 我在AppStore商店更新完毕后就大概看了一下 并没有什么实质性的功能 可能内测功能还是内测人使用吧
  • org.apache.catalina.core.ApplicationContext.log ssi: Can‘t find file: /index.htmlERROR ErrorPageFil

    自己配置的tomcat 部署应用时提示错误信息 org apache catalina core ApplicationContext log ssi Can t find file index html ERROR ErrorPageFi
  • 如何设计一个高并发系统?

    原创 苏三呀 苏三说技术 2023 09 08 08 21 发表于四川 收录于合集 系统设计3个 大家好 我是苏三 又跟大家见面了 前言 最近有位粉丝问了我一个问题 如何设计一个高并发系统 这是一个非常高频的面试题 面试官可以从多个角度 考
  • 【VUE2】VUE2基础知识和原理--超详细--超简介--零基础(一)

    vue基础知识和原理 1 初识Vue 想让Vue工作 就必须创建一个Vue实例 且要传入一个配置对象 demo容器里的代码依然符合html规范 只不过混入了一些特殊的Vue语法 demo容器里的代码被称为 Vue模板 Vue实例和容器是一一
  • 兼容火狐--常见问题修改

    此文为本人在实际工作中遇到的情况做的记录 所以比较乱 主要用于自己日后查看 如果对大家有帮助 当然也更好 最普遍的情况 当遇到功能不好使的情况 首先按f12看控制台有没有报错 A如果有定位错误 常见错误 window frames ifra
  • Qt与MSVC中文乱码问题的解决方案

    一 问题是什么 在学习Qt编程的过程中 大多数人都遇到过中文乱码的问题 总结起来有三类 1 Qt Creator中显示的汉字变为乱码 编辑器上方有 Could not decode with UTF 8 encoding Editing n
  • PHP与MySQL程序设计 学习笔记 第二章 环境配置

    主流Linux发行包中都加入了Apache 如果没有 也可以利用发行包的打包服务轻松安装 如Ubuntu的apt get命令 http httpd apache org download cgi可导航到离你最近的镜像站点 windows安装
  • 如何查看linux服务器的版本和配置信息

    linux下看配置 可没有windows那么直观 你只能一个一个查看 一 cpu root srv more proc cpuinfo grep modelname root srv grep model name proc cpuinfo
  • python quit()讲解_Python:pygame.QUIT()

    Just been messing around with pygame and ran into this error CODE import sys import pygame pygame init size width height
  • pytorch入门级教程——分类代码分析与实现(iris数据集)

    用iris数据进行分类训练 并可视化 首先导入API import torch import torch nn functional as F import matplotlib pyplot as plt from sklearn dec
  • 斐波那契数列的对数时间复杂度计算分析(说服你对数时间复杂度是可以算的)+求平方的对数时间分析

    我先强调一下 请侧重注意时间复杂度 不要在意语句的作用 先上一下斐波那契的代码 解释在注释里面 跟语言没关系 都差不多啦 大家想看别的语言的解释 没学过Java也能看 只是它在第一个 我就直接复制了 真的 力扣 先上只看时间复杂度的句子 c
  • 离散数学和算法

    特点 离散数学涉及研究可数的 不同的元素 其原理广泛用于构建计算机科学和数据科学的算法 离散数学概念的知识将帮助您理解位于数据驱动任务核心的算法 二进制和通用数学 快速掌握离散数学原理 在学习离散数学语言时 还将学习对研究和描述计算机科学和
  • 【浅谈算法】1-冒泡排序优化(JAVA实现)

    原理 从左至右遍历数组 每两个数比较一次 并将大数向右移 如 给定数组 5 1 9 7 实现从左至右依次由小到大的排序 其步骤为 第一趟操作 1 比较 5 1 两个数 如果左数大于右数 则将两数交换位置 反之则不变 因为5 gt 1 所以交
  • 基于SSM+MySQL+Layui的客户关系信息管理系统

    登陆 登陆首页 市场活动 活动详情 线索管理 线索详情 客户管理 联系人 交易管理 交易管理 个人信息 角色信息 技术描述 开发工具 Idea Eclipse 数据库 mysql Jar包仓库 Maven 前段框架 jquery Jsp 后
  • 【python与数据分析】实验十三 北京市空气质量

    目录 一 实验内容 二 完成情况 三 数据分析 1 问题描述 2 编程思路 3 程序代码 4 程序运行结果 1 2014年 2019年AQI时间序列折线图 2 各年AQI折线图 AQI直方图 PM2 5与AQI散点图 空气质量整体情况的饼图
  • Linux Git-v2.35.1的安装与配置

    Git v2 35 1的安装与配置 Git官网下载地址 1 下载安装包和依赖库 解压 检查 编译 安装 删除安装包和解压目录 wget https mirrors edge kernel org pub software scm git g
  • WGS84坐标转火星坐标(iOS篇)

    WGS84坐标转火星坐标 iOS篇 转自 keakon的涂鸦馆 http www keakon net 2011 07 02 WGS84 E5 9D 90 E6 A0 87 E8 BD AC E7 81 AB E6 98 9F E5 在这个