最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

中国区GPS偏移纠正(适用于Google地图)

IT圈 admin 5浏览 0评论

中国区GPS偏移纠正(适用于Google地图)

在做iOS开发时,用到一个获取当前位置周边商家的功能。当时每次我在获取从iPhone里GPS返回过来的数据到Google Place API上获取时总是发现,获取的商家并不是最近的,而是几百米以外的。经多次尝试,确实是这样。我在网上搜索一下,发现原来是相关部门和谐掉了。相关部门规定:为了保证国家安全,所有的地图公司提供的地图必须对实际的GPS坐标进行一定的偏移,偏移后的GPS坐标系俗称火星坐标系,而这个偏移是不固定的,具体的算法是国家机密。悲催了,在网上找了很久,终于找到了一个解决方案:网上已经有人根据Google的相关接口,每隔0.1个经纬度获取一个地图偏移像素,把中国区的所有经纬度都转换了,组成一个数据文件。此数据文件是一个连续的结构数组:

typedef struct offset_data {int16_t lng;    //12151表示121.51int16_t lat;    //3130表示31.30int16_t x_off;  //地图x轴偏移像素值int16_t y_off;  //地图y轴偏移像素值
}offset_data;

然而这个偏移量是地图图片偏移的像素值,而我们需要的是实际上偏移的经纬度。这就需要一个把经纬度转换成地图xy轴坐标的算法:

static double lngToPixel(double lng, int zoom) {return (lng + 180) * (256L << zoom) / 360;
}
static double latToPixel(double lat, int zoom) {double siny =sin(lat * M_PI / 180);double y = log((1 + siny) / (1 - siny));return (128 << zoom) * (1 - y / (2 * M_PI));
}

然后把这个地图xy轴坐标加上对应的地图xy轴的偏移量,最后还要反过来将最终正确的地图xy轴坐标转换成正确的经纬度:

static double pixelToLng(double pixelX, int zoom) {return pixelX * 360 / (256L << zoom) - 180;
}
static double pixelToLat(double pixelY, int zoom) {double y = 2 * M_PI * (1 - pixelY / (128 << zoom));double z = pow(M_E, y);double siny = (z - 1) / (z + 1);return asin(siny) * 180 / M_PI;
}

我写了WGS2Mars方法,他的参数是经度和维度的地址,同时将转换好的经纬度传递回来。由于数据库的结构完全是按照顺序的,所以我用了c标准库的折半查找算法,你需要包含一下<stdlib.h>这个头文件。

static int compare_offset_data(offset_data *data1, offset_data *data2){int det_lng = (data1->lng)-(data2->lng);if (det_lng!=0) {return det_lng;}else{return (data1->lat)-(data2->lat);}
}void WGS2Mars(double *lat, double *lng){NSData *offsetFileData = [NSData dataWithContentsOfFile:@"offset.dat"];const void *buf = [offsetFileData bytes]; //byte buf for content of file "offset.dat"long long buflen = [offsetFileData length]; //length of byte buf for content of file "offset.dat"offset_data search_data;search_data.lat = (int)(*lat*100);search_data.lng = (int)(*lng*100);offset_data *ret = bsearch(&search_data, buf, buflen/sizeof(offset_data), sizeof(offset_data), (int (*)(const void *, const void *))compare_offset_data);//折半查找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);
}

数据库的下载地址:
.html


中国区GPS偏移纠正(适用于Google地图)

在做iOS开发时,用到一个获取当前位置周边商家的功能。当时每次我在获取从iPhone里GPS返回过来的数据到Google Place API上获取时总是发现,获取的商家并不是最近的,而是几百米以外的。经多次尝试,确实是这样。我在网上搜索一下,发现原来是相关部门和谐掉了。相关部门规定:为了保证国家安全,所有的地图公司提供的地图必须对实际的GPS坐标进行一定的偏移,偏移后的GPS坐标系俗称火星坐标系,而这个偏移是不固定的,具体的算法是国家机密。悲催了,在网上找了很久,终于找到了一个解决方案:网上已经有人根据Google的相关接口,每隔0.1个经纬度获取一个地图偏移像素,把中国区的所有经纬度都转换了,组成一个数据文件。此数据文件是一个连续的结构数组:

typedef struct offset_data {int16_t lng;    //12151表示121.51int16_t lat;    //3130表示31.30int16_t x_off;  //地图x轴偏移像素值int16_t y_off;  //地图y轴偏移像素值
}offset_data;

然而这个偏移量是地图图片偏移的像素值,而我们需要的是实际上偏移的经纬度。这就需要一个把经纬度转换成地图xy轴坐标的算法:

static double lngToPixel(double lng, int zoom) {return (lng + 180) * (256L << zoom) / 360;
}
static double latToPixel(double lat, int zoom) {double siny =sin(lat * M_PI / 180);double y = log((1 + siny) / (1 - siny));return (128 << zoom) * (1 - y / (2 * M_PI));
}

然后把这个地图xy轴坐标加上对应的地图xy轴的偏移量,最后还要反过来将最终正确的地图xy轴坐标转换成正确的经纬度:

static double pixelToLng(double pixelX, int zoom) {return pixelX * 360 / (256L << zoom) - 180;
}
static double pixelToLat(double pixelY, int zoom) {double y = 2 * M_PI * (1 - pixelY / (128 << zoom));double z = pow(M_E, y);double siny = (z - 1) / (z + 1);return asin(siny) * 180 / M_PI;
}

我写了WGS2Mars方法,他的参数是经度和维度的地址,同时将转换好的经纬度传递回来。由于数据库的结构完全是按照顺序的,所以我用了c标准库的折半查找算法,你需要包含一下<stdlib.h>这个头文件。

static int compare_offset_data(offset_data *data1, offset_data *data2){int det_lng = (data1->lng)-(data2->lng);if (det_lng!=0) {return det_lng;}else{return (data1->lat)-(data2->lat);}
}void WGS2Mars(double *lat, double *lng){NSData *offsetFileData = [NSData dataWithContentsOfFile:@"offset.dat"];const void *buf = [offsetFileData bytes]; //byte buf for content of file "offset.dat"long long buflen = [offsetFileData length]; //length of byte buf for content of file "offset.dat"offset_data search_data;search_data.lat = (int)(*lat*100);search_data.lng = (int)(*lng*100);offset_data *ret = bsearch(&search_data, buf, buflen/sizeof(offset_data), sizeof(offset_data), (int (*)(const void *, const void *))compare_offset_data);//折半查找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);
}

数据库的下载地址:
.html


发布评论

评论列表 (0)

  1. 暂无评论