57 static inline void UTM(
double lat,
double lon,
double *x,
double *y)
60 const static double m0 = (1 - UTM_E2/4 - 3*UTM_E4/64 - 5*UTM_E6/256);
61 const static double m1 = -(3*UTM_E2/8 + 3*UTM_E4/32 + 45*UTM_E6/1024);
62 const static double m2 = (15*UTM_E4/256 + 45*UTM_E6/1024);
63 const static double m3 = -(35*UTM_E6/3072);
66 int cm = ((lon >= 0.0)
67 ? ((int)lon - ((
int)lon)%6 + 3)
68 : ((int)lon - ((
int)lon)%6 - 3));
76 double slat = sin(rlat);
77 double clat = cos(rlat);
78 double tlat = tan(rlat);
81 double fn = (lat > 0) ? UTM_FN_N : UTM_FN_S;
83 double T = tlat * tlat;
84 double C = UTM_EP2 * clat * clat;
85 double A = (rlon - rlon0) * clat;
86 double M = WGS84_A * (m0*rlat + m1*sin(2*rlat)
87 + m2*sin(4*rlat) + m3*sin(6*rlat));
88 double V = WGS84_A / sqrt(1 - UTM_E2*slat*slat);
91 *x = UTM_FE + UTM_K0 * V * (A + (1-T+C)*pow(A,3)/6
92 + (5-18*T+T*T+72*C-58*
UTM_EP2)*pow(A,5)/120);
93 *y = fn + UTM_K0 * (M + V * tlat * (A*A/2
94 + (5-T+9*C+4*C*C)*pow(A,4)/24
95 + ((61-58*T+T*T+600*C-330*
UTM_EP2)
112 char LetterDesignator;
114 if ((84 >= Lat) && (Lat >= 72)) LetterDesignator =
'X';
115 else if ((72 > Lat) && (Lat >= 64)) LetterDesignator =
'W';
116 else if ((64 > Lat) && (Lat >= 56)) LetterDesignator =
'V';
117 else if ((56 > Lat) && (Lat >= 48)) LetterDesignator =
'U';
118 else if ((48 > Lat) && (Lat >= 40)) LetterDesignator =
'T';
119 else if ((40 > Lat) && (Lat >= 32)) LetterDesignator =
'S';
120 else if ((32 > Lat) && (Lat >= 24)) LetterDesignator =
'R';
121 else if ((24 > Lat) && (Lat >= 16)) LetterDesignator =
'Q';
122 else if ((16 > Lat) && (Lat >= 8)) LetterDesignator =
'P';
123 else if (( 8 > Lat) && (Lat >= 0)) LetterDesignator =
'N';
124 else if (( 0 > Lat) && (Lat >= -8)) LetterDesignator =
'M';
125 else if ((-8 > Lat) && (Lat >= -16)) LetterDesignator =
'L';
126 else if((-16 > Lat) && (Lat >= -24)) LetterDesignator =
'K';
127 else if((-24 > Lat) && (Lat >= -32)) LetterDesignator =
'J';
128 else if((-32 > Lat) && (Lat >= -40)) LetterDesignator =
'H';
129 else if((-40 > Lat) && (Lat >= -48)) LetterDesignator =
'G';
130 else if((-48 > Lat) && (Lat >= -56)) LetterDesignator =
'F';
131 else if((-56 > Lat) && (Lat >= -64)) LetterDesignator =
'E';
132 else if((-64 > Lat) && (Lat >= -72)) LetterDesignator =
'D';
133 else if((-72 > Lat) && (Lat >= -80)) LetterDesignator =
'C';
135 else LetterDesignator =
'Z';
136 return LetterDesignator;
148 static inline void LLtoUTM(
const double Lat,
const double Long,
149 double &UTMNorthing,
double &UTMEasting,
153 double eccSquared =
UTM_E2;
157 double eccPrimeSquared;
158 double N, T, C, A, M;
161 double LongTemp = (Long+180)-
int((Long+180)/360)*360-180;
165 double LongOriginRad;
168 ZoneNumber = int((LongTemp + 180)/6) + 1;
170 if( Lat >= 56.0 && Lat < 64.0 && LongTemp >= 3.0 && LongTemp < 12.0 )
174 if( Lat >= 72.0 && Lat < 84.0 )
176 if( LongTemp >= 0.0 && LongTemp < 9.0 ) ZoneNumber = 31;
177 else if( LongTemp >= 9.0 && LongTemp < 21.0 ) ZoneNumber = 33;
178 else if( LongTemp >= 21.0 && LongTemp < 33.0 ) ZoneNumber = 35;
179 else if( LongTemp >= 33.0 && LongTemp < 42.0 ) ZoneNumber = 37;
182 LongOrigin = (ZoneNumber - 1)*6 - 180 + 3;
188 eccPrimeSquared = (eccSquared)/(1-eccSquared);
190 N = a/sqrt(1-eccSquared*sin(LatRad)*sin(LatRad));
191 T = tan(LatRad)*tan(LatRad);
192 C = eccPrimeSquared*cos(LatRad)*cos(LatRad);
193 A = cos(LatRad)*(LongRad-LongOriginRad);
195 M = a*((1 - eccSquared/4 - 3*eccSquared*eccSquared/64 - 5*eccSquared*eccSquared*eccSquared/256)*LatRad
196 - (3*eccSquared/8 + 3*eccSquared*eccSquared/32 + 45*eccSquared*eccSquared*eccSquared/1024)*sin(2*LatRad)
197 + (15*eccSquared*eccSquared/256 + 45*eccSquared*eccSquared*eccSquared/1024)*sin(4*LatRad)
198 - (35*eccSquared*eccSquared*eccSquared/3072)*sin(6*LatRad));
200 UTMEasting = (double)(k0*N*(A+(1-T+C)*A*A*A/6
201 + (5-18*T+T*T+72*C-58*eccPrimeSquared)*A*A*A*A*A/120)
204 UTMNorthing = (double)(k0*(M+N*tan(LatRad)*(A*A/2+(5-T+9*C+4*C*C)*A*A*A*A/24
205 + (61-58*T+T*T+600*C-330*eccPrimeSquared)*A*A*A*A*A*A/720)));
207 UTMNorthing += 10000000.0;
210 static inline void LLtoUTM(
const double Lat,
const double Long,
211 double &UTMNorthing,
double &UTMEasting,
212 std::string &UTMZone) {
213 char zone_buf[] = {0, 0, 0, 0};
215 LLtoUTM(Lat, Long, UTMNorthing, UTMEasting, zone_buf);
230 static inline void UTMtoLL(
const double UTMNorthing,
const double UTMEasting,
231 const char* UTMZone,
double& Lat,
double& Long )
235 double eccSquared =
UTM_E2;
236 double eccPrimeSquared;
237 double e1 = (1-sqrt(1-eccSquared))/(1+sqrt(1-eccSquared));
238 double N1, T1, C1, R1, D, M;
245 x = UTMEasting - 500000.0;
248 ZoneNumber = strtoul(UTMZone, &ZoneLetter, 10);
249 if((*ZoneLetter -
'N') < 0)
254 LongOrigin = (ZoneNumber - 1)*6 - 180 + 3;
256 eccPrimeSquared = (eccSquared)/(1-eccSquared);
259 mu = M/(a*(1-eccSquared/4-3*eccSquared*eccSquared/64-5*eccSquared*eccSquared*eccSquared/256));
261 phi1Rad = mu + (3*e1/2-27*e1*e1*e1/32)*sin(2*mu)
262 + (21*e1*e1/16-55*e1*e1*e1*e1/32)*sin(4*mu)
263 +(151*e1*e1*e1/96)*sin(6*mu);
265 N1 = a/sqrt(1-eccSquared*sin(phi1Rad)*sin(phi1Rad));
266 T1 = tan(phi1Rad)*tan(phi1Rad);
267 C1 = eccPrimeSquared*cos(phi1Rad)*cos(phi1Rad);
268 R1 = a*(1-eccSquared)/pow(1-eccSquared*sin(phi1Rad)*sin(phi1Rad), 1.5);
271 Lat = phi1Rad - (N1*tan(phi1Rad)/R1)*(D*D/2-(5+3*T1+10*C1-4*C1*C1-9*eccPrimeSquared)*D*D*D*D/24
272 +(61+90*T1+298*C1+45*T1*T1-252*eccPrimeSquared-3*C1*C1)*D*D*D*D*D*D/720);
275 Long = (D-(1+2*T1+C1)*D*D*D/6+(5-2*C1+28*T1-3*C1*C1+8*eccPrimeSquared+24*T1*T1)
276 *D*D*D*D*D/120)/cos(phi1Rad);
281 static inline void UTMtoLL(
const double UTMNorthing,
const double UTMEasting,
282 std::string UTMZone,
double& Lat,
double& Long) {
283 UTMtoLL(UTMNorthing, UTMEasting, UTMZone.c_str(), Lat, Long);
static char UTMLetterDesignator(double Lat)
static void UTMtoLL(const double UTMNorthing, const double UTMEasting, const char *UTMZone, double &Lat, double &Long)
static void LLtoUTM(const double Lat, const double Long, double &UTMNorthing, double &UTMEasting, char *UTMZone)
const double DEGREES_PER_RADIAN
const double RADIANS_PER_DEGREE
static void UTM(double lat, double lon, double *x, double *y)