Main Page | File List | Globals | Related Pages

latlong.c

00001 /****************************************************************************/
00002 /*                                                                          */
00003 /* ./gps/latlong.c   -   Convert latitude and longitude                     */
00004 /*                                                                          */
00005 /* This file is part of gpstrans - a program to communicate with garmin gps */
00006 /* Parts are taken from John F. Waers (jfwaers@csn.net) program MacGPS.     */
00007 /*                                                                          */
00008 /*                                                                          */
00009 /*    Copyright (c) 1995 by Carsten Tschach (tschach@zedat.fu-berlin.de)    */
00010 /*                                                                          */
00011 /* Permission  to use, copy,  modify, and distribute  this software and its */
00012 /* documentation for non-commercial purpose, is hereby granted without fee, */
00013 /* providing that the  copyright notice  appear in all copies and that both */
00014 /* the  copyright notice and  this permission  notice appear in  supporting */
00015 /* documentation.  I make no representations about  the suitability of this */
00016 /* software  for any  purpose.  It is  provides "as is" without  express or */
00017 /* implid warranty.                                                         */
00018 /*                                                                          */
00019 /****************************************************************************/
00020 
00021 
00022 #include <PalmOS.h>
00023 #include <PalmCompatibility.h>
00024 #include "latlong.h"
00025 #include "MathLib.h"
00026 
00027 /* define constants */
00028 // static double CONVERT = 11930464.7111111111111;              /* 2^31 / 180 */
00029 /* #ifndef __LINUX__ */
00030 static double PI = 3.14159265358979323846;      /* PI */
00031 /* #endif */
00032 static double WGSa = 6378137.0;        /* WGS84 semimajor axis */
00033 static double WGSinvf = 298.257223563; /* WGS84 1/f */
00034 
00035 
00036 
00037 /****************************************************************************/
00038 /* Converts latitude and longitude in decimal degrees from WGS84 to another */
00039 /* datum or from another datum to WGS84. The arguments to this function     */
00040 /* include a direction flag 'fromWGS84', pointers to double precision       */
00041 /* latitude and longitude, and an index to the gDatum[] array.              */
00042 /****************************************************************************/
00043 void
00044 translate (short fromWGS84, double *latitude, double *longitude,
00045            short datumID)
00046 {
00047 
00048     double dx = gDatum[datumID].dx;
00049     double dy = gDatum[datumID].dy;
00050     double dz = gDatum[datumID].dz;
00051 
00052     double phi = *latitude * PI / 180.0;
00053     double lambda = *longitude * PI / 180.0;
00054     double a0,
00055       b0,
00056       es0,
00057       f0;                              /* Reference ellipsoid of input data */
00058     double a1,
00059       b1,
00060       es1,
00061       f1;                              /* Reference ellipsoid of output data */
00062     double psi;                        /* geocentric latitude */
00063     double x,
00064       y,
00065       z;                               /* 3D coordinates with respect to original datum */
00066     double psi1;                       /* transformed geocentric latitude */
00067 
00068     if (datumID == WGS84Index)                             /* do nothing if current datum is WGS84 */
00069         return;
00070 
00071     if (fromWGS84)
00072       {                                                    /* convert from WGS84 to new datum */
00073           a0 = WGSa;                                       /* WGS84 semimajor axis */
00074           f0 = 1.0 / WGSinvf;                              /* WGS84 flattening */
00075           a1 = gEllipsoid[gDatum[datumID].ellipsoid].a;
00076           f1 = 1.0 / gEllipsoid[gDatum[datumID].ellipsoid].invf;
00077       }
00078     else
00079       {                                                    /* convert from datum to WGS84 */
00080           a0 = gEllipsoid[gDatum[datumID].ellipsoid].a;    /* semimajor axis */
00081           f0 = 1.0 / gEllipsoid[gDatum[datumID].ellipsoid].invf;        /* flattening */
00082           a1 = WGSa;                                       /* WGS84 semimajor axis */
00083           f1 = 1 / WGSinvf;                                /* WGS84 flattening */
00084           dx = -dx;
00085           dy = -dy;
00086           dz = -dz;
00087       }
00088 
00089     b0 = a0 * (1 - f0);                                    /* semiminor axis for input datum */
00090     es0 = 2 * f0 - f0 * f0;                                /* eccentricity^2 */
00091 
00092     b1 = a1 * (1 - f1);                                    /* semiminor axis for output datum */
00093     es1 = 2 * f1 - f1 * f1;                                /* eccentricity^2 */
00094 
00095     /* Convert geodedic latitude to geocentric latitude, psi */
00096     if (*latitude == 0.0 || *latitude == 90.0 || *latitude == -90.0)
00097         psi = phi;
00098     else
00099         psi = atan ((1 - es0) * tan (phi));
00100 
00101     /* Calc x and y axis coordinates with respect to original ellipsoid */
00102     if (*longitude == 90.0 || *longitude == -90.0)
00103       {
00104           x = 0.0;
00105           y = fabs (a0 * b0 / sqrt (b0 * b0 + a0 * a0 * pow (tan (psi), 2.0)));
00106       }
00107     else
00108       {
00109           x = fabs ((a0 * b0) /
00110                     sqrt ((1 + pow (tan (lambda), 2.0)) *
00111                           (b0 * b0 + a0 * a0 * pow (tan (psi), 2.0))));
00112           y = fabs (x * tan (lambda));
00113       }
00114 
00115     if (*longitude < -90.0 || *longitude > 90.0)
00116         x = -x;
00117     if (*longitude < 0.0)
00118         y = -y;
00119 
00120     /* Calculate z axis coordinate with respect to the original ellipsoid */
00121     if (*latitude == 90.0)
00122         z = b0;
00123     else if (*latitude == -90.0)
00124         z = -b0;
00125     else
00126         z = tan (psi) * sqrt ((a0 * a0 * b0 * b0) / (b0 * b0 + a0 * a0 * pow (tan (psi), 2.0)));
00127 
00128     /* Calculate the geocentric latitude with respect to the new ellipsoid */
00129     psi1 = atan ((z - dz) / sqrt ((x - dx) * (x - dx) + (y - dy) * (y - dy)));
00130 
00131     /* Convert to geocentric latitude and save return value */
00132     *latitude = atan (tan (psi1) / (1 - es1)) * 180.0 / PI;
00133 
00134     /* Calculate the longitude with respect to the new ellipsoid */
00135     *longitude = atan ((y - dy) / (x - dx)) * 180.0 / PI;
00136 
00137     /* Correct the resultant for negative x values */
00138     if (x - dx < 0.0)
00139       {
00140           if (y - dy > 0.0)
00141               *longitude = 180.0 + *longitude;
00142           else
00143               *longitude = -180.0 + *longitude;
00144       }
00145 }

Generated on Sun Aug 29 11:00:40 2004 for GPilotS by doxygen 1.3.4