GPS坐标转笛卡尔坐标

提要

我们知道GPS坐标是由经度,纬度,海拔组成,精度和纬度都是角度,海报是高度。

在进行基于地理的搜索的时候,常用到KDTree,在构建在KDTree的时候,不能直接用GPS的坐标,要将GPS坐标转换成笛卡尔坐标才能用于构建KDTree。下面就是相关的转换算法。

注:GPS信息由几种标准,这里的采用的是google map的经纬度信息。

js实现

geodecy.js

/*             geodesy routines in JavaScript
                 James R. Clynch NPS / 2003

          Done for support of web education pages

          == must convert inputs to numbers for safety ==
          == if string comes in - sometimes works, sometimes not !==
*/

<!--

// =======================================================================

     function geodGBL()

//             test and ensure geodesy globals loaded
     {

     var  tstglobal

     tstglobal = typeof EARTH_A;
     if ( tstglobal == "undefined" )  wgs84() 

     }

// =======================================================================

       function earthcon(ai,bi)

/*        Sets Earth Constants as globals
             --  input a,b
             --  Leaves Globals
                 EARTH_A      EARTH_B   EARTH_F  EARTH_Ecc
*/

     {
           var  f,ecc, eccsq, a,b

           a        =  Number(ai);
           b        =  Number(bi);

           f        =  1-b/a;
           eccsq    =  1 - b*b/(a*a);
           ecc      =  Math.sqrt(eccsq);

           EARTH_A  =  a;
           EARTH_B  =  b;
           EARTH_F  =  f;
           EARTH_Ecc=  ecc;
           EARTH_Esq=  eccsq;
     }

// =======================================================================

     function wgs84()

/*        WGS84 Earth Constants
             --  returns a,b,f,e  --
             --  Leaves Globals
                 EARTH_A      EARTH_B   EARTH_F  EARTH_Ecc

*/

     {
          var  wgs84a, wgs84b, wgs84f

          wgs84a         =  6378.137;
          wgs84f         =  1.0/298.257223563;
          wgs84b         =  wgs84a * ( 1.0 - wgs84f );

          earthcon (wgs84a, wgs84b );

     }          

// =======================================================================

    function  radcur(lati)

/*
       compute the radii at the geodetic latitude lat (in degrees)

     input:
               lat       geodetic latitude in degrees
     output:
               rrnrm     an array 3 long
                         r,  rn,  rm   in km

*/

{

     var rrnrm = new Array(3)

     var dtr   = Math.PI/180.0

     var  a,b,lat
     var  asq,bsq,eccsq,ecc,clat,slat
     var  dsq,d,rn,rm,rho,rsq,r,z

//        -------------------------------------

     geodGBL();

     a     = EARTH_A;
     b     = EARTH_B;

     asq   = a*a;
     bsq   = b*b;
     eccsq  =  1 - bsq/asq;
     ecc = Math.sqrt(eccsq);

     lat   =  Number(lati);

     clat  =  Math.cos(dtr*lat);
     slat  =  Math.sin(dtr*lat);

     dsq   =  1.0 - eccsq * slat * slat;
     d     =  Math.sqrt(dsq);

     rn    =  a/d;
     rm    =  rn * (1.0 - eccsq ) / dsq;

     rho   =  rn * clat;
     z     =  (1.0 - eccsq ) * rn * slat;
     rsq   =  rho*rho + z*z;
     r     =  Math.sqrt( rsq );

     rrnrm[0]  =  r;
     rrnrm[1]  =  rn;
     rrnrm[2]  =  rm;

     return ( rrnrm );

   }

// =======================================================================

//        physical radius of earth from geodetic latitude

     function  rearth (lati)
     {
          var    rrnrm, r,lat

          lat   =  Number(lati);

          rrnrm =  radcur ( lat );
          r     =  rrnrm[0];

          return ( r );

     }

// =======================================================================

     function  gc2gd (flatgci, altkmi )

/*        geocentric latitude to geodetic latitude

     Input:
               flatgc    geocentric latitude deg.
               altkm     altitide in km
     ouput:
               flatgd    geodetic latitude in deg

*/

     {

     var dtr   = Math.PI/180.0;
     var rtd   = 1/dtr;

     var  flatgd,flatgc,altkm
     var  rrnrm = new Array(3)
     var  re,rn,ecc, esq;
     var  slat,clat,tlat
     var  altnow,ratio

     geodGBL();

     flatgc=  Number(flatgci);
     altkm =  Number(altkmi);

     ecc   =  EARTH_Ecc;
     esq   =  ecc*ecc;

//             approximation by stages
//             1st use gc-lat as if is gd, then correct alt dependence

     altnow  =  altkm;

     rrnrm   =  radcur (flatgc);
     rn      =  rrnrm[1];

     ratio   = 1 - esq*rn/(rn+altnow);

     tlat    = Math.tan(dtr*flatgc) / ratio;
     flatgd  = rtd * Math.atan(tlat);

//        now use this approximation for gd-lat to get rn etc.

     rrnrm   =  radcur ( flatgd );
     rn      =  rrnrm[1];

     ratio   =  1  - esq*rn/(rn+altnow)
     tlat    =  Math.tan(dtr*flatgc)/ratio;
     flatgd  =  rtd * Math.atan(tlat);

     return  flatgd

     }

