天天看点

proj4测绘坐标系转换

proj4测绘坐标系转换

相同基准面之间投影坐标和地理坐标的转换

pj_transform

projPJ pj_merc,pj_latlong;
    double x,y;
    //定义墨卡托投影坐标系
    pj_merc=pj_init_plus("+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs");
    //定义地理坐标系
    pj_latlong = pj_init_plus("+proj=longlat +datum=WGS84 +no_defs");
        
    x = -9.866554;
    y = 7.454779;
    //经纬度(度转弧度)
    x *= DEG_TO_RAD;
    y *= DEG_TO_RAD;
	//地理坐标转投影坐标
    pj_transform(pj_latlong, pj_merc, 1, 1, &x, &y, NULL);
    cout.precision(12);
    cout << "(" << x << " , " << y << ")" << endl;
	//投影坐标转地理坐标
    pj_transform(pj_merc,pj_latlong,1,1,&x,&y,NULL);
    x*=RAD_TO_DEG;
    y*=RAD_TO_DEG;
    cout.precision(8);
    cout << "(" << x << " , " << y << ")" << endl;
           

相同基准下地理坐标和空间直角坐标系的转换(即大地坐标与地心坐标的转换)

pj_geocentric_to_geodetic

:地心坐标转大地坐标(XYZ->BLH)

pj_geodetic_to_geocentric

:大地坐标转地心坐标(BLH->XYZ)

WGS84基准下的转换

typedef struct { double u, v,w; } projUVW;
	
	double wgs84_a = 6378137.0;//长半轴
    double wgs84_f = 1.0/298.257223563;//扁率
    double wgs84_b = wgs84_a * (1 - wgs84_f);//短半轴
    double wgs84_e=(wgs84_a*wgs84_a-wgs84_b*wgs84_b)/(wgs84_a*wgs84_a);//第一偏心率的平方
    

    projUVW pt3[2] = {{116.5164884833, 39.7663036028,  23.220}, {116.987654321, 39.453, 18}};
    
    for (int i = 0; i < 2; i++)
    {
        cout << "第" << i << "个点的转换:\n";
        pt3[i].u *= DEG_TO_RAD;
        pt3[i].v *= DEG_TO_RAD;

        pj_geodetic_to_geocentric(wgs84_a, wgs84_e, 1, 1, &pt3[i].u, &pt3[i].v, &pt3[i].w);
        cout.setf(ios::fixed);
        cout.precision(4);
        cout.width(12);
        cout << "\t经纬度转换为空间坐标\n\t";
        cout << pt3[i].u << "\t" << pt3[i].v << "\t" << pt3[i].w << endl;

        pj_geocentric_to_geodetic(wgs84_a, wgs84_e, 1, 1, &pt3[i].u, &pt3[i].v, &pt3[i].w);
        cout.setf(ios::fixed);
        cout.precision(9);
        cout.width(12);
        cout << "\t空间坐标转换为经纬度\n\t";
        cout << pt3[i].u * RAD_TO_DEG << "\t" << pt3[i].v * RAD_TO_DEG << "\t" ;
        cout.precision(4);
        cout << pt3[i].w << endl;
    }
           

等价于:

typedef struct { double u, v,w; } projUVW;
	
 	// 地心坐标系
    const char* geoccs="+proj=geocent +datum=WGS84";
    // 大地坐标系
    const char* latlon="+proj=latlong +datum=WGS84";
    projPJ pjGeoccs, pjLatlon;
    //初始化当前投影对象
    pjGeoccs= pj_init_plus(geoccs);
    pjLatlon= pj_init_plus(latlon);
    
    projUVW pt3[2] = {{116.5164884833, 39.7663036028,  23.220}, {116.987654321, 39.453, 18}};
    
    for (int i = 0; i < 2; i++)
    {
        cout << "第" << i << "个点的转换:\n";
        pt3[i].u *= DEG_TO_RAD;
        pt3[i].v *= DEG_TO_RAD;

         pj_transform(pjLatlon,pjGeoccs, 1, 1, &pt3[i].u, &pt3[i].v, &pt3[i].w);
        cout.setf(ios::fixed);
        cout.precision(4);
        cout.width(12);
        cout << "\t经纬度转换为空间坐标\n\t";
        cout << pt3[i].u << "\t" << pt3[i].v << "\t" << pt3[i].w << endl;

        pj_transform(pjGeoccs, pjLatlon, 1, 1, &pt3[i].u, &pt3[i].v, &pt3[i].w);
        cout.setf(ios::fixed);
        cout.precision(9);
        cout.width(12);
        cout << "\t空间坐标转换为经纬度\n\t";
        cout << pt3[i].u * RAD_TO_DEG << "\t" << pt3[i].v * RAD_TO_DEG << "\t" ;
        cout.precision(4);
        cout << pt3[i].w << endl;
    }
           

不同基准下空间直角坐标系下的转换

pj_datum_transform

三参数

  • GRS80下的地理坐标转GRS80下的空间直角坐标系
  • 三参数将GRS80空间直角坐标系转WGS84空间直角坐标系
  • WGS84空间直角坐标系转WGS84地理坐标系
