经纬度BL换算到高斯平面直角坐标XY(高斯投影正算)的源码及算法

本文提供了一种使用VB编写的GPS坐标从经纬度转换到高斯平面直角坐标的算法及其实现代码。该方法适用于GIS应用中快速准确地进行坐标转换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、
经纬度BL换算到高斯平面直角坐标XY(高斯投影正算)的源码及算法

在   gis   的帖子 "用excel完成gps坐标转换的简易方法   "   基础上,
我给出对应的vb程序段,我在   evb   开发的gps定位功能中,用它实现坐标换算(具体的参数请参考gis   的帖子)。
感觉速度比较快,效果比较好。所以帖上来,希望与名位交流:
=====================================
'经纬度bl换算到高斯平面直角坐标xy(高斯投影正算)

 

private   function   bl2xy(byref   a2   as   double,   byref   f2   as   double,   byref   e2   as   double,   _ 
byref   s2   as   double,   byref   t2   as   double)   as   boolean 
'a2   输入中央子午线,以度.分形式输入,如115度30分则输入115.30;   起算数据l0 
'
f2   以度小数形式输入经度值,   l 
'
e2   以度小数形式输入纬度值,b 
'
s2   计算结果,横坐标y 
'
t2   计算结果,纵坐标x 
'
投影带号计算 n=[l/6]+1   如:测得经度103.xxxx,故n=[103.x/6]+1=17+1=18 
'
中央经线经度 l0   =   n*6-3   =   [l/6]*6+3 

dim   b2   as   double 
'dim   g2   as   double 
dim   h2   as   double 
dim   i2   as   double 
dim   j2   as   double 
dim   k2   as   double 
dim   l2   as   double 
dim   m2   as   double 
dim   n2   as   double 
dim   o2   as   double 
dim   p2   as   double 
dim   q2   as   double 
dim   r2   as   double 

b2   
=   int(a2)   +   (int(a2   *   100)   -   int(a2)   *   100)   /   60   +   (a2   *   10000   -   int(a2   *   100)   *   100)   /   3600 
'把l0化成度(a2) 
'
g2   =   f2   -   b2   '   l   -l0 
'
h2   =   g2   /   57.2957795130823   '化作弧度 
h2   =   (f2   -   b2)   /   57.2957795130823   '将经差的单位化为弧度 
i2   =   tan(e2   /   57.2957795130823)   'tan   (b) 
j2   =   cos(e2   /   57.2957795130823)   '   cos   (b) 
k2   =   0.006738525415   *   j2   *   j2 
l2   
=   i2   *   i2 
m2   
=   1   +   k2 
n2   
=   6399698.9018   /   sqr(m2) 
o2   
=   h2   *   h2   *   j2   *   j2 
p2   
=   i2   *   j2 
q2   
=   p2   *   p2 
r2   
=   (32005.78006   +   q2   *   (133.92133   +   q2   *   0.7031)) 
s2   
=   ((((l2   -   18)   *   l2   -   (58   *   l2   -   14)   *   k2   +   5)   *   o2   /   20   +   m2   -   l2)   *   o2   /   6   +   1)   *   n2   *   (h2   *   j2) 
s2   
=   s2   +   18500000   '在计算的基础上加上了“带号”(18)和“东移”(500km) 
'
计算结果,横坐标y 
t2   =   6367558.49686   *   e2   /   57.29577951308   -   p2   *   j2   *   r2   +   ((((l2   -   58)   *   l2   +   61)   *   _ 
o2   
/   30   +   (4   *   k2   +   5)   *   m2   -   l2)   *   o2   /   12   +   1)   *   n2   *   i2   *   o2   /   2 
'计算结果,纵坐标x 
'
msgbox   "pts2= "   &   s2   &   "   pt   t2= "   &   t2 

bl2xy   
=   true 
end   function

 二、

 

//   GaussBL2xy.cpp   :   Defines   the   entry   point   for   the   console   application. 
// 

#include   
"stdafx.h " 
#include   
"math.h " 
#include   
"CoorTrans.h " 
#include   
<iostream> 

using   namespace   std; 

void   main(int   argc,   char*   argv[]) 

  
double   MyL0   =   108;   //中央子午线 
  double   MyB   =   33.44556666;   //33   du   44   fen   55.6666   miao 
  double   MyL   =   109.22334444;   //3度带,109   d   22   m   33.4444   s 
  
  PrjPoint_Krasovsky   MyPrj; 
  MyPrj.SetL0(MyL0); 
  MyPrj.SetBL(MyB,   MyL); 
  
double   OutMyX;                       //结果应该大致是:3736714.783,   627497.303 
  double   OutMyY; 
  OutMyX   
=   MyPrj.x;           //正算结果:   北坐标x 
  OutMyY   =   MyPrj.y;           //结果:东坐标y 
  
  
