关于GCJ02和WGS84坐标系对比
来源:互联网 发布:服装电脑制版软件 编辑:程序博客网 时间:2024/06/14 17:46
大家都知道,在兲朝的电子地图的坐标都是经过了一个坐标偏移,叫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坐标系对比
- 关于GCJ02和WGS84坐标系的一点实验
- WGS84 GCJ02和BD09坐标系相互转换代码
- 各地图坐标系转换(WGS84坐标系,GCJ02坐标系,BD09坐标系)
- 关于GPS坐标系的几种概念以及相互转化(WGS84,GCJ02, BD09)
- 百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系互转
- PHP 不同地图坐标系经纬度转换 GCj02 WGS84 BD-09
- WGS84、GCJ02、BD09各坐标系之间的转换算法
- 百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换(JS版代码)
- 关于WGS84,GCJ02和BD09坐标在QT下的互相转换
- 地球坐标系(WGS84),火星坐标系(GCJ02), 百度坐标系(BD09)坐标转换
- wgs84到gcj02
- wgs84转gcj02
- WGS84、GCJ02坐标相关
- 一个提供了百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换的工具模块。
- [JS] 百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换(JS版代码)
- WGS84、GCJ02、BD09地图坐标系间的坐标转换及坐标距离计算
- WGS84坐标系
- 监听器(Listener)
- 最短路径树问题
- android notification通知栏方式更新APP
- CodeForces 44B Cola
- poj 3481 Double Queue(treap)
- 关于GCJ02和WGS84坐标系对比
- 回文数字
- 001-编辑器工作区 srt字幕文件
- 数字游戏
- 002-unity 资源及资源类型 srt字幕文件
- typedef struct,struct
- 使用mysql时遇到的各种问题
- Socket心跳包异常检测的C语言实现,服务器与客户端代码案例
- 2