// =======================================================================

     function  gd2gc (flatgdi, altkmi )

/*        geodetic latitude to geocentric latitude

     Input:
               flatgd    geodetic latitude deg.
               altkm     altitide in km
     ouput:
               flatgc    geocentric latitude in deg

*/

     {

     var dtr   = Math.PI/180.0;
     var rtd   = 1/dtr;

     var  flatgc,flatgd,altkm
     var  rrnrm = new Array(3)
     var  re,rn,ecc, esq;
     var  slat,clat,tlat
     var  altnow,ratio

     geodGBL();

     flatgd=  Number(flatgdi);
     altkm =  Number(altkmi);

     ecc   =  EARTH_Ecc;
     esq   =  ecc*ecc;

     altnow  =  altkm;

     rrnrm   =  radcur (flatgd);
     rn      =  rrnrm[1];

     ratio   = 1 - esq*rn/(rn+altnow);

     tlat    = Math.tan(dtr*flatgd) * ratio;
     flatgc  = rtd * Math.atan(tlat);

     return  flatgc;

     }

// =======================================================================

     function  llenu ( flati,floni)

/*        latitude longitude to east,north,up unit vectors

     input:
               flat      latitude in degees N
                         [ gc -> gc enu,  gd usual enu ]
               flon      longitude in degrees E
     output:
               enu[3[3]]  packed 3-unit vectors / each a 3 vector

*/

     {

     var  flat,flon;
     var  dtr,clat,slat,clon,slon  ;
     var  ee = new Array(3);
     var  en = new Array(3);
     var  eu = new Array(3);

     var  enu = new Array(3);

     var dtr   = Math.PI/180.0

//             --------------------------------

     flat = Number(flati);
     flon = Number(floni);

     clat = Math.cos(dtr*flat);
     slat = Math.sin(dtr*flat);
     clon = Math.cos(dtr*flon);
     slon = Math.sin(dtr*flon);

     ee[0]  =  -slon;
     ee[1]  =   clon;
     ee[2]  =   0.0;

     en[0]  =  -clon * slat;
     en[1]  =  -slon * slat;
     en[2]  =          clat;

     eu[0]  =   clon * clat;
     eu[1]  =   slon * clat;
     eu[2]  =          slat;

     enu[0] =  ee;
     enu[1] =  en;
     enu[2] =  eu;

     return  enu ;

     }

// =======================================================================

       function llhxyz (flati,floni, altkmi )

/*        lat,lon,height to xyz vector

     input:
          flat      geodetic latitude in deg
          flon      longitude in deg
          altkm     altitude in km
     output:
          returns vector x 3 long ECEF in km

*/

     {

      var  dtr =  Math.PI/180.0;
      var  flat,flon,altkm;
      var  clat,clon,slat,slon;
      var  rrnrm = new Array(3);
      var  rn,esq;
      var  x,y,z;
      var  xvec = new Array(3);

     geodGBL();

     flat  = Number(flati);
     flon  = Number(floni);
     altkm = Number(altkmi);

     clat = Math.cos(dtr*flat);
     slat = Math.sin(dtr*flat);
     clon = Math.cos(dtr*flon);
     slon = Math.sin(dtr*flon);

     rrnrm  = radcur (flat);
     rn     = rrnrm[1];
     re     = rrnrm[0];

     ecc    = EARTH_Ecc;
     esq    = ecc*ecc

     x      =  (rn + altkm) * clat * clon;
     y      =  (rn + altkm) * clat * slon;
     z      =  ( (1-esq)*rn + altkm ) * slat;

     xvec[0]  = x;
     xvec[1]  = y;
     xvec[2]  = z;

     return  xvec ;

     }

// =======================================================================

       function xyzllh ( xvec )

