大家都知道,在兲朝的电子地图的坐标都是经过了一个坐标偏移,叫GCJ_02的东西。在网上发现了将WGS84经纬度转成GCJ02的一个代码,写了个小程序测试了下看看全国各地的偏移量有多大。

关于WGS84转GCJ02的资料网上很多,我参考的是https://on4wp7.codeplex.com/SourceControl/changeset/view/21483#EvilTransform.cs。

先放一个处理的结果图,大概说明一下,绿色为偏移量最小的地方,红色为偏移量最大地方。右下角为图例,最小值为0.000213487度大概为20多米,最大值为0.0104393大概为1公里多(不过这个地点已经超过我国范围了,下图右上角的区域)。关于GCJ02这个坐标系这里不讨论,下面主要说一下怎么用GDAL之类的库生成下面这个彩色的误差图像。

首先,找个中国的四至范围(陆地区域) 最西为东经 73°,最东为东经 135.5°。最男为北纬 18°,最北为北纬 54°,然后指定一个输出图像的格网大小,也就是分辨率,上面这个图大致为10000米也就是10公里一个像素。这样就可以得到这个图像的大小和仿射变换的参数了。

接下来,创建图像,然后遍历图像的每一个像素值,并且计算得到该像素值行列号对应的真实的WGS84经纬度坐标。

然后将WGS84经纬度通过上面的网址里面的转换关系计算转换后的GCJ02坐标系下的经纬度,然后计算这两个经纬度之间的距离,这里简单起见,直接用经纬度的欧拉距离,实际上应该用椭球上的两点大圆距离。

最后将每个点的距离计算出来,写出到图像即可。下面是全部代码。

最后牢骚几句。其实从上面这个图以及下面的公式可以发现,兲超某单位搞出来的这个坐标转换还是很厉害的,误差每个地方都不一样,而且还是连续的,从公式中可以看出,坐标转换的公式由一个关于经纬度的线性多项式(次数从0.5到2)加上经纬度的正弦函数组成。如果都是线性多项式的话,可以很容易推到反函数,但是后面加了一个非线性的函数(正弦函数应该是为了周期性的增加误差用的),这样反函数就非常不容易推导出来。所以关于从GCJ02坐标系转到WGS84只能用迭代法来进行求解了。

