特性 | WGS-84 | GCJ-02(国测局坐标系) |
---|---|---|
性质 | 全球标准地理坐标系 | 中国官方加密偏移坐标系 |
制定方 | 美国国防部(1984年确立) | 中国国家测绘地理信息局(2002年推出) |
定位精度 | 真实地球坐标(GPS卫星原始数据) | 在WGS-84基础上人为加入随机偏移 |
法律地位 | 国际通用标准(谷歌地图、苹果地图境外使用) | 中国法定地图服务坐标系(高德、腾讯、百度境内使用) |
偏移目的 | 无偏移(科学测量基准) | 国家安全(防止高精度坐标被军事利用) |
#ifndef QGCTRANSFORM_H
#define QGCTRANSFORM_H
#include <QPointF>
#include <QtMath>
class QGCTransform
{
private:
// 克拉索夫斯基椭球参数
static constexpr const double a = 6378245.0; // 长半轴
static constexpr const double ee = 0.00669342162296594323; // 扁率
//判断是否在国内,不在国内则不做偏移
static bool outOfChina(double lat, double lon);
//度分格式转十进制度
static double dmToDegrees(double dm);
//纬度偏移计算
static double transformLat(double x, double y);
//经度偏移计算
static double transformLon(double x, double y);
public:
//wgs84转gcj02 返回lng,lat
static QPointF wgs84Togcj02(double wgsLat, double wgsLon);
};
#endif
#include "QGCTransform.h"
// 类外定义静态常量(C++11标准要求)
constexpr double QGCTransform::a;
constexpr double QGCTransform::ee;
bool QGCTransform::outOfChina(double lat, double lon)
{
if (lon < 72.004 || lon > 137.8347) return true;
if (lat < 0.8293 || lat > 55.8271) return true;
return false;
}
double QGCTransform::dmToDegrees(double dm)
{
// 分离度和分
int degrees = static_cast<int>(dm / 100);
double minutes = dm - degrees * 100;
// 转换公式:十进制度 = 度 + 分/60
return degrees + minutes / 60.0;
}
double QGCTransform::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(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 QGCTransform::transformLon(double x, 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;
}
QPointF QGCTransform::wgs84Togcj02(double wgsLat, double wgsLon)
{
double wgsLat1 = dmToDegrees(wgsLat);
double wgsLon1 = dmToDegrees(wgsLon);
if (outOfChina(wgsLat1, wgsLon1))
{
return QPointF(wgsLon1, wgsLat1);
}
double dLat = transformLat(wgsLon1 - 105.0, wgsLat1 - 35.0);
double dLon = transformLon(wgsLon1 - 105.0, wgsLat1 - 35.0);
const double radLat = wgsLat1 / 180.0 * M_PI;
double magic = sin(radLat);
magic = 1 - ee * magic * magic;
const 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);
return QPointF(wgsLon1 + dLon, wgsLat1 + dLat);
}
目前测试下来是可以使用的,我的配置环境是VS2022+QT5.15.2