/*        xyz vector  to  lat,lon,height

     input:
          xvec[3]   xyz ECEF location
     output:

          llhvec[3] with components

          flat      geodetic latitude in deg
          flon      longitude in deg
          altkm     altitude in km

*/

     {

      var  dtr =  Math.PI/180.0;
      var  flatgc,flatn,dlat;
      var  rnow,rp;
      var  x,y,z,p;
      var  tangc,tangd;

      var  testval,kount;

      var  rn,esq;
      var  clat,slat;
      var  rrnrm = new Array(3);

      var  flat,flon,altkm;
      var  llhvec = new Array(3);

     geodGBL();

     esq    =  EARTH_Esq;

     x      = xvec[0];
     y      = xvec[1];
     z      = xvec[2];

     x      = Number(x);
     y      = Number(y);
     z      = Number(z);

     rp     = Math.sqrt ( x*x + y*y + z*z );

     flatgc = Math.asin ( z / rp )/dtr;

     testval= Math.abs(x) + Math.abs(y);
     if ( testval < 1.0e-10)
         {flon = 0.0 }
     else
         {flon = Math.atan2 ( y,x )/dtr }
     if (flon < 0.0 )  { flon = flon + 360.0 }

     p      =  Math.sqrt( x*x + y*y );

//             on pole special case

     if ( p < 1.0e-10 )
       {
          flat = 90.0
          if ( z < 0.0 ) { flat = -90.0 }

          altkm = rp - rearth(flat);
          llhvec[0]  = flat;
          llhvec[1]  = flon;
          llhvec[2]  = altkm;

          return  llhvec;
        }

//        first iteration, use flatgc to get altitude
//        and alt needed to convert gc to gd lat.

     rnow  =  rearth(flatgc);
     altkm =  rp - rnow;
     flat  =  gc2gd (flatgc,altkm);

     rrnrm =  radcur(flat);
     rn    =  rrnrm[1];

     for ( var kount = 0; kount< 5 ; kount++ )
       {
           slat  =  Math.sin(dtr*flat);
           tangd =  ( z + rn*esq*slat ) / p;
           flatn =  Math.atan(tangd)/dtr;

           dlat  =  flatn - flat;
           flat  =  flatn;
           clat  =  Math.cos( dtr*flat );

           rrnrm =  radcur(flat);
           rn    =  rrnrm[1];

           altkm =  (p/clat) - rn;

           if ( Math.abs(dlat) < 1.0e-12 ) { break }

       }

          llhvec[0]  = flat;
          llhvec[1]  = flon;
          llhvec[2]  = altkm;

          return  llhvec ;

     }

// =======================================================================

//-->

C++实现

就是根据将JS代码转成C艹.

GPS 转笛卡尔

void GPSTransform::gpsPoint2DescartesPoint(const double latitude, const double longitude, const double altitude, double &x, double &y, double &z)
{
	//wgs84 WGS84 Earth Constants
	double wgs84a = 6378.137;
	double wgs84f = 1.0 / 298.257223563;
	double wgs84b = wgs84a * (1.0 - wgs84f);

	//earthcon
	double f = 1 - wgs84b / wgs84a;
	double eccsq = 1 - (wgs84b* wgs84b) / (wgs84a * wgs84a);
	double ecc = sqrt(eccsq);
	double esq = ecc * ecc;

	//llhxyz
	double dtr = M_PI / 180.0;
	//qDebug() << dtr << gpsPoint.latitude << endl;
	double clat = cos(dtr * latitude);
	double slat = sin(dtr * latitude);
	double clon = cos(dtr * longitude);
	double slon = sin(dtr * longitude);
	//qDebug() << clat << slon << endl;

	//radcur compute the radii at the geodetic latitude lat (in degrees)
	double dsq = 1.0 - eccsq * slat *slat;
	double d = sqrt(dsq);
	//qDebug() << d;
	double rn = wgs84a / d;
	double rm = rn * (1.0 - eccsq) / dsq;

	double rho = rn * clat;
	double zz = (1.0 - eccsq) * rn *slat;
	double rsq = rho * rho + zz*zz;
	double r = sqrt(rsq);

	x = (rn + altitude) * clat * clon;
	y = (rn + altitude) * clat * slon;
	z = ((1 - esq)*rn + altitude) * slat;
}

运行结果

验证网站

Geodetic to Cartesian Converter - http://www.apsalin.com/convert-geodetic-to-cartesian.aspx

atitude,Longitude,Height to/from ECEF (X,Y,Z) - http://www.oc.nps.edu/oc2902w/coord/llhxyz.htm

时间: 2024-08-08 14:39:57

GPS坐标转笛卡尔坐标的相关文章

delphi 调用百度地图WEBSERVICE转换GPS坐标