// 兲朝火星坐标系偏移公式
// https://on4wp7.codeplex.com/SourceControl/changeset/view/21483#EvilTransform.cs
static double transformLat(double x, double y)
{
double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * sqrt(abs(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;
} static double transformLon(double x, double y)
{
double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(abs(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;
} // World Geodetic System ==> Mars Geodetic System
void WGS2GCJTransform(double wgLon, double wgLat, double &mgLon, double &mgLat)
{
const double a = 6378245.0;
const double ee = 0.00669342162296594323; double dLat = transformLat(wgLon - 105.0, wgLat - 35.0);
double dLon = transformLon(wgLon - 105.0, wgLat - 35.0); double radLat = wgLat / 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); mgLat = wgLat + dLat;
mgLon = wgLon + dLon;
} void CalcGCJ02ToWGS84Error(const char *pszFile, double dRes)
{
GDALAllRegister();
GDALDriver *pDirver = (GDALDriver *)GDALGetDriverByName("GTiff"); //中国国土面积的四至(陆地区域) 最西为东经 73°,最东为东经 135.5°。最男为北纬 18°,最北为北纬 54°
double dMinX = 73.0;
double dMaxX = 135.5;
double dMinY = 18.0;
double dMaxY = 54.0; // 根据指定的分辨率计算输出图像大小
int nWidth = static_cast<int>((dMaxX - dMinX) / dRes + .5);
int nHeight = static_cast<int>((dMaxY - dMinY) / dRes + .5); printf("%dx%d\n", nWidth, nHeight); // 构造输出图像的仿射变换参数
double dGeoTransform[6] = {dMinX, dRes, 0, dMaxY, 0, -dRes}; // 创建输出图像
GDALDataset* poDS = pDirver->Create(pszFile, nWidth, nHeight, 1, GDT_Float32, NULL);
poDS->SetGeoTransform(dGeoTransform);
poDS->SetProjection(SRS_WKT_WGS84); //GDALRasterBand *pBandLon = poDS->GetRasterBand(1);
//GDALRasterBand *pBandLat = poDS->GetRasterBand(2);
GDALRasterBand *pBandDis = poDS->GetRasterBand(1);
double *pBuffer = new double[nWidth];
double *pDstLon = new double[nWidth];
double *pDstLat = new double[nWidth]; for (int i=0; i<nHeight; i++)
{
#pragma omp parallel for
for (int j=0; j<nWidth; j++)
{
double dSrcLon, dSrcLat;
GDALApplyGeoTransform(dGeoTransform, j, i, &dSrcLon, &dSrcLat);
WGS2GCJTransform(dSrcLon, dSrcLat, pDstLon[j], pDstLat[j]); pDstLon[j] = dSrcLon - pDstLon[j];
pDstLat[j] = dSrcLat - pDstLat[j];
double dDis = sqrt(pDstLon[j]*pDstLon[j] + pDstLat[j]*pDstLat[j]);
pBuffer[j] = dDis;
} //pBandLon->RasterIO(GF_Write, 0, i, nWidth, 1, pDstLon, nWidth, 1, GDT_Float64, 0, 0);
//pBandLat->RasterIO(GF_Write, 0, i, nWidth, 1, pDstLat, nWidth, 1, GDT_Float64, 0, 0);
pBandDis->RasterIO(GF_Write, 0, i, nWidth, 1, pBuffer, nWidth, 1, GDT_Float64, 0, 0);
} RELEASE(pDstLon);
RELEASE(pDstLat);
RELEASE(pBuffer); GDALClose(GDALDatasetH(poDS));
}

关于GCJ02和WGS84坐标系的一点实验的更多相关文章

  1. 百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换(JS版代码)

    /** * Created by Wandergis on 2015/7/8. * 提供了百度坐标(BD09).国测局坐标(火星坐标,GCJ02).和WGS84坐标系之间的转换 */ //定义一些常量 ...

  2. GCJ-02火星坐标系和WGS-84坐标系转换关系

    GCJ-02火星坐标系和WGS-84坐标系转换关系 WGS-84:GPS坐标系 GCJ-02:火星坐标系,国测局02年发布的坐标体系,高德,腾讯等使用. BD-09:百度坐标系,百度自研,百度地图使用 ...

  3. wgs84坐标系与gcj02坐标系转换误差分布图 | Mapping the Error in Transformation between WGS84 and GCJ02 Coordinations

    国际上通用的是wgs84坐标系,而我国对于境内的坐标进行了加密,采用了gcj02坐标系,或者称为火星坐标系.亢孟军老师带的一门课<多媒体电子地图设计>要求我们从wgs84坐标系转换为gcj ...

  4. 获取全国市以及地理坐标,各大坐标系北斗,百度,WGS-84坐标系的转换,有图,有代码

    1 先上坐标取到的值: 获取到的坐标部分如下: '北京市':[116.39564503788,39.92998577808], '天津市':[117.21081309155,39.1439299033 ...

  5. WGS84坐标系图层转火星坐标系(是整个图层转哟,不是转单点坐标)

    开篇唠叨(着急的略过) 大天朝“火星坐标系”小科普:是一种国家保密插件,对真实坐标系统进行人为的加偏处理,将真实的坐标加密成虚假的坐标,加密后的坐标被称为火星坐标系统.所有的电子地图所有的导航设备,都 ...

  6. 北京54全国80及WGS84坐标系的相互转换

    这三个坐标系统是当前国内较为常用的,它们均采用不同的椭球基准.其中北京54坐标系,属三心坐标系,大地原点在苏联的普而科沃,长轴6378245m,短轴6356863,扁率1/298.3:西安80坐标系, ...

  7. 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法

    $x_pi = 3.14159265358979324 * 3000.0 / 180.0; //火星坐标系 (GCJ-02)转百度坐标系 (BD-09)算法 function bd_encrypt($ ...

  8. 【PHP版】火星坐标系 (GCJ-02) 与百度坐标系 (BD-09ll)转换算法

    首先感谢java版作者@宋宋宋伟,java版我是看http://blog.csdn.net/coolypf/article/details/8569813 然后根据java代码修改成了php代码. & ...

  9. WGS84、WebMercator、GCJ02和BD09坐标系简介与转换

    WGS84(GPS): 地心坐标系,空间直角坐标系,原点与地球质心重合,为GPS采用的坐标系,也是目前广泛使用的GPS全球卫星定位系统使用的坐标系. 通过GPS可以直接获取WGS84下的坐标(B,L, ...

随机推荐

  1. [Noi2016]优秀的拆分

    来自F allDream的博客,未经允许,请勿转载,谢谢. 如果一个字符串可以被拆分为 AABB 的形式,其中 A和 B是任意非空字符串,则我们称该字符串的这种拆分是优秀的. 例如,对于字符串 aab ...

  2. VS生成项目时,有些文件无法复制到输出目录的解决办法

    有时候,我们在生成项目时,发现有些文件如:.jpg的图片文件,无法复制到输出目录中,此时会非常纠结,反复的清理项目,重新生成,依旧不能解决此问题.后来我打开.csproj的项目工程文件时,经过对比发现 ...

  3. Missing URI template variable 'XXXX' for method parameter of type String

    原因:就是spring的controller上的@RequestMapping的实参和方法里面的形参名字不一致 方法:改成一样就可. ps.还能用绑定的方法,不建议,因为太麻烦了 @RequestMa ...

  4. KMP及其改进算法

    本文主要讲述KMP已经KMP的一种改进方法.若发现不正确的地方,欢迎交流指出,谢谢! KMP算法的基本思想: KMP的算法流程: 每当一趟匹配过程中出现字符比较不等时,不需回溯 i 指针,而是利用已经 ...

  5. Nginx+tomcat配置集群负载均衡

    开发的应用采用F5负载均衡交换机,F5将请求转发给5台hp unix服务器,每台服务器有多个webserver实例,对外提供web服务和socket等接口服务.之初,曾有个小小的疑问为何不采用开源的a ...

  6. Web压力测试和手机App测试

    总纲:认识测试关系和目标http://blog.csdn.net/superxgl/article/details/27189631 一.web测试和App服务端测试 软件安装 建议安装loadrun ...

  7. [转载]致创业者:APP已死 服务永生

    前几日,有位创业者和我讲他在带领团队做一个将爱踢球的人集中在一起的App,我告诉他你的创业方向错了.原因在于你的目的是要为爱踢球的人提供服务,而你现在却在竭尽全力的做App,你应该做的是设计你为爱踢球 ...

  8. django之数据库orm

    一.数据库的配置 1 django默认支持sqlite,mysql, oracle,postgresql数据库. <1>sqlite django默认使用sqlite的数据库,默认自带sq ...

  9. iOS开源照片浏览器框架SGPhotoBrowser的设计与实现

    简介 近日在制作一个开源加密相册时附带着设计了一个照片浏览器,在进一步优化后发布到了GitHub供大家使用,该框架虽然没有MWPhotoBrowser那么强大,但是使用起来更为方便,操作更符合常规相册 ...

  10. 一小时入门PHP

    [版权申明:本文系作者原创,转载请注明出处] 文章出处:[http://blog.csdn.net/sdksdk0/article/details/52332296](http://blog.csdn ...