OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimUtmProjection.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 //
3 // License: See top LICENSE.txt file.
4 //
5 // Author: Garrett Potts
6 //
7 // Description:
8 //
9 // Calls Geotrans Utm projection code.
10 //*******************************************************************
11 // $Id: ossimUtmProjection.cpp 20133 2011-10-12 19:03:47Z oscarkramer $
12 
13 #include <cstdlib>
14 #include <cmath>
15 using namespace std;
16 
21 
22 RTTI_DEF1(ossimUtmProjection, "ossimUtmProjection", ossimMapProjection)
23 
24 /******************************* DEFINES *********************************/
25 
26 #define UTM_NO_ERROR 0x0000
27 #define UTM_LAT_ERROR 0x0001
28 #define UTM_LON_ERROR 0x0002
29 #define UTM_EASTING_ERROR 0x0004
30 #define UTM_NORTHING_ERROR 0x0008
31 #define UTM_ZONE_ERROR 0x0010
32 #define UTM_HEMISPHERE_ERROR 0x0020
33 #define UTM_ZONE_OVERRIDE_ERROR 0x0040
34 #define UTM_A_ERROR 0x0080
35 #define UTM_B_ERROR 0x0100
36 #define UTM_A_LESS_B_ERROR 0x0200
37 
38 #define MIN_LAT ( (-80.5 * M_PI) / 180.0 ) /* -80.5 degrees in radians */
39 #define MAX_LAT ( (84.5 * M_PI) / 180.0 ) /* 84.5 degrees in radians */
40 #define MAX_DELTA_LONG ((M_PI * 90.0)/180.0) /* 90 degrees in radians */
41 #define MIN_EASTING 100000
42 #define MAX_EASTING 900000
43 #define MIN_NORTHING 0
44 #define MAX_NORTHING 10000000
45 #define MIN_SCALE_FACTOR 0.3
46 #define MAX_SCALE_FACTOR 3.0
47 
48 #define SPHTMD(Latitude) ((double) (theTranMerc_ap * Latitude \
49  - theTranMerc_bp * sin(2.e0 * Latitude) + theTranMerc_cp * sin(4.e0 * Latitude) \
50  - theTranMerc_dp * sin(6.e0 * Latitude) + theTranMerc_ep * sin(8.e0 * Latitude) ) )
51 
52 #define SPHSN(Latitude) ((double) (getA() / sqrt( 1.e0 - theTranMerc_es * \
53  pow(sin(Latitude), 2))))
54 
55 #define SPHSR(Latitude) ((double) (getA() * (1.e0 - theTranMerc_es) / \
56  pow(DENOM(Latitude), 3)))
57 
58 #define DENOM(Latitude) ((double) (sqrt(1.e0 - theTranMerc_es * pow(sin(Latitude),2))))
59 
60 
62  const ossimGpt& origin)
63  :
64  ossimMapProjection(ellipsoid, origin),
65  theTranMerc_a(6378137.0),
66  theTranMerc_f(1.0/298.257223563),
67  theTranMerc_es(0.0066943799901413800),
68  theTranMerc_ebs(0.0067394967565869),
69  theTranMerc_Origin_Lat(0.0),
70  theTranMerc_Origin_Long(0.0),
71  theTranMerc_False_Northing(0.0),
72  theTranMerc_False_Easting(500000.0),
73  theTranMerc_Scale_Factor(0.9996),
74  theTranMerc_ap(6367449.1458008),
75  theTranMerc_bp(16038.508696861),
76  theTranMerc_cp(16.832613334334),
77  theTranMerc_dp(0.021984404273757),
78  theTranMerc_Delta_Easting(40000000.0),
79  theTranMerc_Delta_Northing(40000000.0),
80  theZone(1),
81  theHemisphere('N')
82 
83 {
84  setZone(origin);
86  update();
87 }
88 
90  const ossimGpt& origin,
91  ossim_int32 zone,
92  char hemisphere)
93  :
94  ossimMapProjection(ellipsoid, origin),
95  theTranMerc_a(6378137.0),
96  theTranMerc_f(1.0/298.257223563),
97  theTranMerc_es(0.0066943799901413800),
98  theTranMerc_ebs(0.0067394967565869),
99  theTranMerc_Origin_Lat(0.0),
100  theTranMerc_Origin_Long(0.0),
101  theTranMerc_False_Northing(0.0),
102  theTranMerc_False_Easting(500000.0),
103  theTranMerc_Scale_Factor(0.9996),
104  theTranMerc_ap(6367449.1458008),
105  theTranMerc_bp(16038.508696861),
106  theTranMerc_cp(16.832613334334),
107  theTranMerc_dp(0.021984404273757),
108  theTranMerc_Delta_Easting(40000000.0),
109  theTranMerc_Delta_Northing(40000000.0),
110  theZone(zone),
111  theHemisphere(hemisphere)
112 {
113  setZone(zone);
114  setHemisphere(hemisphere);
115  update();
116 }
117 
119  :
121  theTranMerc_a(6378137.0),
122  theTranMerc_f(1.0/298.257223563),
123  theTranMerc_es(0.0066943799901413800),
124  theTranMerc_ebs(0.0067394967565869),
125  theTranMerc_Origin_Lat(0.0),
126  theTranMerc_Origin_Long(0.0),
127  theTranMerc_False_Northing(0.0),
128  theTranMerc_False_Easting(500000.0),
129  theTranMerc_Scale_Factor(0.9996),
130  theTranMerc_ap(6367449.1458008),
131  theTranMerc_bp(16038.508696861),
132  theTranMerc_cp(16.832613334334),
133  theTranMerc_dp(0.021984404273757),
134  theTranMerc_Delta_Easting(40000000.0),
135  theTranMerc_Delta_Northing(40000000.0),
136  theZone(zone),
137  theHemisphere('N')
138 {
139  setZone(zone);
140  update();
141 }
142 
144  :ossimMapProjection(src),
145  theTranMerc_a(src.theTranMerc_a),
146  theTranMerc_f(src.theTranMerc_f),
147  theTranMerc_es(src.theTranMerc_es),
148  theTranMerc_ebs(src.theTranMerc_ebs),
149  theTranMerc_Origin_Lat(src.theTranMerc_Origin_Lat),
150  theTranMerc_Origin_Long(src.theTranMerc_Origin_Long),
151  theTranMerc_False_Northing(src.theTranMerc_False_Northing),
152  theTranMerc_False_Easting(src.theTranMerc_False_Easting),
153  theTranMerc_Scale_Factor(src.theTranMerc_Scale_Factor),
154  theTranMerc_ap(src.theTranMerc_ap),
155  theTranMerc_bp(src.theTranMerc_bp),
156  theTranMerc_cp(src.theTranMerc_cp),
157  theTranMerc_dp(src.theTranMerc_dp),
158  theTranMerc_Delta_Easting(src.theTranMerc_Delta_Easting),
159  theTranMerc_Delta_Northing(src.theTranMerc_Delta_Northing),
160  theZone(src.theZone),
161  theHemisphere(src.theHemisphere)
162 {
163  setZone(theZone);
165  update();
166 }
167 
169 {
172  origin.latd(0.0);
173  double falseNorthing = 10000000.0;
174  if (theHemisphere == 'N')
175  {
176  falseNorthing = 0.0;
177  }
180  origin.latr(),
181  origin.lonr(),
183  falseNorthing,
185 
188 
190 }
191 
192 ossimGpt ossimUtmProjection::inverse(const ossimDpt &eastingNorthing)const
193 {
194  double lat = 0.0;
195  double lon = 0.0;
196 
198  eastingNorthing.y,
199  &lat,
200  &lon);
201 
202  return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum);
203 }
204 
206 {
207  double easting = 0.0;
208  double northing = 0.0;
209  ossimGpt gpt = latLon;
210 
211  if (theDatum)
212  {
213  if (theDatum->code() != latLon.datum()->code())
214  {
215  gpt.changeDatum(theDatum); // Shift to our datum.
216  }
217  }
218 
220  gpt.lonr(),
221  &easting,
222  &northing);
223 
224  return ossimDpt(easting, northing);
225 }
226 
228 {
229  ossimUtmProjection* proj = new ossimUtmProjection(*this);
230  return proj;
231 }
232 
234 {
235  return theZone;
236 }
237 
239 {
240  return theHemisphere;
241 }
242 
244 {
245  setZone(origin);
246  // NOTE: We will not set the hemisphere if the origin latitude is 0.0.
247  if (origin.latd() != 0.0)
248  {
250  }
252 }
253 
255 {
256  setZone(computeZone(ground));
257 }
258 
260 {
261  if( (zone < 1) || (zone > 60) )
262  {
264  }
265  else
266  {
267  theZone = zone;
268  }
270  theOrigin.latd(0);
273 }
274 
276 {
277  char hemisphere = ground.latd()<0.0?'S':'N';
278  setHemisphere(hemisphere);
279 }
280 
282 {
283  hemisphere = toupper(hemisphere);
284  if((hemisphere != 'N') &&
285  (hemisphere != 'S'))
286  {
287  theHemisphere = theOrigin.latd() < 0?'S':'N';
288  }
289  else
290  {
291  theHemisphere = hemisphere;
292  }
293 
294  if (theHemisphere == 'N')
295  {
297  }
298  else
299  {
300  theTranMerc_False_Northing = 10000000.0;
301  }
302 }
303 
305 {
306  ossim_int32 result = 0;
307 
308  double longitude = ground.lonr();
309  double lat_Degrees = (ossim_int32)( (ground.latd()) + 0.00000005);
310  double long_Degrees = (ossim_int32)( (ground.lond()) + 0.00000005);
311 
312  if (longitude < M_PI)
313  result = (ossim_int32)( (31 + ((180 * longitude) / (6 * M_PI)) ) + 0.00000005);
314  else
315  result = (ossim_int32)( (((180 * longitude) / (6 * M_PI)) - 29) + 0.00000005);
316  if (result > 60)
317  result = 1;
318  /* UTM special cases */
319  if ((lat_Degrees > 55) && (lat_Degrees < 64) && (long_Degrees > -1)
320  && (long_Degrees < 3))
321  result = 31;
322  if ((lat_Degrees > 55) && (lat_Degrees < 64) && (long_Degrees > 2)
323  && (long_Degrees < 12))
324  result = 32;
325  if ((lat_Degrees > 71) && (long_Degrees > -1) && (long_Degrees < 9))
326  result = 31;
327  if ((lat_Degrees > 71) && (long_Degrees > 8) && (long_Degrees < 21))
328  result = 33;
329  if ((lat_Degrees > 71) && (long_Degrees > 20) && (long_Degrees < 33))
330  result = 35;
331  if ((lat_Degrees > 71) && (long_Degrees > 32) && (long_Degrees < 42))
332  result = 37;
333 
334  return result;
335 }
336 
338 {
339  return (6.0 * zone - 183.0);;
340 }
341 
343  const char* prefix)
344 {
345  const char* zone = kwl.find(prefix, ossimKeywordNames::ZONE_KW);
346  const char* hemisphere = kwl.find(prefix, ossimKeywordNames::HEMISPHERE_KW);
347 
348  ossimMapProjection::loadState(kwl, prefix);
349 
350  // initialize zone to a dummy value.
351  //
352  theZone = 0;
353 // if(ossimString(type) == STATIC_TYPE_NAME(ossimUtmProjection))
354  {
355  if(!zone)
356  {
358  }
359  else if (zone)
360  {
361  theZone = atoi(zone);
362 
363  if( (theZone < 1) || (theZone > 60) )
364  {
366  }
367  else
368  {
369 // if(!kwl.find(prefix, ossimKeywordNames::CENTRAL_MERIDIAN_KW))
370 // {
372 // }
373 // if(!kwl.find(prefix, ossimKeywordNames::ORIGIN_LATITUDE_KW))
374 // {
375  theOrigin.latd(0);
376 // }
377  }
378  }
379  if (hemisphere)
380  {
381  ossimString s = hemisphere;
382  s = s.trim();
383  s = s.upcase();
384 
385  setHemisphere(*s.c_str());
386  }
387  else
388  {
389  char hemisphere = theOrigin.latd()<0?'S':'N';
390  setHemisphere(hemisphere);
391  }
392  }
393 
394  update();
395 
396  return true;
397 }
398 
399 bool ossimUtmProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const
400 {
401  kwl.add(prefix,
403  theZone,
404  true);
405 
406  kwl.add(prefix,
409  true);
410 
411  return ossimMapProjection::saveState(kwl, prefix);
412 }
413 
415  double f,
416  double Origin_Latitude,
417  double Central_Meridian,
418  double False_Easting,
419  double False_Northing,
420  double /* Scale_Factor */)
421 
422 { /* BEGIN Set_Tranverse_Mercator_Parameters */
423  /*
424  * The function Set_Tranverse_Mercator_Parameters receives the ellipsoid
425  * parameters and Tranverse Mercator projection parameters as inputs, and
426  * sets the corresponding state variables. If any errors occur, the error
427  * code(s) are returned by the function, otherwise UTM_NO_ERROR is
428  * returned.
429  *
430  * a : Semi-major axis of ellipsoid, in meters (input)
431  * f : Flattening of ellipsoid (input)
432  * Origin_Latitude : Latitude in radians at the origin of the (input)
433  * projection
434  * Central_Meridian : Longitude in radians at the center of the (input)
435  * projection
436  * False_Easting : Easting/X at the center of the projection (input)
437  * False_Northing : Northing/Y at the center of the projection (input)
438  * Scale_Factor : Projection scale factor (input)
439  */
440 
441  double tn; /* True Meridianal distance constant */
442  double tn2;
443  double tn3;
444  double tn4;
445  double tn5;
446  double dummy_northing;
447  double TranMerc_b; /* Semi-minor axis of ellipsoid, in meters */
448 // double inv_f = 1 / f;
449  ossim_int32 Error_Code = UTM_NO_ERROR;
450 
451 // if (a <= 0.0)
452 // { /* Semi-major axis must be greater than zero */
453 // Error_Code |= UTM_A_ERROR;
454 // }
455 // if ((inv_f < 250) || (inv_f > 350))
456 // { /* Inverse flattening must be between 250 and 350 */
457 // Error_Code |= UTM_INV_F_ERROR;
458 // }
459 // if ((Origin_Latitude < -MAX_LAT) || (Origin_Latitude > MAX_LAT))
460 // { /* origin latitude out of range */
461 // Error_Code |= UTM_ORIGIN_LAT_ERROR;
462 // }
463 // if ((Central_Meridian < -M_PI) || (Central_Meridian > TWO_PI))
464 // { /* origin longitude out of range */
465 // Error_Code |= UTM_CENT_MER_ERROR;
466 // }
467 // if ((Scale_Factor < MIN_SCALE_FACTOR) || (Scale_Factor > MAX_SCALE_FACTOR))
468 // {
469 // Error_Code |= UTM_SCALE_FACTOR_ERROR;
470 // }
471  if (!Error_Code)
472  { /* no errors */
473  theTranMerc_a = a;
474  theTranMerc_f = f;
479  // theTranMerc_Scale_Factor = 1;
480 
481  /* Eccentricity Squared */
483  /* Second Eccentricity Squared */
484  theTranMerc_ebs = (1 / (1 - theTranMerc_es)) - 1;
485 
486  TranMerc_b = theTranMerc_a * (1 - theTranMerc_f);
487  /*True meridianal constants */
488  tn = (theTranMerc_a - TranMerc_b) / (theTranMerc_a + TranMerc_b);
489  tn2 = tn * tn;
490  tn3 = tn2 * tn;
491  tn4 = tn3 * tn;
492  tn5 = tn4 * tn;
493 
494  theTranMerc_ap = theTranMerc_a * (1.e0 - tn + 5.e0 * (tn2 - tn3)/4.e0
495  + 81.e0 * (tn4 - tn5)/64.e0 );
496  theTranMerc_bp = 3.e0 * theTranMerc_a * (tn - tn2 + 7.e0 * (tn3 - tn4)
497  /8.e0 + 55.e0 * tn5/64.e0 )/2.e0;
498  theTranMerc_cp = 15.e0 * theTranMerc_a * (tn2 - tn3 + 3.e0 * (tn4 - tn5 )/4.e0) /16.0;
499  theTranMerc_dp = 35.e0 * theTranMerc_a * (tn3 - tn4 + 11.e0 * tn5 / 16.e0) / 48.e0;
500  theTranMerc_ep = 315.e0 * theTranMerc_a * (tn4 - tn5) / 512.e0;
508  &dummy_northing);
509  theTranMerc_Origin_Lat = Origin_Latitude;
510  if (Central_Meridian > M_PI)
511  Central_Meridian -= TWO_PI;
512  theTranMerc_Origin_Long = Central_Meridian;
513  theTranMerc_False_Northing = False_Northing;
514  theTranMerc_False_Easting = False_Easting;
515  // theTranMerc_Scale_Factor = Scale_Factor;
516  } /* END OF if(!Error_Code) */
517  return (Error_Code);
518 } /* END of Set_Transverse_Mercator_Parameters */
519 
520 
522  double *f,
523  double *Origin_Latitude,
524  double *Central_Meridian,
525  double *False_Easting,
526  double *False_Northing,
527  double *Scale_Factor)const
528 
529 { /* BEGIN Get_Tranverse_Mercator_Parameters */
530  /*
531  * The function Get_Transverse_Mercator_Parameters returns the current
532  * ellipsoid and Transverse Mercator projection parameters.
533  *
534  * a : Semi-major axis of ellipsoid, in meters (output)
535  * f : Flattening of ellipsoid (output)
536  * Origin_Latitude : Latitude in radians at the origin of the (output)
537  * projection
538  * Central_Meridian : Longitude in radians at the center of the (output)
539  * projection
540  * False_Easting : Easting/X at the center of the projection (output)
541  * False_Northing : Northing/Y at the center of the projection (output)
542  * Scale_Factor : Projection scale factor (output)
543  */
544 
545  *a = theTranMerc_a;
546  *f = theTranMerc_f;
547  *Origin_Latitude = theTranMerc_Origin_Lat;
548  *Central_Meridian = theTranMerc_Origin_Long;
549  *False_Easting = theTranMerc_False_Easting;
550  *False_Northing = theTranMerc_False_Northing;
551  *Scale_Factor = theTranMerc_Scale_Factor;
552 
553  return;
554 } /* END OF Get_Tranverse_Mercator_Parameters */
555 
556 
557 
559  double Longitude,
560  double *Easting,
561  double *Northing)const
562 
563 { /* BEGIN Convert_Geodetic_To_Transverse_Mercator */
564 
565  /*
566  * The function Convert_Geodetic_To_Transverse_Mercator converts geodetic
567  * (latitude and longitude) coordinates to Transverse Mercator projection
568  * (easting and northing) coordinates, according to the current ellipsoid
569  * and Transverse Mercator projection coordinates. If any errors occur, the
570  * error code(s) are returned by the function, otherwise UTM_NO_ERROR is
571  * returned.
572  *
573  * Latitude : Latitude in radians (input)
574  * Longitude : Longitude in radians (input)
575  * Easting : Easting/X in meters (output)
576  * Northing : Northing/Y in meters (output)
577  */
578 
579  double c; /* Cosine of latitude */
580  double c2;
581  double c3;
582  double c5;
583  double c7;
584  double dlam; /* Delta longitude - Difference in Longitude */
585  double eta; /* constant - theTranMerc_ebs *c *c */
586  double eta2;
587  double eta3;
588  double eta4;
589  double s; /* Sine of latitude */
590  double sn; /* Radius of curvature in the prime vertical */
591  double t; /* Tangent of latitude */
592  double tan2;
593  double tan3;
594  double tan4;
595  double tan5;
596  double tan6;
597  double t1; /* Term in coordinate conversion formula - GP to Y */
598  double t2; /* Term in coordinate conversion formula - GP to Y */
599  double t3; /* Term in coordinate conversion formula - GP to Y */
600  double t4; /* Term in coordinate conversion formula - GP to Y */
601  double t5; /* Term in coordinate conversion formula - GP to Y */
602  double t6; /* Term in coordinate conversion formula - GP to Y */
603  double t7; /* Term in coordinate conversion formula - GP to Y */
604  double t8; /* Term in coordinate conversion formula - GP to Y */
605  double t9; /* Term in coordinate conversion formula - GP to Y */
606  double tmd; /* True Meridional distance */
607  double tmdo; /* True Meridional distance for latitude of origin */
608  ossim_int32 Error_Code = UTM_NO_ERROR;
609 // double temp_Origin;
610 // double temp_Long;
611 
612 // if ((Latitude < -MAX_LAT) || (Latitude > MAX_LAT))
613 // { /* Latitude out of range */
614 // Error_Code|= UTM_LAT_ERROR;
615 // }
616  if (Longitude > M_PI)
617  Longitude -= TWO_PI;
618 // if ((Longitude < (theTranMerc_Origin_Long - MAX_DELTA_LONG))
619 // || (Longitude > (theTranMerc_Origin_Long + MAX_DELTA_LONG)))
620 // {
621 // if (Longitude < 0)
622 // temp_Long = Longitude + TWO_PI;
623 // else
624 // temp_Long = Longitude;
625 // if (theTranMerc_Origin_Long < 0)
626 // temp_Origin = theTranMerc_Origin_Long + TWO_PI;
627 // else
628 // temp_Origin = theTranMerc_Origin_Long;
629 // if ((temp_Long < (temp_Origin - MAX_DELTA_LONG))
630 // || (temp_Long > (temp_Origin + MAX_DELTA_LONG)))
631 // Error_Code|= UTM_LON_ERROR;
632 // }
633  if (!Error_Code)
634  { /* no errors */
635 
636  /*
637  * Delta Longitude
638  */
639  dlam = Longitude - theTranMerc_Origin_Long;
640 
641 // if (fabs(dlam) > (9.0 * M_PI / 180))
642 // { /* Distortion will result if Longitude is more than 9 degrees from the Central Meridian */
643 // Error_Code |= UTM_LON_WARNING;
644 // }
645 
646  if (dlam > M_PI)
647  dlam -= TWO_PI;
648  if (dlam < -M_PI)
649  dlam += TWO_PI;
650  if (fabs(dlam) < 2.e-10)
651  dlam = 0.0;
652 
653  s = sin(Latitude);
654  c = cos(Latitude);
655  c2 = c * c;
656  c3 = c2 * c;
657  c5 = c3 * c2;
658  c7 = c5 * c2;
659  t = tan (Latitude);
660  tan2 = t * t;
661  tan3 = tan2 * t;
662  tan4 = tan3 * t;
663  tan5 = tan4 * t;
664  tan6 = tan5 * t;
665  eta = theTranMerc_ebs * c2;
666  eta2 = eta * eta;
667  eta3 = eta2 * eta;
668  eta4 = eta3 * eta;
669 
670  /* radius of curvature in prime vertical */
671  sn = SPHSN(Latitude);
672 
673  /* True Meridianal Distances */
674  tmd = SPHTMD(Latitude);
675 
676  /* Origin */
678 
679  /* northing */
680  t1 = (tmd - tmdo) * theTranMerc_Scale_Factor;
681  t2 = sn * s * c * theTranMerc_Scale_Factor/ 2.e0;
682  t3 = sn * s * c3 * theTranMerc_Scale_Factor * (5.e0 - tan2 + 9.e0 * eta
683  + 4.e0 * eta2) /24.e0;
684 
685  t4 = sn * s * c5 * theTranMerc_Scale_Factor * (61.e0 - 58.e0 * tan2
686  + tan4 + 270.e0 * eta - 330.e0 * tan2 * eta + 445.e0 * eta2
687  + 324.e0 * eta3 -680.e0 * tan2 * eta2 + 88.e0 * eta4
688  -600.e0 * tan2 * eta3 - 192.e0 * tan2 * eta4) / 720.e0;
689 
690  t5 = sn * s * c7 * theTranMerc_Scale_Factor * (1385.e0 - 3111.e0 *
691  tan2 + 543.e0 * tan4 - tan6) / 40320.e0;
692 
693  *Northing = theTranMerc_False_Northing + t1 + pow(dlam,2.e0) * t2
694  + pow(dlam,4.e0) * t3 + pow(dlam,6.e0) * t4
695  + pow(dlam,8.e0) * t5;
696 
697  /* Easting */
698  t6 = sn * c * theTranMerc_Scale_Factor;
699  t7 = sn * c3 * theTranMerc_Scale_Factor * (1.e0 - tan2 + eta ) /6.e0;
700  t8 = sn * c5 * theTranMerc_Scale_Factor * (5.e0 - 18.e0 * tan2 + tan4
701  + 14.e0 * eta - 58.e0 * tan2 * eta + 13.e0 * eta2 + 4.e0 * eta3
702  - 64.e0 * tan2 * eta2 - 24.e0 * tan2 * eta3 )/ 120.e0;
703  t9 = sn * c7 * theTranMerc_Scale_Factor * ( 61.e0 - 479.e0 * tan2
704  + 179.e0 * tan4 - tan6 ) /5040.e0;
705 
706  *Easting = theTranMerc_False_Easting + dlam * t6 + pow(dlam,3.e0) * t7
707  + pow(dlam,5.e0) * t8 + pow(dlam,7.e0) * t9;
708  }
709  return (Error_Code);
710 } /* END OF Convert_Geodetic_To_Transverse_Mercator */
711 
712 
714  double Northing,
715  double *Latitude,
716  double *Longitude)const
717 { /* BEGIN Convert_Transverse_Mercator_To_Geodetic */
718 
719  /*
720  * The function Convert_Transverse_Mercator_To_Geodetic converts Transverse
721  * Mercator projection (easting and northing) coordinates to geodetic
722  * (latitude and longitude) coordinates, according to the current ellipsoid
723  * and Transverse Mercator projection parameters. If any errors occur, the
724  * error code(s) are returned by the function, otherwise UTM_NO_ERROR is
725  * returned.
726  *
727  * Easting : Easting/X in meters (input)
728  * Northing : Northing/Y in meters (input)
729  * Latitude : Latitude in radians (output)
730  * Longitude : Longitude in radians (output)
731  */
732 
733  double c; /* Cosine of latitude */
734  double de; /* Delta easting - Difference in Easting (Easting-Fe) */
735  double dlam; /* Delta longitude - Difference in Longitude */
736  double eta; /* constant - theTranMerc_ebs *c *c */
737  double eta2;
738  double eta3;
739  double eta4;
740  double ftphi; /* Footpoint latitude */
741  int i; /* Loop iterator */
742  /*double s; Sine of latitude */
743  double sn; /* Radius of curvature in the prime vertical */
744  double sr; /* Radius of curvature in the meridian */
745  double t; /* Tangent of latitude */
746  double tan2;
747  double tan4;
748  double t10; /* Term in coordinate conversion formula - GP to Y */
749  double t11; /* Term in coordinate conversion formula - GP to Y */
750  double t12; /* Term in coordinate conversion formula - GP to Y */
751  double t13; /* Term in coordinate conversion formula - GP to Y */
752  double t14; /* Term in coordinate conversion formula - GP to Y */
753  double t15; /* Term in coordinate conversion formula - GP to Y */
754  double t16; /* Term in coordinate conversion formula - GP to Y */
755  double t17; /* Term in coordinate conversion formula - GP to Y */
756  double tmd; /* True Meridional distance */
757  double tmdo; /* True Meridional distance for latitude of origin */
758  ossim_int32 Error_Code = UTM_NO_ERROR;
759 
760 // if ((Easting < (theTranMerc_False_Easting - theTranMerc_Delta_Easting))
761 // ||(Easting > (theTranMerc_False_Easting + theTranMerc_Delta_Easting)))
762 // { /* Easting out of range */
763 // Error_Code |= UTM_EASTING_ERROR;
764 // }
765 // if ((Northing < (theTranMerc_False_Northing - theTranMerc_Delta_Northing))
766 // || (Northing > (theTranMerc_False_Northing + theTranMerc_Delta_Northing)))
767 // { /* Northing out of range */
768 // Error_Code |= UTM_NORTHING_ERROR;
769 // }
770 
771  if (!Error_Code)
772  {
773  /* True Meridional Distances for latitude of origin */
775 
776  /* Origin */
777  tmd = tmdo + (Northing - theTranMerc_False_Northing) / theTranMerc_Scale_Factor;
778 
779  /* First Estimate */
780  sr = SPHSR(0.e0);
781  ftphi = tmd/sr;
782 
783  for (i = 0; i < 5 ; i++)
784  {
785  t10 = SPHTMD (ftphi);
786  sr = SPHSR(ftphi);
787  ftphi = ftphi + (tmd - t10) / sr;
788  }
789 
790  /* Radius of Curvature in the meridian */
791  sr = SPHSR(ftphi);
792 
793  /* Radius of Curvature in the meridian */
794  sn = SPHSN(ftphi);
795 
796  /* Sine Cosine terms */
797  // s = sin(ftphi);
798  c = cos(ftphi);
799 
800  /* Tangent Value */
801  t = tan(ftphi);
802  tan2 = t * t;
803  tan4 = tan2 * tan2;
804  eta = theTranMerc_ebs * pow(c,2);
805  eta2 = eta * eta;
806  eta3 = eta2 * eta;
807  eta4 = eta3 * eta;
808  de = Easting - theTranMerc_False_Easting;
809  if (fabs(de) < 0.0001)
810  de = 0.0;
811 
812  /* Latitude */
813  t10 = t / (2.e0 * sr * sn * pow(theTranMerc_Scale_Factor, 2));
814  t11 = t * (5.e0 + 3.e0 * tan2 + eta - 4.e0 * pow(eta,2)
815  - 9.e0 * tan2 * eta) / (24.e0 * sr * pow(sn,3)
816  * pow(theTranMerc_Scale_Factor,4));
817  t12 = t * (61.e0 + 90.e0 * tan2 + 46.e0 * eta + 45.E0 * tan4
818  - 252.e0 * tan2 * eta - 3.e0 * eta2 + 100.e0
819  * eta3 - 66.e0 * tan2 * eta2 - 90.e0 * tan4
820  * eta + 88.e0 * eta4 + 225.e0 * tan4 * eta2
821  + 84.e0 * tan2* eta3 - 192.e0 * tan2 * eta4)
822  / ( 720.e0 * sr * pow(sn,5) * pow(theTranMerc_Scale_Factor, 6) );
823  t13 = t * ( 1385.e0 + 3633.e0 * tan2 + 4095.e0 * tan4 + 1575.e0
824  * pow(t,6))/ (40320.e0 * sr * pow(sn,7) * pow(theTranMerc_Scale_Factor,8));
825  *Latitude = ftphi - pow(de,2) * t10 + pow(de,4) * t11 - pow(de,6) * t12
826  + pow(de,8) * t13;
827 
828  t14 = 1.e0 / (sn * c * theTranMerc_Scale_Factor);
829 
830  t15 = (1.e0 + 2.e0 * tan2 + eta) / (6.e0 * pow(sn,3) * c *
831  pow(theTranMerc_Scale_Factor,3));
832 
833  t16 = (5.e0 + 6.e0 * eta + 28.e0 * tan2 - 3.e0 * eta2
834  + 8.e0 * tan2 * eta + 24.e0 * tan4 - 4.e0
835  * eta3 + 4.e0 * tan2 * eta2 + 24.e0
836  * tan2 * eta3) / (120.e0 * pow(sn,5) * c
837  * pow(theTranMerc_Scale_Factor,5));
838 
839  t17 = (61.e0 + 662.e0 * tan2 + 1320.e0 * tan4 + 720.e0
840  * pow(t,6)) / (5040.e0 * pow(sn,7) * c
841  * pow(theTranMerc_Scale_Factor,7));
842 
843  /* Difference in Longitude */
844  dlam = de * t14 - pow(de,3) * t15 + pow(de,5) * t16 - pow(de,7) * t17;
845 
846  /* Longitude */
847  (*Longitude) = theTranMerc_Origin_Long + dlam;
848  while (*Latitude > (90.0 * RAD_PER_DEG))
849  {
850  *Latitude = M_PI - *Latitude;
851  *Longitude += M_PI;
852  if (*Longitude > M_PI)
853  *Longitude -= TWO_PI;
854  }
855 
856  while (*Latitude < (-90.0 * RAD_PER_DEG))
857  {
858  *Latitude = - (*Latitude + M_PI);
859  *Longitude += M_PI;
860  if (*Longitude > M_PI)
861  *Longitude -= TWO_PI;
862  }
863  if (*Longitude > TWO_PI)
864  *Longitude -= TWO_PI;
865  if (*Longitude < -M_PI)
866  *Longitude += TWO_PI;
867 
868 // if (fabs(dlam) > (9.0 * M_PI / 180))
869 // { /* Distortion will result if Longitude is more than 9 degrees from the Central Meridian */
870 // Error_Code |= UTM_LON_WARNING;
871 // }
872  }
873  return (Error_Code);
874 } /* END OF Convert_Transverse_Mercator_To_Geodetic */
875 
877 {
878  out << setiosflags(ios::fixed) << setprecision(15)
879  << "// ossimUtmProjection::print"
880  << "\ntheZone: " << theZone
881  << "\ntheHemisphere: " << theHemisphere
882  << endl;
883  return ossimMapProjection::print(out);
884 }
885 
887 {
889 }
890 
892 {
894 }
895 
896 //*************************************************************************************************
898 //*************************************************************************************************
900 {
901  bool result = false;
902  if ( this == &proj )
903  {
904  result = true; // Pointer addresses the same.
905  }
906  else
907  {
908  //---
909  // Check our stuff first. No sense going onto ossimMapProjection::operator==
910  // if we are not a utm projection.
911  //---
912  const ossimUtmProjection* p = dynamic_cast<const ossimUtmProjection*>(&proj);
913  if ( p )
914  {
915  if ( theZone == p->theZone )
916  {
917  if ( theHemisphere == p->theHemisphere )
918  {
919  result = ossimMapProjection::operator==(proj);
920  }
921  }
922  }
923  }
924  return result;
925 }
926 
928 {
929  // Always recompute in case origin, zone, or hemisphere were changed.
931 }
932 
ossim_uint32 getCodeFromUtmProj(const ossimUtmProjection *proj) const
Given UTM projection, derives the associated EPSG code. This is faster than a Db lookup.
virtual ossimGpt inverse(const ossimDpt &eastingNorthing) const
Will take a point in meters and convert it to ground.
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
virtual ossim_uint32 getPcsCode() const
Returns the EPSG PCS code based on datum, zone, and hemisphere.
virtual std::ostream & print(std::ostream &out) const
Prints data members to stream.
static ossimString upcase(const ossimString &aString)
Definition: ossimString.cpp:34
virtual double getFalseEasting() const
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
double lond() const
Will convert the radian measure to degrees.
Definition: ossimGpt.h:97
ossim_int32 Convert_Transverse_Mercator_To_Geodetic(double Easting, double Northing, double *Latitude, double *Longitude) const
The function Convert_Transverse_Mercator_To_Geodetic converts Transverse Mercator projection (easting...
#define DEG_PER_RAD
#define SPHTMD(Latitude)
Represents serializable keyword/value map.
const char * find(const char *key) const
double y
Definition: ossimDpt.h:165
virtual void setOrigin(const ossimGpt &origin)
Sets theOrigin to origin.
virtual const ossimString & code() const
Definition: ossimDatum.h:57
virtual void setOrigin(const ossimGpt &origin)
This will set the utm zone and utm origin base on origin passed in.
#define SPHSN(Latitude)
double latd() const
Will convert the radian measure to degrees.
Definition: ossimGpt.h:87
void changeDatum(const ossimDatum *datum)
This will actually perform a shift.
Definition: ossimGpt.cpp:316
virtual ossimDpt forward(const ossimGpt &latLon) const
All map projections will convert the world coordinate to an easting northing (Meters).
const ossimDatum * datum() const
datum().
Definition: ossimGpt.h:196
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
static const char * ZONE_KW
void Get_Transverse_Mercator_Parameters(double *a, double *f, double *Origin_Latitude, double *Central_Meridian, double *False_Easting, double *False_Northing, double *Scale_Factor) const
The function Get_Transverse_Mercator_Parameters returns the current ellipsoid and Transverse Mercator...
#define M_PI
virtual bool operator==(const ossimProjection &projection) const
Compares this to arg projection and returns TRUE if the same.
static ossimEpsgProjectionDatabase * instance()
Instantiates singleton instance of this class:
const double & getA() const
virtual ossimGpt origin() const
double lonr() const
Returns the longitude in radian measure.
Definition: ossimGpt.h:76
unsigned int ossim_uint32
ossimString trim(const ossimString &valueToTrim=ossimString(" \\)) const
this will strip lead and trailing character passed in.
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
#define SPHSR(Latitude)
virtual double getFalseNorthing() const
static ossim_int32 computeZone(const ossimGpt &gpt)
#define MAX_DELTA_LONG
ossim_int32 theZone
zone can be from 1 through 60 (0 == NOT SET)
void setZone(const ossimGpt &ground)
#define UTM_NO_ERROR
static const char * HEMISPHERE_KW
double x
Definition: ossimDpt.h:164
#define TWO_PI
double latr() const
latr().
Definition: ossimGpt.h:66
const char * c_str() const
Returns a pointer to a null-terminated array of characters representing the string&#39;s contents...
Definition: ossimString.h:396
ossim_int32 getZone() const
ossim_int32 Convert_Geodetic_To_Transverse_Mercator(double Latitude, double Longitude, double *Easting, double *Northing) const
The function Convert_Geodetic_To_Transverse_Mercator converts geodetic (latitude and longitude) coord...
const double & getFlattening() const
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
ossimUtmProjection(const ossimEllipsoid &ellipsoid=ossimEllipsoid(), const ossimGpt &origin=ossimGpt())
char theHemisphere
can be N or S.
ossimEllipsoid theEllipsoid
This method verifies that the projection parameters match the current pcs code.
#define RTTI_DEF1(cls, name, b1)
Definition: ossimRtti.h:485
ossimDpt theFalseEastingNorthing
Hold the false easting northing.
static double computeZoneMeridian(ossim_int32 zone)
Return in decimal degrees the zone meridian.
void setHemisphere(const ossimGpt &ground)
virtual std::ostream & print(std::ostream &out) const
Prints data members to stream.
#define MAX_LAT
#define RAD_PER_DEG
virtual bool operator==(const ossimProjection &projection) const
Returns TRUE if principal parameters are within epsilon tolerance.
virtual ossimObject * dup() const
std::basic_ostream< char > ostream
Base class for char output streams.
Definition: ossimIosFwd.h:23
int ossim_int32
ossim_int32 Set_Transverse_Mercator_Parameters(double a, double f, double Origin_Latitude, double Central_Meridian, double False_Easting, double False_Northing, double Scale_Factor)
The function Set_Tranverse_Mercator_Parameters receives the ellipsoid parameters and Tranverse Mercat...
const ossimDatum * theDatum
This is only set if we want to have built in datum shifting.