GPS坐标(大地坐标)转高斯平面坐标,并计算 GPS 坐标(大地坐标)两点间的距离

元气小坏坏 提交于 2020-03-29 07:06:21

不知道啥时候在网上找到的算法,经实验发现貌似挺精确的,经修改后备用:

#include <cmath>

//高斯平面坐标系
struct CRDCARTESIAN
{
    double x;
    double y;
    double z;
} ;

//大地坐标系(可以是 北京54坐标系,西安80坐标系,WGS84坐标系(GPS 坐标))
struct CRDGEODETIC
{
    double longitude; //经度
    double latitude; //纬度 
    double height; //大地高,可设为0
};

#define WGS84 84    //WGS84坐标系(GPS 坐标)
#define BJ54 54     //北京54坐标系
#define XIAN80 80   //西安80坐标系
#define ZONEWIDE3 3 //投影带宽度 3
#define ZONEWIDE6 6 //投影带宽度 6

//---------------------------------------------------------------------------
void BLTOXY(CRDCARTESIAN * pcc, CRDGEODETIC * pcg, int Datum, int zonewide)
{
    double B = pcg->latitude; //纬度
    double L = pcg->longitude; //经度//纬度度数

    double L0; //中央经线度数
    double N; //卯酉圈曲率半径 
    double q2;
    double x; //高斯平面纵坐标
    double y; //高斯平面横坐标
    double s; //赤道至纬度B的经线弧长
    double f; //参考椭球体扁率
    double e1; //椭球第一偏心率
    double a; //参考椭球体长半轴
    //double b;    //参考椭球体短半轴
    double a1, a2, a3, a4;
    double b1, b2, b3, b4;
    double c0, c1, c2, c3;

    const double IPI = 0.0174532925199433333333; //3.1415926535898/180.0

    int prjno = 0; //投影带号   
    // zonewide 投影带宽带, 3 或者是 6
    if (zonewide == 6)
    {
        prjno = (int) (L / zonewide) + 1;
        L0 = prjno * zonewide - 3;
    }
    else
    {
        prjno = (int) ((L - 1.5) / 3) + 1;
        L0 = prjno * 3;
    }

    /*
     * 北京 54
     * 长半轴a=6378245m
     * 短半轴b=6356863.0188m
     * 扁率α=1/298.3
     * 第一偏心率平方 =0.006693421622966
     * 第二偏心率平方 =0.006738525414683 
     * 
     * 西安80
     * 长半轴a=6378140±5(m)
     * 短半轴b=6356755.2882m
     * 扁率α=1/298.257
     * 第一偏心率平方 =0.00669438499959
     * 第二偏心率平方=0.00673950181947 
     * 
     * WGS84
     * 长半轴a=6378137± 2(m)
     * 短半轴b=6356752.3142m
     * 扁率α=1/298.257223563
     * 第一偏心率平方 =0.00669437999013
     * 第二偏心率平方 =0.00673949674223
     * 
     */

    //Datum 投影基准面类型:北京54基准面为54,西安80基准面为80,WGS84基准面为84
    if (Datum == 84)
    {
        a = 6378137;
        f = 1 / 298.257223563;
    }
    else if (Datum == 54)
    {
        a = 6378245;
        f = 1 / 298.3;
    }
    else if (Datum == 80)
    {
        a = 6378140;
        f = 1 / 298.257;
    }

    e1 = 2 * f - f*f; //(a*a-b*b)/(a*a) 椭球第一偏心率

    L0 = L0*IPI; // 转为弧度
    L = L*IPI; // 转为弧度
    B = B*IPI; // 转为弧度

    double sinB = sin(B); //sinB
    double cosB = cos(B); //cosB
    double tanB = tan(B); //tanB

    double l = L - L0; //L-L0l
    double m = l * cosB; //ltanB

    N = a / sqrt(1 - e1 * pow(sinB, 2));
    q2 = e1 / (1 - e1) * pow(cosB, 2);

    a1 = 1 + 3.0 / 4.0 * e1 + 45.0 / 64.0 * pow(e1, 2) + 175.0 / 256.0 * pow(e1, 3)
            + 11025.0 / 16384.0 * pow(e1, 4) + 43659.0 / 65536.0 * pow(e1, 5);

    a2 = 3.0 / 4.0 * e1 + 15.0 / 16.0 * pow(e1, 2) + 525.0 / 512.0 * pow(e1, 3)
            + 2205.0 / 2048.0 * pow(e1, 4) + 72765.0 / 65536.0 * pow(e1, 5);
    
    a3 = 15.0 / 64.0 * pow(e1, 2) + 105.0 / 256.0 * pow(e1, 3) + 2205.0 / 4096.0
            * pow(e1, 4) + 10359.0 / 16384.0 * pow(e1, 5);
    
    a4 = 35.0 / 512.0 * pow(e1, 3) + 315.0 / 2048.0 * pow(e1, 4) + 31185.0 / 13072.0
            * pow(e1, 5);
    b1 = a1 * a * (1 - e1);
    b2 = -1.0 / 2.0 * a2 * a * (1 - e1);
    b3 = 1.0 / 4.0 * a3 * a * (1 - e1);
    b4 = -1.0 / 6.0 * a4 * a * (1 - e1);
    c0 = b1;
    c1 = 2 * b2 + 4 * b3 + 6 * b4;
    c2 = -(8 * b3 + 32 * b4);
    c3 = 32 * b4;
    s = c0 * B + cosB * (c1 * sinB + c2 * pow(sinB, 3) + c3 * pow(sinB, 5));
    
    x = s + 0.5 * N * tanB * pow(m, 2) + 1.0 / 24.0 * (5 - pow(tanB, 2) + 9 * q2 + 4
            * pow(q2, 2)) * N * tanB * pow(m, 4) + 1.0 / 720.0 * (61 - 58 * pow(tanB, 6))
            * N * tanB * pow(m, 6);
    
    y = N * m + 1.0 / 6.0 * (1 - pow(tanB, 2) + q2) * N * pow(m, 3) + 1.0 / 120.0
            * (5 - 18 * tanB * tanB + pow(tanB, 4) - 14 * q2 - 58 * q2 * pow(tanB, 2)) * N * pow(m, 5);

    y = y + 1000000 * prjno + 500000;
    pcc->x = x;
    pcc->y = y - 38000000;
    pcc->z = 0;
}

double BLDistance(CRDGEODETIC *pcg1, CRDGEODETIC *pcg2, int Datum, int zonewide)
{
    CRDCARTESIAN pcc1, pcc2;
    BLTOXY(&pcc1, pcg1, Datum, zonewide);
    BLTOXY(&pcc2, pcg2, Datum, zonewide);

    double xdes = fabs(pcc1.x - pcc2.x);
    double ydes = fabs(pcc1.y - pcc2.y);
    double des = sqrt(xdes * xdes + ydes * ydes);

    return des;
}


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!