OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimObliqueMercatorProjection.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 // Copyright (C) 2000 ImageLinks Inc.
3 //
4 // License: See top LICENSE.txt file.
5 //
6 // Author: Garrett Potts
7 //
8 //*******************************************************************
9 // $Id: ossimObliqueMercatorProjection.cpp 17815 2010-08-03 13:23:14Z dburken $
12 
13 #define OMERC_NO_ERROR 0x0000
14 #define OMERC_LAT_ERROR 0x0001
15 #define OMERC_LON_ERROR 0x0002
16 #define OMERC_ORIGIN_LAT_ERROR 0x0004
17 #define OMERC_LAT1_ERROR 0x0008
18 #define OMERC_LAT2_ERROR 0x0010
19 #define OMERC_LON1_ERROR 0x0020
20 #define OMERC_LON2_ERROR 0x0040
21 #define OMERC_LAT1_LAT2_ERROR 0x0080
22 #define OMERC_DIFF_HEMISPHERE_ERROR 0x0100
23 #define OMERC_EASTING_ERROR 0x0200
24 #define OMERC_NORTHING_ERROR 0x0400
25 #define OMERC_A_ERROR 0x0800
26 #define OMERC_INV_F_ERROR 0x1000
27 #define OMERC_SCALE_FACTOR_ERROR 0x2000
28 #define OMERC_LON_WARNING 0x4000
29 
30 RTTI_DEF1(ossimObliqueMercatorProjection, "ossimObliqueMercatorProjection", ossimMapProjection)
31 
32 #ifndef PI_OVER_2
33 # define PI_OVER_2 ( M_PI / 2.0)
34 #endif
35 #ifndef PI_OVER_4
36 # define PI_OVER_4 ( M_PI / 4.0)
37 #endif
38 #ifndef TWO_PI
39 # define TWO_PI (2.0 * M_PI)
40 #endif
41 #define MIN_SCALE_FACTOR 0.3
42 #define MAX_SCALE_FACTOR 3.0
43 
44 #define OMERC_t(lat, e_sinlat, e_over_2) (tan(PI_OVER_4 - lat / 2.0)) / \
45  (pow((1 - e_sinlat) / (1 + e_sinlat), e_over_2))
46 
47 
49  const ossimGpt& origin)
50  : ossimMapProjection(ellipsoid, origin)
51 {
52  setDefaults();
53  update();
54 }
55 
57  const ossimGpt& origin,
58  const ossimGpt& point1,
59  const ossimGpt& point2,
60  double falseEasting,
61  double falseNorthing,
62  double scaleFactor)
63  : ossimMapProjection(ellipsoid, origin)
64 {
65  setParameters(point1, point2, falseEasting, falseNorthing, scaleFactor);
66 }
67 
69 {
72  theOrigin.latr(),
80 
83 
85 }
86 
88 {
89  OMerc_False_Easting = falseEasting;
90  update();
91 }
92 
94 {
95  OMerc_False_Northing = falseNorthing;
96  update();
97 }
98 
99 void ossimObliqueMercatorProjection::setFalseEastingNorthing(double falseEasting, double falseNorthing)
100 {
101  OMerc_False_Easting = falseEasting;
102  OMerc_False_Northing = falseNorthing;
103  update();
104 
105 }
106 
108 {
109  theCentralPoint1 = point;
110 
111  update();
112 }
113 
115 {
116  theCentralPoint2 = point;
117  update();
118 }
119 
121 {
122  OMerc_Scale_Factor = scaleFactor;
123  update();
124 }
125 
127  const ossimGpt& point2,
128  double falseEasting,
129  double falseNorthing,
130  double scaleFactor)
131 {
132  theCentralPoint1 = point1;
133  theCentralPoint2 = point2;
134  OMerc_False_Easting = falseEasting;
135  OMerc_False_Northing = falseNorthing;
136  OMerc_Scale_Factor = scaleFactor;
137 
138  update();
139 }
140 
142 {
143  // initialize the central points to be 5 degrees about the origin.
144  OMerc_Delta_Northing = 40000000.0;
145  OMerc_Delta_Easting = 40000000.0;
146 
151 
152  theCentralPoint1.clampLat(-90.0, 90.0);
153  theCentralPoint1.clampLon(-180.0, 180.0);
154  theCentralPoint2.clampLat(-90.0, 90.0);
155  theCentralPoint2.clampLon(-180.0, 180.0);
156 
157  OMerc_False_Easting = 0.0;
158  OMerc_False_Northing = 0.0;
159 
160  OMerc_Scale_Factor = 1.0;
161 }
162 
163 
165 {
166  double lat = 0.0;
167  double lon = 0.0;
168 
169  Convert_Oblique_Mercator_To_Geodetic(eastingNorthing.x,
170  eastingNorthing.y,
171  &lat,
172  &lon);
173 
174  return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum);
175 }
176 
178 {
179  double easting = 0.0;
180  double northing = 0.0;
181  ossimGpt gpt = latLon;
182 
183  if (theDatum)
184  {
185  if (theDatum->code() != latLon.datum()->code())
186  {
187  gpt.changeDatum(theDatum); // Shift to our datum.
188  }
189  }
190 
192  gpt.lonr(),
193  &easting,
194  &northing);
195  return ossimDpt(easting, northing);
196 }
197 
199 {
200  kwl.add(prefix,
203  true);
204 
205  kwl.add(prefix,
208  true);
209 
210  kwl.add(prefix,
213  true);
214 
215  kwl.add(prefix,
218  true);
219 
220  kwl.add(prefix,
223  true);
224 
225 
226  return ossimMapProjection::saveState(kwl, prefix);
227 }
228 
230  const char* prefix)
231 {
232  bool flag = ossimMapProjection::loadState(kwl, prefix);
233  const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
234  const char* point1Lat = kwl.find(prefix, ossimKeywordNames::CENTRAL_POINT1_LAT_KW);
235  const char* point1Lon = kwl.find(prefix, ossimKeywordNames::CENTRAL_POINT1_LON_KW);
236  const char* point2Lat = kwl.find(prefix, ossimKeywordNames::CENTRAL_POINT2_LAT_KW);
237  const char* point2Lon = kwl.find(prefix, ossimKeywordNames::CENTRAL_POINT2_LON_KW);
238  const char* scale = kwl.find(prefix, ossimKeywordNames::SCALE_FACTOR_KW);
239 
240  setDefaults();
241 
243  {
246 
247  if(point1Lat&&point1Lon&&point2Lat&&point2Lon)
248  {
249  theCentralPoint1.latd(ossimString(point1Lat).toDouble());
250  theCentralPoint1.lond(ossimString(point1Lon).toDouble());
251  theCentralPoint2.latd(ossimString(point2Lat).toDouble());
252  theCentralPoint2.lond(ossimString(point2Lon).toDouble());
253  }
254  if(scale)
255  {
257  }
258  }
259 
260  update();
261 
262  return flag;
263 
264 }
265 
266 /*
267  * FUNCTIONS
268  */
269 
271  double f,
272  double Origin_Latitude,
273  double Latitude_1,
274  double Longitude_1,
275  double Latitude_2,
276  double Longitude_2,
277  double False_Easting,
278  double False_Northing,
279  double Scale_Factor)
280 { /* BEGIN Set_Oblique_Mercator_Parameters */
281 /*
282  * The function Set_Oblique_Mercator_Parameters receives the ellipsoid parameters and
283  * projection parameters as inputs, and sets the corresponding state
284  * variables. If any errors occur, the error code(s) are returned by the function,
285  * otherwise OMERC_NO_ERROR is returned.
286  *
287  * a : Semi-major axis of ellipsoid, in meters (input)
288  * f : Flattening of ellipsoid (input)
289  * Origin_Latitude : Latitude, in radians, at which the (input)
290  * point scale factor is 1.0
291  * Latitude_1 : Latitude, in radians, of first point lying on
292  * central line (input)
293  * Longitude_1 : Longitude, in radians, of first point lying on
294  * central line (input)
295  * Latitude_2 : Latitude, in radians, of second point lying on
296  * central line (input)
297  * Longitude_2 : Longitude, in radians, of second point lying on
298  * central line (input)
299  * False_Easting : A coordinate value, in meters, assigned to the
300  * central meridian of the projection (input)
301  * False_Northing : A coordinate value, in meters, assigned to the
302  * origin latitude of the projection (input)
303  * Scale_Factor : Multiplier which reduces distances in the
304  * projection to the actual distance on the
305  * ellipsoid (input)
306  */
307 
308 // double inv_f = 1 / f;
309  double es2, one_MINUS_es2;
310  double cos_olat, cos_olat2;
311  double sin_olat, sin_olat2, es2_sin_olat2;
312  double t0, t1, t2;
313  double D, D2, D2_MINUS_1, sqrt_D2_MINUS_1;
314  double H, L, LH;
315  double E2;
316  double F, G, J, P;
317  double dlon;
318  long Error_Code = OMERC_NO_ERROR;
319 
320 // if (a <= 0.0)
321 // { /* Semi-major axis must be greater than zero */
322 // Error_Code |= OMERC_A_ERROR;
323 // }
324 // if ((inv_f < 250) || (inv_f > 350))
325 // { /* Inverse flattening must be between 250 and 350 */
326 // Error_Code |= OMERC_INV_F_ERROR;
327 // }
328 // if ((Origin_Latitude <= -PI_OVER_2) || (Origin_Latitude >= PI_OVER_2))
329 // { /* origin latitude out of range - can not be at a pole */
330 // Error_Code |= OMERC_ORIGIN_LAT_ERROR;
331 // }
332 // if ((Latitude_1 <= -PI_OVER_2) || (Latitude_1 >= PI_OVER_2))
333 // { /* first latitude out of range - can not be at a pole */
334 // Error_Code |= OMERC_LAT1_ERROR;
335 // }
336 // if ((Latitude_2 <= -PI_OVER_2) || (Latitude_2 >= PI_OVER_2))
337 // { /* second latitude out of range - can not be at a pole */
338 // Error_Code |= OMERC_LAT2_ERROR;
339 // }
340 // if (Latitude_1 == 0.0)
341 // { /* first latitude can not be at the equator */
342 // Error_Code |= OMERC_LAT1_ERROR;
343 // }
344 // if (Latitude_1 == Latitude_2)
345 // { /* first and second latitudes can not be equal */
346 // Error_Code |= OMERC_LAT1_LAT2_ERROR;
347 // }
348 // if (((Latitude_1 < 0.0) && (Latitude_2 > 0.0)) ||
349 // ((Latitude_1 > 0.0) && (Latitude_2 < 0.0)))
350 // { /*first and second points can not be in different hemispheres */
351 // Error_Code |= OMERC_DIFF_HEMISPHERE_ERROR;
352 // }
353 // if ((Longitude_1 < -PI) || (Longitude_1 > TWO_PI))
354 // { /* first longitude out of range */
355 // Error_Code |= OMERC_LON1_ERROR;
356 // }
357 // if ((Longitude_2 < -PI) || (Longitude_2 > TWO_PI))
358 // { /* first longitude out of range */
359 // Error_Code |= OMERC_LON2_ERROR;
360 // }
361 // if ((Scale_Factor < MIN_SCALE_FACTOR) || (Scale_Factor > MAX_SCALE_FACTOR))
362 // { /* scale factor out of range */
363 // Error_Code |= OMERC_SCALE_FACTOR_ERROR;
364 // }
365  if (!Error_Code)
366  { /* no errors */
367 
368  OMerc_a = a;
369  OMerc_f = f;
370  OMerc_Origin_Lat = Origin_Latitude;
371  OMerc_Lat_1 = Latitude_1;
372  OMerc_Lat_2 = Latitude_2;
373  OMerc_Lon_1 = Longitude_1;
374  OMerc_Lon_2 = Longitude_2;
375  OMerc_Scale_Factor = Scale_Factor;
376  OMerc_False_Northing = False_Northing;
377  OMerc_False_Easting = False_Easting;
378 
379  es2 = 2 * OMerc_f - OMerc_f * OMerc_f;
380  es = sqrt(es2);
381  one_MINUS_es2 = 1 - es2;
382  es_OVER_2 = es / 2.0;
383 
384  cos_olat = cos(OMerc_Origin_Lat);
385  cos_olat2 = cos_olat * cos_olat;
386  sin_olat = sin(OMerc_Origin_Lat);
387  sin_olat2 = sin_olat * sin_olat;
388  es2_sin_olat2 = es2 * sin_olat2;
389 
390  OMerc_B = sqrt(1 + (es2 * cos_olat2 * cos_olat2) / one_MINUS_es2);
391  OMerc_A = (OMerc_a * OMerc_B * OMerc_Scale_Factor * sqrt(one_MINUS_es2)) / (1.0 - es2_sin_olat2);
394 
395  t0 = OMERC_t(OMerc_Origin_Lat, es * sin_olat, es_OVER_2);
396  t1 = OMERC_t(OMerc_Lat_1, es * sin(OMerc_Lat_1), es_OVER_2);
397  t2 = OMERC_t(OMerc_Lat_2, es * sin(OMerc_Lat_2), es_OVER_2);
398 
399  D = (OMerc_B * sqrt(one_MINUS_es2)) / (cos_olat * sqrt(1.0 - es2_sin_olat2));
400  D2 = D * D;
401  if (D2 < 1.0)
402  D2 = 1.0;
403  D2_MINUS_1 = D2 - 1.0;
404  sqrt_D2_MINUS_1 = sqrt(D2_MINUS_1);
405  if (D2_MINUS_1 > 1.0e-10)
406  {
407  if (OMerc_Origin_Lat >= 0.0)
408  OMerc_E = (D + sqrt_D2_MINUS_1) * pow(t0, OMerc_B);
409  else
410  OMerc_E = (D - sqrt_D2_MINUS_1) * pow(t0, OMerc_B);
411  }
412  else
413  OMerc_E = D * pow(t0, OMerc_B);
414  H = pow(t1, OMerc_B);
415  L = pow(t2, OMerc_B);
416  F = OMerc_E / H;
417  G = (F - 1.0 / F) / 2.0;
418  E2 = OMerc_E * OMerc_E;
419  LH = L * H;
420  J = (E2 - LH) / (E2 + LH);
421  P = (L - H) / (L + H);
422 
423  dlon = OMerc_Lon_1 - OMerc_Lon_2;
424  if (dlon < -M_PI )
425  OMerc_Lon_2 -= TWO_PI;
426  if (dlon > M_PI)
427  OMerc_Lon_2 += TWO_PI;
428  dlon = OMerc_Lon_1 - OMerc_Lon_2;
429  OMerc_Origin_Long = (OMerc_Lon_1 + OMerc_Lon_2) / 2.0 - (atan(J * tan(OMerc_B * dlon / 2.0) / P)) / OMerc_B;
430 
432 // if (dlon < -M_PI )
433 // OMerc_Origin_Long -= TWO_PI;
434 // if (dlon > M_PI)
435 // OMerc_Origin_Long += TWO_PI;
436 
438  OMerc_gamma = atan(sin(OMerc_B * dlon) / G);
439  cos_gamma = cos(OMerc_gamma);
440  sin_gamma = sin(OMerc_gamma);
441 
442  OMerc_azimuth = asin(D * sin_gamma);
443  cos_azimuth = cos(OMerc_azimuth);
444  sin_azimuth = sin(OMerc_azimuth);
445 
446  if (OMerc_Origin_Lat >= 0)
447  OMerc_u = A_over_B * atan(sqrt_D2_MINUS_1/cos_azimuth);
448  else
449  OMerc_u = -A_over_B * atan(sqrt_D2_MINUS_1/cos_azimuth);
450 
451  } /* End if(!Error_Code) */
452  return (Error_Code);
453 } /* End Set_Oblique_Mercator_Parameters */
454 
456  double *f,
457  double *Origin_Latitude,
458  double *Latitude_1,
459  double *Longitude_1,
460  double *Latitude_2,
461  double *Longitude_2,
462  double *False_Easting,
463  double *False_Northing,
464  double *Scale_Factor)const
465 { /* Begin Get_Oblique_Mercator_Parameters */
466 /*
467  * The function Get_Oblique_Mercator_Parameters returns the current ellipsoid
468  * parameters and Oblique Mercator projection parameters.
469  *
470  * a : Semi-major axis of ellipsoid, in meters (output)
471  * f : Flattening of ellipsoid (output)
472  * Origin_Latitude : Latitude, in radians, at which the (output)
473  * point scale factor is 1.0
474  * Latitude_1 : Latitude, in radians, of first point lying on
475  * central line (output)
476  * Longitude_1 : Longitude, in radians, of first point lying on
477  * central line (output)
478  * Latitude_2 : Latitude, in radians, of second point lying on
479  * central line (output)
480  * Longitude_2 : Longitude, in radians, of second point lying on
481  * central line (output)
482  * False_Easting : A coordinate value, in meters, assigned to the
483  * central meridian of the projection (output)
484  * False_Northing : A coordinate value, in meters, assigned to the
485  * origin latitude of the projection (output)
486  * Scale_Factor : Multiplier which reduces distances in the
487  * projection to the actual distance on the
488  * ellipsoid (output)
489  */
490 
491  *a = OMerc_a;
492  *f = OMerc_f;
493  *Origin_Latitude = OMerc_Origin_Lat;
494  *Latitude_1 = OMerc_Lat_1;
495  *Longitude_1 = OMerc_Lon_1;
496  *Latitude_2 = OMerc_Lat_2;
497  *Longitude_2 = OMerc_Lon_2;
498  *Scale_Factor = OMerc_Scale_Factor;
499  *False_Easting = OMerc_False_Easting;
500  *False_Northing = OMerc_False_Northing;
501 
502  return;
503 } /* End Get_Azimuthal_Equidistant_Parameters */
504 
506  double Longitude,
507  double *Easting,
508  double *Northing)const
509 { /* BEGIN Convert_Geodetic_To_Oblique_Mercator */
510 /*
511  * The function Convert_Geodetic_To_Oblique_Mercator converts geodetic (latitude and
512  * longitude) coordinates to Oblique Mercator projection (easting and
513  * northing) coordinates, according to the current ellipsoid and Oblique Mercator
514  * projection parameters. If any errors occur, the error code(s) are returned
515  * by the function, otherwise OMERC_NO_ERROR is returned.
516  *
517  * Latitude : Latitude (phi), in radians (input)
518  * Longitude : Longitude (lambda), in radians (input)
519  * Easting : Easting (X), in meters (output)
520  * Northing : Northing (Y), in meters (output)
521  */
522 
523  double dlam, B_dlam, cos_B_dlam;
524  double t, S, T, V, U;
525  double Q, Q_inv;
526  /* Coordinate axes defined with respect to the azimuth of the center line */
527  /* Natural origin*/
528  double v = 0;
529  double u = 0;
530  long Error_Code = OMERC_NO_ERROR;
531 
532 // if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2))
533 // { /* Latitude out of range */
534 // Error_Code |= OMERC_LAT_ERROR;
535 // }
536 // if ((Longitude < -M_PI) || (Longitude > TWO_PI))
537 // { /* Longitude out of range */
538 // Error_Code |= OMERC_LON_ERROR;
539 // }
540  if (!Error_Code)
541  { /* no errors */
542  dlam = Longitude - OMerc_Origin_Long;
543 
544 // if (fabs(dlam) >= PI_OVER_2)
545 // { /* Distortion will result if Longitude is 90 degrees or more from the Central Meridian */
546 // Error_Code |= OMERC_LON_WARNING;
547 // }
548 
549 // if (dlam > M_PI)
550 // {
551 // dlam -= TWO_PI;
552 // }
553 // if (dlam < -M_PI)
554 // {
555 // dlam += TWO_PI;
556 // }
557 
558  if (fabs(fabs(Latitude) - PI_OVER_2) > 1.0e-10)
559  {
560  t = OMERC_t(Latitude, es * sin(Latitude), es_OVER_2);
561  Q = OMerc_E / pow(t, OMerc_B);
562  Q_inv = 1.0 / Q;
563  S = (Q - Q_inv) / 2.0;
564  T = (Q + Q_inv) / 2.0;
565  B_dlam = OMerc_B * dlam;
566  V = sin(B_dlam);
567  U = ((-1.0 * V * cos_gamma) + (S * sin_gamma)) / T;
568  if (fabs(fabs(U) - 1.0) < 1.0e-10)
569  { /* Point projects into infinity */
570  Error_Code |= OMERC_LON_ERROR;
571  }
572  else
573  {
574  v = A_over_B * log((1.0 - U) / (1.0 + U)) / 2.0;
575  cos_B_dlam = cos(B_dlam);
576  if (fabs(cos_B_dlam) < 1.0e-10)
577  u = OMerc_A * B_dlam;
578  else
579  u = A_over_B * atan(((S * cos_gamma) + (V * sin_gamma)) / cos_B_dlam);
580  }
581  }
582  else
583  {
584  if (Latitude > 0.0)
585  v = A_over_B * log(tan(PI_OVER_4 - (OMerc_gamma / 2.0)));
586  else
587  v = A_over_B * log(tan(PI_OVER_4 + (OMerc_gamma / 2.0)));
588  u = A_over_B * Latitude;
589  }
590 
591 
592  u = u - OMerc_u;
593 
594  *Easting = OMerc_False_Easting + v * cos_azimuth + u * sin_azimuth;
595  *Northing = OMerc_False_Northing + u * cos_azimuth - v * sin_azimuth;
596 
597  }
598  return (Error_Code);
599 } /* End Convert_Geodetic_To_Oblique_Mercator */
600 
601 
603  double Northing,
604  double *Latitude,
605  double *Longitude)const
606 { /* Begin Convert_Oblique_Mercator_To_Geodetic */
607 /*
608  * The function Convert_Oblique_Mercator_To_Geodetic converts Oblique Mercator projection
609  * (easting and northing) coordinates to geodetic (latitude and longitude)
610  * coordinates, according to the current ellipsoid and Oblique Mercator projection
611  * coordinates. If any errors occur, the error code(s) are returned by the
612  * function, otherwise OMERC_NO_ERROR is returned.
613  *
614  * Easting : Easting (X), in meters (input)
615  * Northing : Northing (Y), in meters (input)
616  * Latitude : Latitude (phi), in radians (output)
617  * Longitude : Longitude (lambda), in radians (output)
618  */
619 
620  double dx, dy;
621  /* Coordinate axes defined with respect to the azimuth of the center line */
622  /* Natural origin*/
623  double u, v;
624  double Q_prime, Q_prime_inv;
625  double S_prime, T_prime, V_prime, U_prime;
626  double t;
627  double es_sin;
628  double u_B_over_A;
629  double phi;
630  double temp_phi = 0.0;
631  long Error_Code = OMERC_NO_ERROR;
632 
633 // if ((Easting < (OMerc_False_Easting - OMerc_Delta_Easting))
634 // || (Easting > (OMerc_False_Easting + OMerc_Delta_Easting)))
635 // { /* Easting out of range */
636 // Error_Code |= OMERC_EASTING_ERROR;
637 // }
638 // if ((Northing < (OMerc_False_Northing - OMerc_Delta_Northing))
639 // || (Northing > (OMerc_False_Northing + OMerc_Delta_Northing)))
640 // { /* Northing out of range */
641 // Error_Code |= OMERC_NORTHING_ERROR;
642 // }
643 
644  if (!Error_Code)
645  {
646  dy = Northing - OMerc_False_Northing;
647  dx = Easting - OMerc_False_Easting;
648  v = dx * cos_azimuth - dy * sin_azimuth;
649  u = dy * cos_azimuth + dx * sin_azimuth;
650  u = u + OMerc_u;
651  Q_prime = exp(-1.0 * (v * B_over_A ));
652  Q_prime_inv = 1.0 / Q_prime;
653  S_prime = (Q_prime - Q_prime_inv) / 2.0;
654  T_prime = (Q_prime + Q_prime_inv) / 2.0;
655  u_B_over_A = u * B_over_A;
656  V_prime = sin(u_B_over_A);
657  U_prime = (V_prime * cos_gamma + S_prime * sin_gamma) / T_prime;
658  if (fabs(fabs(U_prime) - 1.0) < 1.0e-10)
659  {
660  if (U_prime > 0)
661  *Latitude = PI_OVER_2;
662  else
663  *Latitude = -PI_OVER_2;
664  *Longitude = OMerc_Origin_Long;
665  }
666  else
667  {
668  t = pow(OMerc_E / sqrt((1.0 + U_prime) / (1.0 - U_prime)), 1.0 / OMerc_B);
669  phi = PI_OVER_2 - 2.0 * atan(t);
670  while (fabs(phi - temp_phi) > 1.0e-10)
671  {
672  temp_phi = phi;
673  es_sin = es * sin(phi);
674  phi = PI_OVER_2 - 2.0 * atan(t * pow((1.0 - es_sin) / (1.0 + es_sin), es_OVER_2));
675  }
676  *Latitude = phi;
677  *Longitude = OMerc_Origin_Long - atan2((S_prime * cos_gamma - V_prime * sin_gamma), cos(u_B_over_A)) / OMerc_B;
678  }
679 
680 // if (fabs(*Latitude) < 2.0e-7) /* force lat to 0 to avoid -0 degrees */
681 // *Latitude = 0.0;
682 // if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */
683 // *Latitude = PI_OVER_2;
684 // else if (*Latitude < -PI_OVER_2)
685 // *Latitude = -PI_OVER_2;
686 
687 // if (*Longitude > PI)
688 // *Longitude -= TWO_PI;
689 // if (*Longitude < -PI)
690 // *Longitude += TWO_PI;
691 
692 // if (fabs(*Longitude) < 2.0e-7) /* force lon to 0 to avoid -0 degrees */
693 // *Longitude = 0.0;
694 // if (*Longitude > PI) /* force distorted values to 180, -180 degrees */
695 // *Longitude = PI;
696 // else if (*Longitude < -PI)
697 // *Longitude = -PI;
698 
699 // if (fabs(*Longitude - OMerc_Origin_Long) >= PI_OVER_2)
700 // { /* Distortion will result if Longitude is 90 degrees or more from the Central Meridian */
701 // Error_Code |= OMERC_LON_WARNING;
702 // }
703 
704  }
705  return (Error_Code);
706 } /* End Convert_Oblique_Mercator_To_Geodetic */
707 
708 //*************************************************************************************************
710 //*************************************************************************************************
712 {
713  if (!ossimMapProjection::operator==(proj))
714  return false;
715 
717  dynamic_cast<const ossimObliqueMercatorProjection*>(&proj);
718  if (!p) return false;
719 
720  if (theCentralPoint1 != p->theCentralPoint1) return false;
721  if (theCentralPoint2 != p->theCentralPoint2) return false;
723 
724  return true;
725 }
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
static const char * CENTRAL_POINT2_LON_KW
#define DEG_PER_RAD
Represents serializable keyword/value map.
const char * find(const char *key) const
virtual ossimGpt inverse(const ossimDpt &eastingNorthing) const
Will take a point in meters and convert it to ground.
bool almostEqual(T x, T y, T tolerance=FLT_EPSILON)
Definition: ossimCommon.h:53
void clampLon(double low, double high)
Definition: ossimGpt.h:228
double y
Definition: ossimDpt.h:165
virtual const ossimString & code() const
Definition: ossimDatum.h:57
#define OMERC_NO_ERROR
double latd() const
Will convert the radian measure to degrees.
Definition: ossimGpt.h:87
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
static const char * TYPE_KW
void changeDatum(const ossimDatum *datum)
This will actually perform a shift.
Definition: ossimGpt.cpp:316
#define STATIC_TYPE_NAME(T)
Definition: ossimRtti.h:325
const ossimDatum * datum() const
datum().
Definition: ossimGpt.h:196
ossimObliqueMercatorProjection(const ossimEllipsoid &ellipsoid=ossimEllipsoid(), const ossimGpt &origin=ossimGpt())
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
virtual ossimDpt forward(const ossimGpt &latLon) const
All map projections will convert the world coordinate to an easting northing (Meters).
#define M_PI
#define OMERC_t(lat, e_sinlat, e_over_2)
const double & getA() const
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
double lonr() const
Returns the longitude in radian measure.
Definition: ossimGpt.h:76
double toDouble() const
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
void clampLat(double low, double high)
Definition: ossimGpt.h:234
long Convert_Geodetic_To_Oblique_Mercator(double Latitude, double Longitude, double *Easting, double *Northing) const
virtual bool operator==(const ossimProjection &projection) const
Returns TRUE if principal parameters are within epsilon tolerance.
static const char * CENTRAL_POINT2_LAT_KW
void Get_Oblique_Mercator_Parameters(double *a, double *f, double *Origin_Latitude, double *Latitude_1, double *Longitude_1, double *Latitude_2, double *Longitude_2, double *False_Easting, double *False_Northing, double *Scale_Factor) const
#define OMERC_LON_ERROR
long Set_Oblique_Mercator_Parameters(double a, double f, double Origin_Latitude, double Latitude_1, double Longitude_1, double Latitude_2, double Longitude_2, double False_Easting, double False_Northing, double Scale_Factor)
static const char * CENTRAL_POINT1_LON_KW
double x
Definition: ossimDpt.h:164
double latr() const
latr().
Definition: ossimGpt.h:66
const double & getFlattening() const
void setFalseEastingNorthing(double falseEasting, double falseNorthing)
ossimEllipsoid theEllipsoid
This method verifies that the projection parameters match the current pcs code.
static const char * SCALE_FACTOR_KW
#define RTTI_DEF1(cls, name, b1)
Definition: ossimRtti.h:485
ossimDpt theFalseEastingNorthing
Hold the false easting northing.
static const char * CENTRAL_POINT1_LAT_KW
long Convert_Oblique_Mercator_To_Geodetic(double Easting, double Northing, double *Latitude, double *Longitude) const
void setParameters(const ossimGpt &point1, const ossimGpt &point2, double falseEasting, double falseNorthing, double scaleFactor)
const ossimDatum * theDatum
This is only set if we want to have built in datum shifting.