百度地图的API说明 使用方法 第一步,申请密钥(ak),作为访问服务的依据: 第二步,按照请求参数说明拼写发送http请求的url,注意需使用第一步申请的ak: 第三步,接收返回的数据(json或者xml格式). 注:本接口支持回调. 服务地址 http://api.map.baidu.com/geoconv/v1/? 组成说明: 域名:http://api.map.baidu.com 服务名:geoconv 服务版本号:v1 服务参数说明 参数 含义 取值范围 是否必须 默认取值 coord

ios根据gps坐标来计算两点间的距离

//ios根据gps坐标来计算两点间的距离 //x1,y1 点1的坐标 x2,y2点2的坐标 -(double) gps2m:(double)x1 _y1:(double)y1 _x2:(double)x2 _y2:(double)y2{ double radLat1 = (x1 * 3.1416 / 180.0); double radLat2 = (x2 * 3.1416 / 180.0); double a = radLat1 - radLat2; double b = (y1 - y2)

GPS坐标换算为百度坐标

最近在做一个关于手机定位的小应用,需求是这样的,用户通过手机(Wp8)进行二维码扫描操作并且记录用户的当前位置,在PC上可以查看用户所在地图的位置,做法就是在用户扫描条码时,通过手机GPS获取当前在地图上的位置(采用百度静态地图,根据坐标直接生成图片)并将图片保存到数据库,PC端直接从数据库中读取并展示图片.问题是:生成的图片所呈现的位置与实际位置偏差太大.于是我开始踏上了寻找解决办法的道路. 首先我检测我的硬件设备是否定位准确,我用WP8手机内置的地图进行了当前位置定位,结果没有问题,说明我的

地图坐标转换 -- 火星坐标与GPS坐标

第一次处理地理位置的数据的人,没什么经验,往往掉入很多坑浪费不少时间.我也是刚刚从坑里爬出来.这篇博文主要是把入门GPS轨迹分析的经验总结一下,以方便大家少走些弯路. (1)可视化 GPS 路径 刚拿到一堆GPS轨迹数据,想看看它长什么样?于是先想办法把它们可视化出来.有很多地图的API可以用,如果不是想搞演示,只是为了快速随便看一眼的话,推荐用百度的在线示例API  http://developer.baidu.com/map/jsdemo.htm#c1_3  里面有比较详细的例子,很丰富的操

计算两个GPS坐标点的距离

计算两个GPS坐标点的距离,第一个参数是第一个点的维度,第二个参数是第一个点的经度 http://yuninglovekefan.blog.sohu.com/235655696.html /** * */ package utils; /** * 坐标计算的工具类 * * @author ywf * */ public class PositionUtils { private static final double EARTH_RADIUS = 6371.004; static double

GPS坐标 转 ECEF地球坐标

#include "stdafx.h" #include <math.h> #define  PI 3.14159 /* 该程序主要是实现从GPS坐标转换为地球的三维坐标的函数 */ void GPS2ECEF(double latitude, double longitude, double height, double &X, double &Y, double &Z) { double a = 6378137; double b = 63567

GPS坐标互转:WGS-84(GPS)、GCJ-02(Google地图)、BD-09(百度地图)(转载)

WGS-84:是国际标准,GPS坐标(Google Earth使用.或者GPS模块)GCJ-02:中国坐标偏移标准,Google Map.高德.腾讯使用BD-09:百度坐标偏移标准,Baidu Map使用//WGS-84 to GCJ-02GPS.gcj_encrypt();//GCJ-02 to WGS-84 粗略GPS.gcj_decrypt();//GCJ-02 to WGS-84 精确(二分极限法)// var threshold = 0.000000001; 目前设置的是精确到小数点后

GPS坐标转化为百度坐标

============问题描述============ 想把手机采集的GPS坐标转化为百度坐标,在网上找了一下代码: GeoPoint geoPoint3 = new GeoPoint((int) ((mLat1 + 0.001) * 1E6), (int) ((mLon1 + 0.003) * 1E6)); GeoPoint GeoPointBaidu = CoordinateConvert.fromWgs84ToBaidu(geoPoint3);  mOverlayList.add(new

GPS坐标互转:WGS-84(GPS)、GCJ-02(Google地图)、BD-09(百度地图)

WGS-84:是国际标准,GPS坐标(Google Earth使用.或者GPS模块)GCJ-02:中国坐标偏移标准,Google Map.高德.腾讯使用BD-09:百度坐标偏移标准,Baidu Map使用 //WGS-84 to GCJ-02GPS.gcj_encrypt(); //GCJ-02 to WGS-84 粗略GPS.gcj_decrypt(); //GCJ-02 to WGS-84 精确(二分极限法)// var threshold = 0.000000001; 目前设置的是精确到小