File: tm.c

package info (click to toggle)
gpstrans 0.34-6
  • links: PTS
  • area: main
  • in suites: potato
  • size: 476 kB
  • ctags: 348
  • sloc: ansic: 3,463; makefile: 97
file content (129 lines) | stat: -rw-r--r-- 5,468 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/****************************************************************************/
/*                                                                          */
/* ./gps/tm.c   -   Convert to selected datum                               */
/*                                                                          */
/* This file is part of gpstrans - a program to communicate with garmin gps */
/* Parts are taken from John F. Waers (jfwaers@csn.net) program MacGPS.     */
/*                                                                          */
/*                                                                          */
/*    Copyright (c) 1995 by Carsten Tschach (tschach@zedat.fu-berlin.de)    */
/*                                                                          */
/* Permission  to use, copy,  modify, and distribute  this software and its */
/* documentation for non-commercial purpose, is hereby granted without fee, */
/* providing that the  copyright notice  appear in all copies and that both */
/* the  copyright notice and  this permission  notice appear in  supporting */
/* documentation.  I make no representations about  the suitability of this */
/* software  for any  purpose.  It is  provides "as is" without  express or */
/* implid warranty.                                                         */
/*                                                                          */
/****************************************************************************/
#include "defs.h"
#include "Garmin.h"
#include "Prefs.h"
#include <math.h>


/****************************************************************************/
/* Equations from "Map Projections -- A Working Manual", USGS Professional  */
/* Paper 1395                                                               */
/****************************************************************************/


/* prototype function */
static double M(double phi, double a, double es);


/****************************************************************************/
/* Convert latitude and longitude to converted position.                    */
/****************************************************************************/
void toTM(double lat, double lon, double lat0, double lon0, double k0, 
	  double *x, double *y)
{
  extern struct PREFS gPrefs;
  double m, et2, n, t, c, A, a, m0, es, lambda, phi, lambda0, phi0;
  
  datumParams(gPrefs.datum, &a, &es);
  
  lambda  = lon * Degree;
  phi     = lat * Degree;
  
  phi0    = lat0 * Degree;
  lambda0 = lon0 * Degree;
  
  m0  = M(phi0, a, es);
  m   = M(phi, a, es);
  
  et2 = es / (1 - es);

  n   = a / sqrt(1 - es * pow(sin(phi), 2.0)); 
  t   = pow(tan(phi), 2.0);
  c   = et2 * pow(cos(phi), 2.0);
  A   = (lambda - lambda0) * cos(phi);
  *x  = k0*n*(A + (1.0 - t + c)*A*A*A/6.0 
        + (5.0 - 18.0*t + t*t + 72.0*c - 58.0*et2)*pow(A, 5.0) / 120.0);
  *y  = k0*(m - m0 + n*tan(phi)*(A*A/2.0
        + (5.0 - t + 9.0*c + 4*c*c)*pow(A, 4.0)/24.0
        + (61.0 - 58.0*t + t*t + 600.0*c - 330.0*et2)*
        pow(A, 6.0)/720.0) );
}


/****************************************************************************/
/* Convert converted position to latitude and longitude.                    */
/****************************************************************************/
void fromTM(double x, double y, double lat0, double lon0, double k0, 
	    double *lat, double *lon)
{
  extern struct PREFS gFilePrefs;
  double a, m0, es, et2, m, e1, mu, phi1, c1, t1, n1, r1, d, phi0, lambda0;
  
  phi0    = lat0 * Degree;
  lambda0 = lon0 * Degree;
  
  datumParams(gFilePrefs.datum, &a, &es);
  
  m0   = M(phi0, a, es);
  et2  = es / (1.0 - es);
  m    = m0 + y / k0;

  e1   = (1.0 - sqrt(1.0 - es)) / (1.0 + sqrt(1.0 - es));
  mu   = m / (a * (1.0 - es/4.0 - 3.0 * es*es/64.0 - 5.0 * es*es*es/256.0));
  phi1 = mu + (3.0 * e1/2.0 - 27.0 * pow(e1, 3.0)/32.0) * sin(2.0 * mu)
         + (21.0 * e1*e1/16.0 - 55.0 * pow(e1, 4.0)/32.0)
         * sin(4.0 * mu) + 151.0 * pow(e1, 3.0)/96.0 * sin(6.0 * mu)
         + 1097.0 * pow(e1, 4.0)/512.0 * sin(8.0 * mu);
  c1   = et2 * pow(cos(phi1), 2.0);
  t1   = pow(tan(phi1), 2.0);
  n1   = a / sqrt(1 - es * pow(sin(phi1), 2.0));
  r1   = a * (1.0 - es) / pow(1.0 - es * pow(sin(phi1), 2.0), 1.5);
  d    = x / (n1 * k0);
  *lat = (phi1 - n1 * tan(phi1) / r1
         * (d*d / 2.0 - (5.0 + 3.0 * t1 + 10.0 * c1 - 4.0 * c1*c1 - 9.0 * et2)
         * pow(d, 4.0) / 24.0 + (61.0 + 90.0 * t1 + 298.0 * c1 + 45.0 * t1*t1
         - 252.0 * et2 - 3.0 * c1*c1) * pow(d, 6.0) / 720.0 )) / Degree;
  *lon = (lambda0 + (d - (1.0 + 2.0 * t1 + c1) * pow(d, 3.0)/6.0
         + (5.0 -2.0 * c1 + 28.0 * t1 - 3.0 * c1*c1 + 8.0 * et2 + 24.0 * t1*t1)
         * pow(d, 5.0)/120.0) / cos(phi1)) / Degree;
}


/****************************************************************************/
/* Do some calculations  -  don't really know whats happen here.            */
/****************************************************************************/
static double M(double phi, double a, double es)
{
  double fix;

  if (phi == 0.0)
    return 0.0;
  else {
    fix =  a * (
           (1.0 - es/4.0 - 3.0*es*es/64.0 - 5.0*es*es*es/256.0 ) * phi -
           (3.0 * es/8.0 + 3.0*es*es/32.0 + 45.0*es*es*es/1024.0 ) * 
            sin(2.0 * phi) +
           (15.0 * es*es/256.0 + 45.0*es*es*es/1024.0 ) * sin(4.0 * phi) -
           (35.0*es*es*es/3072.0 ) * sin(6.0 * phi) );
    return fix;
  }
}