//////////////////反算///////////////////////////////////////
  double   InputMyX   =   3736714.783;     //如果是独立计算,应该给出中央子午线L0 
  double   InputMyY   =   627497.303
  MyPrj.Setxy(InputMyX,   InputMyY); 
  MyPrj.GetBL(
&MyPrj.B,   &MyPrj.L);   //把计算出的BL的弧度值换算为dms形式 
  double   OutputMyB; 
  
double   OutputMyL; 
  OutputMyB   
=   MyPrj.B;     //反算结果:B 
  OutputMyL   =   MyPrj.L;     //反算结果:L 

  
//分析表明,此程序的结果和Coord4.2的转换结果是一样的,只差到毫米级 
        
//原程序有几个问题,1.Pi的值不对。2.SetBL中多了两行错误代码 



double   Dms2Rad(double   Dms) 

  
double   Degree,   Miniute; 
  
double   Second; 
  
int   Sign; 
  
double   Rad; 
  
if(Dms   > =   0
    Sign   
=   1
  
else 
    Sign   
=   -1
  Dms   
=   fabs(Dms); 
  Degree   
=   floor(Dms); 
  Miniute   
=   floor(fmod(Dms   *   100.0,   100.0)); 
  Second   
=   fmod(Dms   *   10000.0,   100.0); 
  Rad   
=   Sign   *   (Degree   +   Miniute   /   60.0   +   Second   /   3600.0)   *   PI   /   180.0
  
return   Rad; 

double   Rad2Dms(double   Rad) 

  
double   Degree,   Miniute; 
  
double   Second; 
  
int   Sign; 
  
double   Dms; 
  
if(Rad   > =   0
    Sign   
=   1
  
else 
    Sign   
=   -1
  Rad   
=   fabs(Rad   *   180.0   /   PI); 
  Degree   
=   floor(Rad); 
  Miniute   
=   floor(fmod(Rad   *   60.0,   60.0)); 
  Second   
=   fmod(Rad   *   3600.0,   60.0); 
  Dms   
=   Sign   *   (Degree   +   Miniute   /   100.0   +   Second   /   10000.0); 
  
return   Dms; 

/////////////////////////////////////////////////// 
//   Definition   of   PrjPoint 
/////////////////////////////////////////////////// 
bool   PrjPoint::BL2xy() 

  
double   X,   N,   t,   t2,   m,   m2,   ng2; 
  
double   sinB,   cosB; 
  X   
=   A1   *   B   *   180.0   /   PI   +   A2   *   sin(2   *   B)   +   A3   *   sin(4   *   B)   +   A4   *   sin(6   *   B); 
  sinB   
=   sin(B); 
  cosB   
=   cos(B); 
  t   
=   tan(B); 
  t2   
=   t   *   t; 
  N   
=   a   /   sqrt(1   -   e2   *   sinB   *   sinB); 
  m   
=   cosB   *   (L   -   L0); 
  m2   
=   m   *   m; 
  ng2   
=   cosB   *   cosB   *   e2   /   (1   -   e2); 
  
//x,y的计算公式见孔祥元等主编武汉大学出版社2002年出版的《控制测量学》的第72页 
  
//书的的括号有问题,   (   和   [   应该交换 
  x   =   X   +   N   *   t   *   ((0.5   +   ((5   -   t2   +   9   *   ng2   +   4   *   ng2   *   ng2)   /   24.0   +   (61   -     
    
58   *   t2   +   t2   *   t2)   *   m2   /   720.0)   *   m2)   *   m2); 
  y   
=   N   *   m   *   (   1   +   m2   *   (   (1   -   t2   +   ng2)   /   6.0   +   m2   *   (   5   -   18   *   t2   +   t2   *   t2 
    
+   14   *   ng2   -   58   *   ng2   *   t2   )   /   120.0)); 
  y   
+=   500000
    
return   true

bool   PrjPoint::xy2BL() 

  
double   sinB,   cosB,   t,   t2,   N   ,ng2,   V,   yN; 
  
double   preB0,   B0; 
  
double   eta; 
  y   
-=   500000
  B0   
=   x   /   A1; 
  
do 
  { 
    preB0   
=   B0; 
    B0   
=   B0   *   PI   /   180.0
    B0   
=   (x   -   (A2   *   sin(2   *   B0)   +   A3   *   sin(4   *   B0)   +   A4   *   sin(6   *   B0)))   /   A1; 
    eta   
=   fabs(B0   -   preB0); 
  }
while(eta   >   0.000000001); 
  B0   
=   B0   *   PI   /   180.0
  B   
=   Rad2Dms(B0); 
  sinB   
=   sin(B0); 
  cosB   
=   cos(B0); 
  t   
=   tan(B0); 
  t2   
=   t   *   t; 
  N   
=   a   /   sqrt(1   -   e2   *   sinB   *   sinB); 
  ng2   
=   cosB   *   cosB   *   e2   /   (1   -   e2); 
  V   
=   sqrt(1   +   ng2); 
  yN   
=   y   /   N; 
B   
=   B0   -   (yN   *   yN   -   (5   +   3   *   t2   +   ng2   -   9   *   ng2   *   t2)   *   yN   *   yN   *   yN   *   yN   / 
    
12.0   +   (61   +   90   *   t2   +   45   *   t2   *   t2)   *   yN   *   yN   *   yN   *   yN   *   yN   *   yN   /   360.0
    
*   V   *   V   *   t   /   2
  L   
=   L0   +   (yN   -   (1   +   2   *   t2   +   ng2)   *   yN   *   yN   *   yN   /   6.0   +   (5   +   28   *   t2   +   24 
    
*   t2   *   t2   +   6   *   ng2   +   8   *   ng2   *   t2)   *   yN   *   yN   *   yN   *   yN   *   yN   /   120.0)   /   cosB; 
    
return   true

bool   PrjPoint::SetL0(double   dL0) 

  L0   
=   Dms2Rad(dL0); 
    
return   true

bool   PrjPoint::SetBL(double   dB,   double   dL) 

  B   
=   Dms2Rad(dB); 
  L   
=   Dms2Rad(dL); 
        
//B   =   dB;         //我靠,I   wana   say   fuck 
  
//L   =   dL;   //del   it   ! 
  BL2xy(); 
    
return   true

bool   PrjPoint::GetBL(double   *dB,   double   *dL) 

  
*dB   =   Rad2Dms(B); 
  
*dL   =   Rad2Dms(L); 
  
return   true

bool   PrjPoint::Setxy(double   dx,   double   dy) 

  x   
=   dx; 
  y   
=   dy; 
  xy2BL(); 
  
return   true

bool   PrjPoint::Getxy(double   *dx,   double   *dy) 

  
*dx   =   x; 
  
*dy   =   y; 
    
return   true

/////////////////////////////////////////////////// 
//   Definition   of   PrjPoint_IUGG1975 
/////////////////////////////////////////////////// 
PrjPoint_IUGG1975::PrjPoint_IUGG1975()   //在类外定义构造成员函数,要加上类名和域限定符   :: 

  a   
=   6378140
  f   
=   298.257
  e2   
=   1   -   ((f   -   1)   /   f)   *   ((f   -   1)   /   f); 
  e12   
=   (f   /   (f   -   1))   *   (f   /   (f   -   1))   -   1
  A1   
=   111133.0047;     //这几个A是什么意思? 
  A2   =   -16038.5282
  A3   
=   16.8326
  A4   
=   -0.0220

PrjPoint_IUGG1975::
~PrjPoint_IUGG1975()       //析构函数,释放构造函数占用的内存 


/////////////////////////////////////////////////// 
//   Definition   of   PrjPoint_Krasovsky 
/////////////////////////////////////////////////// 
PrjPoint_Krasovsky::PrjPoint_Krasovsky() 

  a   
=   6378245
  f   
=   298.3
  e2   
=   1   -   ((f   -   1)   /   f)   *   ((f   -   1)   /   f); 
  e12   
=   (f   /   (f   -   1))   *   (f   /   (f   -   1))   -   1
  A1   
=   111134.8611
  A2   
=   -16036.4803
  A3   
=   16.8281
  A4   
=   -0.0220

PrjPoint_Krasovsky::
~PrjPoint_Krasovsky() 



  

//CoorTrans.h   文件 
#ifndef   _COORTRANS_H_INCLUDED 
#define   _COORTRANS_H_INCLUDED 

#include   
"stdafx.h " 
#include   
"math.h " 

const   double   PI   =   3.141592653589793

double   Dms2Rad(double   Dms); 
double   Rad2Dms(double   Rad); 

class   PrjPoint 

public
  
double   L0;   //   中央子午线经度 
  double   B,   L;   //   大地坐标 
  double   x,   y;   //   高斯投影平面坐标 
public
  
bool   BL2xy(); 
  
bool   xy2BL(); 

protected
  
double   a,   f,   e2,   e12;   //   基本椭球参数 
  double   A1,   A2,   A3,   A4;   //   用于计算X的椭球参数 

public
  
bool   SetL0(double   dL0); 
  
bool   SetBL(double   dB,   double   dL); 
  
bool   GetBL(double   *dB,   double   *dL); 
  
bool   Setxy(double   dx,   double   dy); 
  
bool   Getxy(double   *dx,   double   *dy); 
}; 

class   PrjPoint_Krasovsky   :   virtual   public   PrjPoint   //类的继承,声明基类是   PrjPoint,虚基类 

public
  PrjPoint_Krasovsky();   
//定义构造函数,用来初始化。(函数名和类名相同) 
  ~PrjPoint_Krasovsky(); 
}; 

class   PrjPoint_IUGG1975   :   virtual   public   PrjPoint 

public
  PrjPoint_IUGG1975(); 
  
~PrjPoint_IUGG1975(); 
}; 

#endif   /*   ndef   _COORTRANS_H_INCLUDED   */ 
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值