大地坐标BLH转平面坐标xyh(高斯投影坐标正算) Java版

技术背景

  做过位置数据处理的小伙伴基本上都会遇到坐标转换,而基于高斯投影原理的大地坐标转平面坐标就是其中一种坐标转换,坐标转换的目的就是方便后面数据的处理工作,大地坐标转高斯平面坐标常用的有两种,即3°带和6°带,具体采用哪种根据实际情况而定。

计算原理

  6°带带号n与相应的中央子午线L0经度的关系为:

image

  3°带带号n’与相应的中央子午线L0’经度的关系为:

image

  设参考椭球的长半轴为 a,第一偏心率为 e,并令:

image

  设中央子午线的经度为 L0,再记:

image

  则高斯投影正算公式为:

image

  其中:

image

  没学过测绘的同学对以上原理不是很理解,也很正常,大家可以查阅相关《大地测量学》书籍,具体武大版还是矿大版的,没什么区别。

具体实现

  具体实现平台依然是IBM的Eclipse软件,编程语言为Java,下面是以3°带为例,进行高斯投影坐标正算,具体内容请看代码

  1 package package1;
  2 
  3 public class BLH_xyh {
  4 
  5 	public static double a          =  6378137;
  6 	public static double e          =  Math.sqrt(0.0066943799013);
  7 	public static double scale_wide =  3;
  8 	public static double π 			=  3.14159265358979323846;
  9 
 10 	public static void main(String[] args) {
 11 		// TODO 自动生成的方法存根
 12 		Point3d xyh = the_coordinates_are_counting(36.0307523111,120.184664478,9.7065);
 13 		System.out.println(xyh.getX()+","+xyh.getY()+","+xyh.getZ());
 14 	}
 15 	public static Point3d the_coordinates_are_counting(double B,double L,double H){
 16 		double A_ = 1
 17 					+3*e*e/4
 18 					+45*e*e*e*e/64
 19 					+175*e*e*e*e*e*e/256
 20 					+11025*e*e*e*e*e*e*e*e/16384
 21 					+43659*e*e*e*e*e*e*e*e*e*e/65536;
 22 		double B_ =   3*e*e/4+15*e*e*e*e/16
 23 					+525*e*e*e*e*e*e/512
 24 					+2205*e*e*e*e*e*e*e*e/2048
 25 					+72765*e*e*e*e*e*e*e*e*e*e/65536;
 26 		double C_ =  15*e*e*e*e/64
 27 					+105*e*e*e*e*e*e/256
 28 					+2205*e*e*e*e*e*e*e*e/4096
 29 					+10395*e*e*e*e*e*e*e*e*e*e/16384;
 30 		double D_ =  35*e*e*e*e*e*e/512
 31 					+315*e*e*e*e*e*e*e*e/2048
 32 					+31185*e*e*e*e*e*e*e*e*e*e/13072;
 33 		/*
 34 		double E_ =  315*e*e*e*e*e*e*e*e/16384
 35 					+3465*e*e*e*e*e*e*e*e*e*e/65536;
 36 		double F_ =  693*e*e*e*e*e*e*e*e*e*e/13072;
 37 		*/
 38 
 39 		double α  =  A_*a*(1-e*e);
 40 		double β  = -B_*a*(1-e*e)/2;
 41 		double γ  =  C_*a*(1-e*e)/4;
 42 		double δ  = -D_*a*(1-e*e)/6;
 43 		/*
 44 		double ε  =  E_*a*(1-e*e)/8;
 45 		double ζ  = -F_*a*(1-e*e)/10;
 46 		*/
 47 
 48 		double C0 =  α;
 49 		double C1 =  2*β+4*γ+6*δ;
 50 		double C2 = -8*γ-32*δ;
 51 		double C3 =  32*δ;
 52 
 53 		double x,y,sign;
 54 		double scale_number = Math.floor(L/scale_wide);
 55 		if(L > (scale_number * scale_wide + scale_wide/2)){
 56 			scale_number =scale_number + 1;
 57 			sign = -1;
 58 		}else{
 59 			sign =  1;
 60 		}
 61 
 62 		double L0 =  scale_wide*scale_number;
 63 		double l  =  Math.abs(L-L0);
 64 			   B  =  B*π/180;
 65 			   l  =  l*π/180;
 66 		double t  =  Math.tan(B);
 67 		double m0 =  Math.cos(B)*l;
 68 		double η  =  Math.sqrt(e*e*Math.pow(Math.cos(B),2)/(1-e*e));
 69 		double N  =  a/Math.sqrt(1-e*e*Math.pow(Math.sin(B), 2));
 70 
 71 		double X0 =  C0*B+Math.cos(B)*(C1*Math.sin(B)+C2*Math.pow(Math.sin(B),3)+C3*Math.pow(Math.sin(B), 5));
 72 
 73 			   x  =  X0
 74 					   +N*t*m0*m0/2
 75 					   +N*t*m0*m0*m0*m0*(5-t*t+9*η*η+4*η*η*η*η)/24
 76 					   +N*t*m0*m0*m0*m0*m0*m0*(61-58*t*t+t*t*t*t)/720;
 77 			   y  =  N*m0+
 78 					 N*m0*m0*m0*(1-t*t+η*η)/6+
 79 					 N*m0*m0*m0*m0*m0*m0*(5-18*t*t+t*t*t*t+14*η*η-58*η*η*t*t)/120;
 80 
 81 			   y =   y*sign+500000;
 82 
 83 		double h =   H;
 84 
 85 		Point3d xyh = new Point3d(x,y,h);
 86 		return xyh;
 87 	}
 88 }

其中Point3d的定义如下:

  1 package package1;
  2 
  3 public class Point3d {
  4 	private double x;
  5 	private double y;
  6 	private double z;
  7 	public Point3d(double x,double y,double z){
  8 		this.x=x;
  9 		this.y=y;
 10 		this.z=z;
 11 	}
 12 	public double getX() {
 13 		return x;
 14 	}
 15 	public void setX(double x) {
 16 		this.x = x;
 17 	}
 18 	public double getY() {
 19 		return y;
 20 	}
 21 	public void setY(double y) {
 22 		this.y = y;
 23 	}
 24 	public double getZ() {
 25 		return z;
 26 	}
 27 	public void setZ(double z) {
 28 		this.z = z;
 29 	}
 30 }

测试数据为36.0307523111,120.184664478,9.7065,运行结果如下:

image

至此结束

致谢

  感谢山东科技大学北斗星光创客兴趣学习小组的王老师对于原理文档的整理以及郑** C++代码的技术分享!

 

参考文档

1、山东科技大学”北斗星光创客”兴趣学习小组GNSS技术文档

posted @ 2018-11-18 16:33  thyou  阅读(6336)  评论(0编辑  收藏  举报