//grs椭球参数
    double grs80_a=6378137.0;WGS
    double grs80_f=1.0/298.257222101;
    double grs80_b=grs80_a*(1-grs80_f);
    double grs80_e=(grs80_a*grs80_a-grs80_b*grs80_b)/(grs80_a*grs80_a) ;
    //BLH
    x=20;
    y=35;
    z=1000;
    
    x*=DEG_TO_RAD;
    y*=DEG_TO_RAD;
    
    pj_geodetic_to_geocentric(grs80_a, grs80_e, 1, 1, &x, &y, &z);
    //三参数 xyz轴的偏移
    x-=199.87;
    y+=74.79;
    z+=246.62;
    
    //wgs84椭球参数
    double wgs84_a = 6378137.0;
    double wgs84_f = 1.0/298.257223563;
    double wgs84_b = wgs84_a * (1 - wgs84_f);
    double wgs84_e=(wgs84_a*wgs84_a-wgs84_b*wgs84_b)/(wgs84_a*wgs84_a);
    pj_geocentric_to_geodetic(wgs84_a,wgs84_e,1,1,&x,&y,&z);
    x*=RAD_TO_DEG;
    y*=RAD_TO_DEG;
    cout.precision(12);
    cout << "(" << x << " , " << y << ")" << endl;
           

等价于:

+towgs84=-199.87,74.79,246.62

projPJ pj_grs80,pj_wgs84;

    pj_grs80=pj_init_plus("+proj=latlong +ellps=GRS80 +towgs84=-199.87,74.79,246.62");
    pj_wgs84 = pj_init_plus("+proj=latlong +datum=WGS84");

    double x,y,z;
    x=20;
    y=35;
    z=1000;
    x*=DEG_TO_RAD;
    y*=DEG_TO_RAD;
    pj_transform(pj_grs80,pj_wgs84,1,1,&x,&y,&z);
    x*=RAD_TO_DEG;
    y*=RAD_TO_DEG;
    cout.precision(12);
    cout << "(" << x << " , " << y << ")" << endl;
           

七参数

  • WGS72下的地理坐标转WGS72下的空间直角坐标系
  • 七参数将WGS72空间直角坐标系转WGS84空间直角坐标系
  • WGS84空间直角坐标系转WGS84地理坐标系
#define PI         3.14159265358979323e0
#define SEC_TO_RAD PI/180/3600

//WGS72 椭球参数
    double wgs72_f=1.0/298.26;
    double wgs72_b=wgs72_a*(1-wgs72_f);
    double wgs72_e=(wgs72_a*wgs72_a-wgs72_b*wgs72_b)/(wgs72_a*wgs72_a) ;//第一偏心率的平方
    x=4;
    y=55;
    z=1000;
    x*=DEG_TO_RAD;
    y*=DEG_TO_RAD;
    pj_geodetic_to_geocentric(wgs72_a, wgs72_e, 1, 1, &x, &y, &z);
	// 七参数
    double Dx_BF =0;
    double Dy_BF =0;
    double Dz_BF =4.5;
    double Rx_BF =0;
    double Ry_BF =0;
    double Rz_BF =0.554*SEC_TO_RAD;//ms
    double M_BF  =1.0+0.219/1000000.0;//尺度变化值(实际缩放值=1.0+缩放因子/1000000)

    double x_out = M_BF*(       x - Rz_BF*y + Ry_BF*z) + Dx_BF;
    double y_out = M_BF*( Rz_BF*x +       y - Rx_BF*z) + Dy_BF;
    double z_out = M_BF*(-Ry_BF*x + Rx_BF*y +       z) + Dz_BF;

     //wgs84椭球参数
    double wgs84_a = 6378137.0;d
    double wgs84_f = 1.0/298.257223563;
    double wgs84_b = wgs84_a * (1 - wgs84_f);
    double wgs84_e=(wgs84_a*wgs84_a-wgs84_b*wgs84_b)/(wgs84_a*wgs84_a);
    pj_geocentric_to_geodetic(wgs84_a,wgs84_e,1,1,&x_out,&y_out,&z_out);
    x_out*=RAD_TO_DEG;
    y_out*=RAD_TO_DEG;
    cout.precision(12);
    cout << "(" << x_out << " , " << y_out << ")" << endl;
           

等价于:

+towgs84=0,0,4.5,0,0,0.554,0.219

projPJ pj_wgs72,pj_wgs84;
    pj_wgs72=pj_init_plus("+proj=latlong +ellps=WGS72 +towgs84=0,0,4.5,0,0,0.554,0.219");
    pj_wgs84 = pj_init_plus("+proj=latlong +datum=WGS84");
    x=4;
    y=55;
    z=1000;
    x*=DEG_TO_RAD;
    y*=DEG_TO_RAD;
    pj_transform(pj_wgs72,pj_wgs84,1,1,&x,&y,&z);
           

亦等价于:

pj_datum_transform

projPJ pj_wgs72,pj_wgs84;
    pj_wgs72=pj_init_plus("+proj=latlong +ellps=WGS72 +towgs84=0,0,4.5,0,0,0.554,0.219");
    pj_wgs84 = pj_init_plus("+proj=latlong +datum=WGS84");
    x=4;
    y=55;
    z=1000;
    x*=DEG_TO_RAD;
    y*=DEG_TO_RAD;
    pj_datum_transform(pj_wgs72,pj_wgs84,1,1,&x,&y,&z);
           

总结

proj4测绘坐标系转换

坐标系转换的流程大抵如此:

pj_transform

->

pj_geodetic_to_geocentric

->

pj_datum_transform

->

pj_geocentric_to_geodetic

->

pj_transform

如下图所示,本文已经包含了椭球的七参数和三参数变换(不同基准的变换)和投影变换。

proj4测绘坐标系转换

继续阅读