80、54、84坐标系七参数转换算法

Wesley13
• 阅读 860

一、为什么要进行坐标转换

   我们所在地球是一个不规则的椭球,地表凹凸不平,地底密度不均,因此很难用一个简单模型来概括。国际上根据建模坐标系的原点不同分为参心坐标系和地心坐标系,其中参心坐标系是指参考椭球的几何中心坐标基准,地心,通常分为:参心空间直角坐标系(以x,y,z为其坐标元素)和参心大地坐标系(以B,L,H为其坐标元素),比如我国的北京54坐标系和西安80坐标系;坐标系是用地球质心作为原点,通常分为地心空间直角坐标系(以x,y,z为其坐标元素)和地心大地坐标系(以B,L,H为其坐标元素),比如GPS采用的WGS84坐标系。

   除了原点以外,任何一个椭球的模型还会有长轴、短轴和扁率三个参数,我整理了下54,80,84三个坐标的椭球模型如下表:

坐标系

长轴(单位:米)

短轴(单位:米)

扁率

北京54坐标系

6378245

6356863

1/298.3

西安80坐标系

6378140

6356755

1/298.25722101

WGS84坐标系

6378137

6356752.314

1/298.25722356

        所以,我们可见这三个坐标系是原点不一,椭球模型不一的坐标系,就如同三个达芬奇的鸡蛋,虽然都是椭球状,但是形状还是不一样的。所以如果直接做两个坐标系之间的转换是明显不行的。

   那么有没有办法进行转换呢?答案是肯定的。在数学上,任何两个空间直角坐标系都可以通过七个参数,即XYZ三个轴的平移,绕XYZ三个轴的旋转角以及两个坐标系的大小比例因子的转换后重叠在一起。因此,我们在做着三个坐标系的转换基本思路就是在空间直角坐标系里,通过七参数的偏移校正,实现坐标系之间参数的转换。

 二、怎样坐标转换

        好了,那我们如何转换呢。首先,我再区分一下地理上的空间直角坐标系、大地坐标系和平面坐标系的区别。

   空间直角坐标系和数学的空间直角坐标系基本相同,是以一个点为原点,三个互相垂直的直线作为三个轴延伸出来一个坐标系,通常表示为(x,y,z);

   大地坐标系是其地面上一点的大地经度L为大地起始子午面与该点所在的子午面所构成的二面角,由起始子午面起算,向东为正,称为东经(0180),向西为负,称为西经(0180);大地纬度B是经过该点作椭球面的法线与赤道面的夹角,由赤道面起算,向北为正,称为北纬(090),向南为负,称为南纬(090);大地高H是地面点沿椭球的法线到椭球面的距离,通常表示为(B,L,H);

   平面坐标系主要是我国测绘领域里使用的坐标系,属于参心大地坐标系,有一个坐标原点(54位原苏联的普尔科沃,80位我们陕西省泾阳县永乐镇),Z轴平行于地球质心指向地极原点方向,大地起始子午面平行于格林尼治平均天文台子午面,X轴在大地起始子午面内与Z轴垂直指向经度0方向,Y轴与Z、X轴成右手坐标系。因为大地高程以1956年青岛验潮站求出的黄海平均水面为基准,一般情况默认为0,所以通常表示为(X,Y)。

下面我以一个例子说明下如何进行WGS84坐标系转西安80坐标系

   WGS84坐标系是大地坐标系,首先要转换到空间直角坐标系,公式如图所示:

80、54、84坐标系七参数转换算法

  其中a,b是WGS84椭球长短轴。代码为:

  1. //第一步转换,大地坐标系换换成空间直角坐标系

  2. private void BLHtoXYZ(double B, double L, double H, double aAxis, double bAxis) {

  3. double dblD2R = Math.PI / 180;

  4. double e1 = Math.sqrt(Math.pow(aAxis, 2) - Math.pow(bAxis, 2)) / aAxis;

  5. double N = aAxis / Math.sqrt(1.0 - Math.pow(e1, 2) * Math.pow(Math.sin(B * dblD2R), 2));

  6. targetX = (N + H) * Math.cos(B * dblD2R) * Math.cos(L * dblD2R);

  7. targetY = (N + H) * Math.cos(B * dblD2R) * Math.sin(L * dblD2R);

  8. targetZ = (N * (1.0 - Math.pow(e1, 2)) + H) * Math.sin(B * dblD2R);

  9. }

      第二步是进行空间直角坐标系里七参数转换,公式如图:

80、54、84坐标系七参数转换算法

      其中△X,△Y,△Z是坐标平移量,R(ω)是旋转矩阵,(1+m)是比例因子,代码如下:

  1. //第二步转换,空间直角坐标系里七参数转换

  2. Ex = transParaSeven.m_dbXRotate / 180 * Math.PI;

  3. Ey = transParaSeven.m_dbYRotate / 180 * Math.PI;

  4. Ez = transParaSeven.m_dbZRotate / 180 * Math.PI;

  5. double newX = transParaSeven.m_dbXOffset + transParaSeven.m_dbScale * targetX + targetY * Ez - targetZ * Ey + targetX;

  6. double newY = transParaSeven.m_dbYOffset + transParaSeven.m_dbScale * targetY - targetX * Ez + targetZ * Ex + targetY;

  7. double newZ = transParaSeven.m_dbZOffset + transParaSeven.m_dbScale * targetZ + targetX * Ey - targetY * Ex + targetZ;

      注意单位为弧度。

      第三步是空间直角坐标系转大地坐标系,转后的大地坐标系为80的大地坐标系,如图:

      80、54、84坐标系七参数转换算法

     其中a,b是西安80椭球长短轴,代码如下:

  1. //第三步转换,空间直接坐标系转换为大地坐标系

  2. private void XYZtoBLH(double X, double Y, double Z, double aAxis, double bAxis) {

  3. double e1 = (Math.pow(aAxis, 2) - Math.pow(bAxis, 2)) / Math.pow(aAxis, 2);

  4. double e2 = (Math.pow(aAxis, 2) - Math.pow(bAxis, 2)) / Math.pow(bAxis, 2);

  5. double S = Math.sqrt(Math.pow(X, 2) + Math.pow(Y, 2));

  6. double cosL = X / S;

  7. double B = 0;

  8. double L = 0;

  9. L = Math.acos(cosL);

  10. L = Math.abs(L);

  11. double tanB = Z / S;

  12. B = Math.atan(tanB);

  13. double c = aAxis * aAxis / bAxis;

  14. double preB0 = 0.0;

  15. double ll = 0.0;

  16. double N = 0.0;

  17. //迭代计算纬度

  18. do {

  19. preB0 = B;

  20. ll = Math.pow(Math.cos(B), 2) * e2;

  21. N = c / Math.sqrt(1 + ll);

  22. tanB = (Z + N * e1 * Math.sin(B)) / S;

  23. B = Math.atan(tanB);

  24. }

  25. while (Math.abs(preB0 - B) >= 0.0000000001);

  26. ll = Math.pow(Math.cos(B), 2) * e2;

  27. N = c / Math.sqrt(1 + ll);

  28. targetZ = Z / Math.sin(B) - N * (1 - e1);

  29. targetB = B * 180 / Math.PI;

  30. targetL = L * 180 / Math.PI;

  31. }

    第四步是进行高斯变换,将大地坐标转为平面坐标,公式如图:

80、54、84坐标系七参数转换算法

    有点复杂,也一时说不清,具体可以查查高斯变换,这个还是很多的。代码如下:

  1. //第四部转换,高斯变换,大地坐标系转平面坐标系,84转80

  2. private void gaussBLtoXY(double mX,double mY){

  3. double m_aAxis = Axis_WGS84_a; //参考椭球长半轴

  4. double m_bAxis = Axis_WGS84_b; //参考椭球短半轴

  5. double m_dbMidLongitude = transParaSeven.daihao*3;//中央子午线经度 济南117 威海123 巴州 87

  6. double m_xOffset = 500000;

  7. double m_yOffset = 0.0;

  8. try{

  9. //角度到弧度的系数

  10. double dblD2R = Math.PI / 180;

  11. //代表e的平方

  12. double e1 = (Math.pow(m_aAxis, 2) - Math.pow(m_bAxis, 2)) / Math.pow(m_aAxis, 2);

  13. //代表e'的平方

  14. double e2 = (Math.pow(m_aAxis, 2) - Math.pow(m_bAxis, 2)) / Math.pow(m_bAxis, 2);

  15. //a0

  16. double a0 = m_aAxis * (1 - e1) * (1.0 + (3.0 / 4.0) * e1 + (45.0 / 64.0) * Math.pow(e1, 2) + (175.0 / 256.0) * Math.pow(e1, 3) + (11025.0 / 16384.0) * Math.pow(e1, 4));

  17. //a2

  18. double a2 = -0.5 * m_aAxis * (1 - e1) * (3.0 / 4 * e1 + 60.0 / 64 * Math.pow(e1, 2) + 525.0 / 512.0 * Math.pow(e1, 3) + 17640.0 / 16384.0 * Math.pow(e1, 4));

  19. //a4

  20. double a4 = 0.25 * m_aAxis * (1 - e1) * (15.0 / 64 * Math.pow(e1, 2) + 210.0 / 512.0 * Math.pow(e1, 3) + 8820.0 / 16384.0 * Math.pow(e1, 4));

  21. //a6

  22. double a6 = (-1.0 / 6.0) * m_aAxis * (1 - e1) * (35.0 / 512.0 * Math.pow(e1, 3) + 2520.0 / 16384.0 * Math.pow(e1, 4));

  23. //a8

  24. double a8 = 0.125 * m_aAxis * (1 - e1) * (315.0 / 16384.0 * Math.pow(e1, 4));

  25. ////纬度转换为弧度表示

  26. //B

  27. double B = mX * dblD2R;

  28. //l

  29. double l = (mY - m_dbMidLongitude) * dblD2R;

  30. ////X

  31. double X = a0 * B + a2 * Math.sin(2.0 * B) + a4 * Math.sin(4.0 * B) + a6 * Math.sin(6.0 * B) + a8 * Math.sin(8.0 * B);

  32. //

  33. double ll = Math.pow(Math.cos(B), 2) * e2;

  34. double c = m_aAxis * m_aAxis / m_bAxis;

  35. //N

  36. double N = c / Math.sqrt(1 + ll);

  37. //t

  38. double t = Math.tan(B);

  39. double p = Math.cos(B) * l;

  40. double dby = X + N * t * (1 + ((5.0 - t * t + (9.0 + 4.0 * ll) * ll) + ((61.0 + (t * t - 58.0) * t * t + (9.0 - 11.0 * t * t) * 30.0 * ll) + (1385.0 + (-31111.0 + (543 - t * t) * t * t) * t * t) * p * p / 56.0) * p * p / 30.0) * p * p / 12.0) * p * p / 2.0;

  41. double dbx;

  42. dbx = N * (1.0 + ((1.0 - t * t + ll) + ((5.0 + t * t * (t * t - 18.0 - 58.0 * ll) + 14 * ll) + (61.0 + (-479.0 + (179.0 - t * t) * t * t) * t * t) * p * p / 42.0) * p * p / 20.0) * p * p / 6.0) * p;

  43. mTargetX = dbx + m_xOffset;

  44. mTargetY = dby + m_yOffset;

  45. }

  46. catch (Exception ex) {

  47. }

  48. }

    OK,也就搞定了。其他的转换也就和这个差不多了,只是步骤相反而已

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Stella981 Stella981
3年前
Openlayers中Feature与WKT之间的转换,Feature坐标系的转换
1、Feature转WKT且带坐标系的转换    varstrwktnewol.format.WKT().writeFeature(feature,{               dataProjection:targetcrs,//目标坐标系               featureProjection:c
Stella981 Stella981
3年前
Python内置海龟(turtle)库绘图命令详解(一)
    本文主要介绍了用Python内置turtle库绘制图形的一些主要命令,turtle库是Python语言中一个很流行的绘制图像的函数库,原理是利用一个小海龟,坐标系原点(0,0)位置开始,根据一组函数指令的控制,在平面坐标系中移动,利用它爬行过的路径即可绘制图形。下面介绍turtle绘图的一些基础知识。!(https://oscimg
Easter79 Easter79
3年前
SVG的坐标系统
在开始学习如何绘图之前,我们先来看一下SVG的坐标系统。与很多计算机绘图所使用的坐标系统一样,SVG也使用了网格坐标系统。这种坐标和我们以前在数学中学过的坐标有些不同。数学中的坐标是由x轴(水平横向延伸)和y轴(垂直纵向延伸)交织组成,交点被称为坐标原点(0,0)。原点沿x轴向右为正值,反之为负值,沿y轴向上
Stella981 Stella981
3年前
SVG 坐标系统
在开始学习如何绘图之前,我们先来看一下SVG的坐标系统。与很多计算机绘图所使用的坐标系统一样,SVG也使用了网格坐标系统。这种坐标和我们以前在数学中学过的坐标有些不同。数学中的坐标是由x轴(水平横向延伸)和y轴(垂直纵向延伸)交织组成,交点被称为坐标原点(0,0)。原点沿x轴向右为正值,反之为负值,沿y轴向上
Stella981 Stella981
3年前
OpenGL NDC 左手还是右手?
之前看到一篇文章说默认情况下OpenGLNDC是基于左手坐标系。我在我之前的博文(https://my.oschina.net/iirecord/blog/824029)中也提到过。之后我在想为什么OpenGLNDC是基于左手坐标系?真的是基于左手坐标系吗?所以这篇博客就是来找到答案。再谈OpenGL坐标变换(CoordinateT
Easter79 Easter79
3年前
SVG 坐标系统
在开始学习如何绘图之前,我们先来看一下SVG的坐标系统。与很多计算机绘图所使用的坐标系统一样,SVG也使用了网格坐标系统。这种坐标和我们以前在数学中学过的坐标有些不同。数学中的坐标是由x轴(水平横向延伸)和y轴(垂直纵向延伸)交织组成,交点被称为坐标原点(0,0)。原点沿x轴向右为正值,反之为负值,沿y轴向上
Stella981 Stella981
3年前
SVG的坐标系统
在开始学习如何绘图之前,我们先来看一下SVG的坐标系统。与很多计算机绘图所使用的坐标系统一样,SVG也使用了网格坐标系统。这种坐标和我们以前在数学中学过的坐标有些不同。数学中的坐标是由x轴(水平横向延伸)和y轴(垂直纵向延伸)交织组成,交点被称为坐标原点(0,0)。原点沿x轴向右为正值,反之为负值,沿y轴向上
Stella981 Stella981
3年前
Canvas入门07
预备知识直线的斜率一条直线与某平面直角坐标系x轴正半轴方向的夹角的正切值即该直线相对于该坐标系的斜率。对于一条直线ykxb,k就是直线的斜率。斜率的计算!(https://oscimg.oschina.net/oscnet/2217f1d7f737fe5ac60f3f2ff339a6fb328
铁扇公主 铁扇公主
12个月前
GPS虚拟定位软件:Aiseesoft AnyCoord免激活最新版
AIseesoftAnyCoordmac版软件介绍支持多种坐标系统:AIseesoftAnyCoord可以将经纬度、UTM坐标、高斯克吕格投影等不同标准下的坐标进行转换。批量转换:用户可以将多个坐标文件一次性导入并进行转换,提高了工作效率。界面简洁:AIs