zoukankan      html  css  js  c++  java
  • iOS 地图坐标转换

    地图坐标转换

    @(iOS)[iOS, 地图]

    简介

    • 各地图API坐标系统比较与转换;
    • WGS84坐标系:即地球坐标系,国际上通用的坐标系。设备一般包含GPS芯片或者北斗芯片获取的经纬度为WGS84地理坐标系,
    • 谷歌地图采用的是WGS84地理坐标系(中国范围除外);
    • GCJ02坐标系:即火星坐标系,是由中国国家测绘局制订的地理信息系统的坐标系统。由WGS84坐标系经加密后的坐标系。
    • 谷歌中国地图和搜搜中国地图采用的是GCJ02地理坐标系; BD09坐标系:即百度坐标系,GCJ02坐标系经加密后的坐标系;
    • 搜狗坐标系、图吧坐标系等,估计也是在GCJ02基础上加密而成的。

    自定义一个类来实现

    #import <Foundation/Foundation.h>
    
    @interface BaiduMapTransform : NSObject
    /// 百度转火星坐标系
    + (NSString *)Gps_bd09_To_Gcj02Lat:(double )bd_lat lon:(double )bd_lon;
    /// 火星转谷歌
    + (NSString *)Gps_gcj_To_Gps84Lat:(double )lat lon:(double )lon;
    /// 百度转谷歌 (WGS84)
    + (NSString *)Gps_bd09_To_Gps84Lat:(double )bd_lat lon:(double )bd_lon;
    @end
    
    • 代码实现
    #import "BaiduMapTransform.h"
    #import <math.h>
    const double a = 6378245.0;
    const double ee = 0.00669342162296594323;
    
    @implementation BaiduMapTransform
    
    #pragma mark - 百度地图转换
    /// 百度转火星坐标系
    + (NSString *)Gps_bd09_To_Gcj02Lat:(double )bd_lat lon:(double )bd_lon
    {
      double x = bd_lon - 0.0065, y = bd_lat - 0.006;
      double z = sqrt(x * x + y * y) - 0.00002 * sin(y * M_PI);
      double theta = atan2(y, x) - 0.000003 * cos(x * M_PI);
      double gg_lon = z * cos(theta);
      double gg_lat = z * sin(theta);
      NSLog(@"火星gps %@", [NSString stringWithFormat:@"%lf,%lf",gg_lon,gg_lat]);
      return [NSString stringWithFormat:@"%lf,%lf",gg_lat,gg_lon];
    }
    
    /// 火星转谷歌
    + (NSString *)Gps_gcj_To_Gps84Lat:(double )lat lon:(double )lon {
      NSString *str = [self transform:lat lon:lon];
      NSArray *gpsStr = [str componentsSeparatedByString:@","];
      double lontitude = lon * 2 - [gpsStr[1] doubleValue];
      double latitude = lat * 2 - [gpsStr[0] doubleValue];
      NSLog(@"谷歌gps %@", [NSString stringWithFormat:@"%lf,%lf",lontitude,latitude]);
      return [NSString stringWithFormat:@"%lf,%lf",latitude,lontitude];
    }
    
    /// 百度转谷歌(WGS84)
    + (NSString *)Gps_bd09_To_Gps84Lat:(double )bd_lat lon:(double )bd_lon {
      NSString *gcj02 = [self Gps_bd09_To_Gcj02Lat:bd_lat lon:bd_lon];
      NSArray *gpsStr = [gcj02 componentsSeparatedByString:@","];
      NSString *map84 = [self Gps_gcj_To_Gps84Lat:[gpsStr[0] doubleValue] lon:[gpsStr[1] doubleValue]];
    //  NSLog(@"谷歌gps %@", [NSString stringWithFormat:@"%lf,%lf",lontitude,latitude]);
      return map84;
    
    }
    
    // 下面都是一些固定算法
    + (double)transformLatX:(double)x y:(double)y {
      double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y
      + 0.2 * sqrt(fabs(x));
      ret += (20.0 * sin(6.0 * x * M_PI) + 20.0 * sin(2.0 * x * M_PI)) * 2.0 / 3.0;
      ret += (20.0 * sin(y * M_PI) + 40.0 * sin(y / 3.0 * M_PI)) * 2.0 / 3.0;
      ret += (160.0 * sin(y / 12.0 * M_PI) + 320 * sin(y * M_PI / 30.0)) * 2.0 / 3.0;
      return ret;
    }
    
    + (double) transformLonX:(double)x y:(double)y {
      double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1
      * sqrt(fabs(x));
      ret += (20.0 * sin(6.0 * x * M_PI) + 20.0 * sin(2.0 * x * M_PI)) * 2.0 / 3.0;
      ret += (20.0 * sin(x * M_PI) + 40.0 * sin(x / 3.0 * M_PI)) * 2.0 / 3.0;
      ret += (150.0 * sin(x / 12.0 * M_PI) + 300.0 * sin(x / 30.0* M_PI)) * 2.0 / 3.0;
      return ret;
    }
    
    + (BOOL)outOfChina:(double )lat lon:(double )lon {
      if (lon < 72.004 || lon > 137.8347)
        return true;
      if (lat < 0.8293 || lat > 55.8271)
        return true;
      return false;
    }
    
    + (NSString *)transform:(double )lat lon:(double )lon {
      if ( [self outOfChina:lat lon:lon]) {
        return [NSString stringWithFormat:@"%lf,%lf",lat,lon];
      }
      double dLat = [self transformLatX:(lon-105.0) y:(lat-35.0)];
      double dLon = [self transformLonX:(lon-105.0) y:(lat-35.0)];
      //  double dLat = transformLatX(lon - 105.0, lat - 35.0);
      //  double dLon = transformLonX(lon - 105.0, lat - 35.0);
      double radLat = lat / 180.0 * M_PI;
      double magic = sin(radLat);
      magic = 1 - ee * magic * magic;
      double sqrtMagic = sqrt(magic);
      dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * M_PI);
      dLon = (dLon * 180.0) / (a / sqrtMagic * cos(radLat) * M_PI);
      double mgLat = lat + dLat;
      double mgLon = lon + dLon;
      return [NSString stringWithFormat:@"%lf,%lf",mgLat,mgLon];
    }
    
    @end
    

    精度测试

    • 首先通过百度获取当前地址

      • 百度 113.151028,23.037077
    • 然后直接转成谷歌,也就是WGS84,中间会先转成火星坐标系,再转成谷歌

      • 火星 113.144468,23.031382
      • 谷歌 113.139012,23.033961
    • 测试网站

    总结

    • 项目中用到百度地图,而服务端需要标准地图的话,可以很方便的进行转换。
    • 而且转换结果还是相当精确的,目前测试的误差,保守估计10m左右.
  • 相关阅读:
    扩展问题
    oracle数据类型及其隐式转换 (摘,转载)
    oralce中to_char默认转换格式的理解
    oracle的to_char中的fm(转,摘录)
    Oracle中TO_DATE TO_CHAR格式(转,摘录)
    ZT Abstract Factory
    ZT Factory Pattern
    Singleton
    几本电子书比较
    名词后变为复数+s,或者+es等怎么读
  • 原文地址:https://www.cnblogs.com/songliquan/p/12784434.html
Copyright © 2011-2022 走看看