OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimPolarStereoProjection.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 // Description:
9 //
10 // Calls Geotrans Polar Stereographic projection code.
11 //*******************************************************************
12 // $Id: ossimPolarStereoProjection.cpp 17815 2010-08-03 13:23:14Z dburken $
13 
14 #include <math.h>
17 
18 RTTI_DEF1(ossimPolarStereoProjection, "ossimPolarStereoProjection", ossimMapProjection)
19 /************************************************************************/
20 /* DEFINES
21  *
22  */
23 
24 #ifndef PI_OVER_2
25 # define PI_OVER_2 ( M_PI / 2.0)
26 #endif
27 #ifndef TWO_PI
28 # define TWO_PI (2.0 * M_PI)
29 #endif
30 #define POLAR_POW(EsSin) pow((1.0 - EsSin) / (1.0 + EsSin), es_OVER_2)
31 
32 #define POLAR_NO_ERROR 0x0000
33 #define POLAR_LAT_ERROR 0x0001
34 #define POLAR_LON_ERROR 0x0002
35 #define POLAR_ORIGIN_LAT_ERROR 0x0004
36 #define POLAR_ORIGIN_LON_ERROR 0x0008
37 #define POLAR_EASTING_ERROR 0x0010
38 #define POLAR_NORTHING_ERROR 0x0020
39 #define POLAR_A_ERROR 0x0040
40 #define POLAR_B_ERROR 0x0080
41 #define POLAR_A_LESS_B_ERROR 0x0100
42 #define POLAR_RADIUS_ERROR 0x0200
43 
44 /************************************************************************/
45 /* GLOBAL DECLARATIONS
46  *
47  */
48 
49 const double PI_Over_4 = (M_PI / 4.0);
50 
52  const ossimGpt& origin)
53  :ossimMapProjection(ellipsoid, origin)
54 {
55  setDefaults();
56  update();
57 // Polar_Delta_Easting = 12713601.0;
58 // Polar_Delta_Northing = 12713601.0;
59 }
60 
62  const ossimGpt& /* origin */,
63  double falseEasting,
64  double falseNorthing)
65 {
66  Polar_False_Easting = falseEasting;
67  Polar_False_Northing = falseNorthing;
68  Polar_Delta_Easting = 12713601.0;
69  Polar_Delta_Northing = 12713601.0;
70 
71  update();
72 }
73 
75 {
78  theOrigin.latr(),
79  theOrigin.lonr(),
82 
85 
87 }
88 
90 {
91  Polar_False_Easting = falseEasting;
92 
93  update();
94 }
95 
97 {
98  Polar_False_Northing = falseNorthing;
99 
100  update();
101 }
102 
104 {
105  Polar_False_Easting = 0.0;
106  Polar_False_Northing = 0.0;
107 }
108 
110  double falseNorthing)
111 {
112  Polar_False_Easting = falseEasting;
113  Polar_False_Northing = falseNorthing;
114 
115  update();
116 }
117 
119 {
120  double lat = 0.0;
121  double lon = 0.0;
122 
124  eastingNorthing.y,
125  &lat,
126  &lon);
127 
128  return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum);
129 }
130 
132 {
133  double easting = 0.0;
134  double northing = 0.0;
135  ossimGpt gpt = latLon;
136 
137  if (theDatum)
138  {
139  if (theDatum->code() != latLon.datum()->code())
140  {
141  gpt.changeDatum(theDatum); // Shift to our datum.
142  }
143  }
144 
146  gpt.lonr(),
147  &easting,
148  &northing);
149 
150  return ossimDpt(easting, northing);
151 }
152 
153 bool ossimPolarStereoProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const
154 {
155  return ossimMapProjection::saveState(kwl, prefix);
156 }
157 
159  const char* prefix)
160 {
161  bool flag = ossimMapProjection::loadState(kwl, prefix);
162  const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
163 
164  setDefaults();
165 
167  {
170  }
171 
172  update();
173 
174  return flag;
175 }
176 
177 
178 /************************************************************************/
179 /* FUNCTIONS
180  *
181  */
182 
183 
185  double f,
186  double Latitude_of_True_Scale,
187  double Longitude_Down_from_Pole,
188  double False_Easting,
189  double False_Northing)
190 
191 { /* BEGIN Set_Polar_Stereographic_Parameters */
192 /*
193  * The function Set_Polar_Stereographic_Parameters receives the ellipsoid
194  * parameters and Polar Stereograpic projection parameters as inputs, and
195  * sets the corresponding state variables. If any errors occur, error
196  * code(s) are returned by the function, otherwise POLAR_NO_ERROR is returned.
197  *
198  * a : Semi-major axis of ellipsoid, in meters (input)
199  * f : Flattening of ellipsoid (input)
200  * Latitude_of_True_Scale : Latitude of true scale, in radians (input)
201  * Longitude_Down_from_Pole : Longitude down from pole, in radians (input)
202  * False_Easting : Easting (X) at center of projection, in meters (input)
203  * False_Northing : Northing (Y) at center of projection, in meters (input)
204  */
205 
206  double es2;
207  double slat, clat;
208  double essin;
209  double one_PLUS_es, one_MINUS_es;
210  double pow_es;
211  double temp;
212 // double inv_f = 1 / f;
213  const double epsilon = 1.0e-2;
214  long Error_Code = POLAR_NO_ERROR;
215 
216 // if (a <= 0.0)
217 // { /* Semi-major axis must be greater than zero */
218 // Error_Code |= POLAR_A_ERROR;
219 // }
220 // if ((inv_f < 250) || (inv_f > 350))
221 // { /* Inverse flattening must be between 250 and 350 */
222 // Error_Code |= POLAR_INV_F_ERROR;
223 // }
224 // if ((Latitude_of_True_Scale < -PI_OVER_2) || (Latitude_of_True_Scale > PI_OVER_2))
225 // { /* Origin Latitude out of range */
226 // Error_Code |= POLAR_ORIGIN_LAT_ERROR;
227 // }
228 // if ((Longitude_Down_from_Pole < -PI) || (Longitude_Down_from_Pole > TWO_PI))
229 // { /* Origin Longitude out of range */
230 // Error_Code |= POLAR_ORIGIN_LON_ERROR;
231 // }
232 
233  if (!Error_Code)
234  { /* no errors */
235 
236  Polar_a = a;
237  two_Polar_a = 2.0 * Polar_a;
238  Polar_f = f;
239 
240  if (Longitude_Down_from_Pole > M_PI)
241  Longitude_Down_from_Pole -= TWO_PI;
242  if (Latitude_of_True_Scale < 0)
243  {
245  Polar_Origin_Lat = -Latitude_of_True_Scale;
246  Polar_Origin_Long = -Longitude_Down_from_Pole;
247  }
248  else
249  {
251  Polar_Origin_Lat = Latitude_of_True_Scale;
252  Polar_Origin_Long = Longitude_Down_from_Pole;
253  }
254  Polar_False_Easting = False_Easting;
255  Polar_False_Northing = False_Northing;
256 
257  es2 = 2 * Polar_f - Polar_f * Polar_f;
258  es = sqrt(es2);
259  es_OVER_2 = es / 2.0;
260 
261  if (fabs(fabs(Polar_Origin_Lat) - PI_OVER_2) > 1.0e-10)
262  {
263  slat = sin(Polar_Origin_Lat);
264  essin = es * slat;
265  pow_es = POLAR_POW(essin);
266  clat = cos(Polar_Origin_Lat);
267  mc = clat / sqrt(1.0 - essin * essin);
268  Polar_a_mc = Polar_a * mc;
269  tc = tan(PI_Over_4 - Polar_Origin_Lat / 2.0) / pow_es;
270  }
271  else
272  {
273  one_PLUS_es = 1.0 + es;
274  one_MINUS_es = 1.0 - es;
275  e4 = sqrt(pow(one_PLUS_es, one_PLUS_es) * pow(one_MINUS_es, one_MINUS_es));
276  }
277  }
278  /* Calculate Radius */
280  &temp, &Polar_Delta_Northing);
281  Polar_Delta_Northing = fabs(Polar_Delta_Northing) + epsilon;
283 
284 
285  return (Error_Code);
286 } /* END OF Set_Polar_Stereographic_Parameters */
287 
288 
289 
291  double *f,
292  double *Latitude_of_True_Scale,
293  double *Longitude_Down_from_Pole,
294  double *False_Easting,
295  double *False_Northing)const
296 
297 { /* BEGIN Get_Polar_Stereographic_Parameters */
298 /*
299  * The function Get_Polar_Stereographic_Parameters returns the current
300  * ellipsoid parameters and Polar projection parameters.
301  *
302  * a : Semi-major axis of ellipsoid, in meters (output)
303  * f : Flattening of ellipsoid (output)
304  * Latitude_of_True_Scale : Latitude of true scale, in radians (output)
305  * Longitude_Down_from_Pole : Longitude down from pole, in radians (output)
306  * False_Easting : Easting (X) at center of projection, in meters (output)
307  * False_Northing : Northing (Y) at center of projection, in meters (output)
308  */
309 
310  *a = Polar_a;
311  *f = Polar_f;
312  *Latitude_of_True_Scale = Polar_Origin_Lat;
313  *Longitude_Down_from_Pole = Polar_Origin_Long;
314  *False_Easting = Polar_False_Easting;
315  *False_Northing = Polar_False_Northing;
316 
317  return;
318 } /* END OF Get_Polar_Stereographic_Parameters */
319 
320 
322  double Longitude,
323  double *Easting,
324  double *Northing)const
325 
326 { /* BEGIN Convert_Geodetic_To_Polar_Stereographic */
327 
328 /*
329  * The function Convert_Geodetic_To_Polar_Stereographic converts geodetic
330  * coordinates (latitude and longitude) to Polar Stereographic coordinates
331  * (easting and northing), according to the current ellipsoid
332  * and Polar Stereographic projection parameters. If any errors occur, error
333  * code(s) are returned by the function, otherwise POLAR_NO_ERROR is returned.
334  *
335  * Latitude : Latitude, in radians (input)
336  * Longitude : Longitude, in radians (input)
337  * Easting : Easting (X), in meters (output)
338  * Northing : Northing (Y), in meters (output)
339  */
340 
341  double dlam;
342  double slat;
343  double essin;
344  double t;
345  double rho;
346  double pow_es;
347  long Error_Code = POLAR_NO_ERROR;
348 
349 // if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2))
350 // { /* Latitude out of range */
351 // Error_Code |= POLAR_LAT_ERROR;
352 // }
353 // if ((Latitude < 0) && (Southern_Hemisphere == 0))
354 // { /* Latitude and Origin Latitude in different hemispheres */
355 // Error_Code |= POLAR_LAT_ERROR;
356 // }
357 // if ((Latitude > 0) && (Southern_Hemisphere == 1))
358 // { /* Latitude and Origin Latitude in different hemispheres */
359 // Error_Code |= POLAR_LAT_ERROR;
360 // }
361 // if ((Longitude < -PI) || (Longitude > TWO_PI))
362 // { /* Longitude out of range */
363 // Error_Code |= POLAR_LON_ERROR;
364 // }
365 
366 
367  if (!Error_Code)
368  { /* no errors */
369 
370  if (fabs(fabs(Latitude) - PI_OVER_2) < 1.0e-10)
371  {
372  *Easting = 0.0;
373  *Northing = 0.0;
374  }
375  else
376  {
377  if (Southern_Hemisphere != 0)
378  {
379  Longitude *= -1.0;
380  Latitude *= -1.0;
381  }
382  dlam = Longitude - Polar_Origin_Long;
383 // if (dlam > M_PI)
384 // {
385 // dlam -= TWO_PI;
386 // }
387 // if (dlam < -M_PI)
388 // {
389 // dlam += TWO_PI;
390 // }
391  slat = sin(Latitude);
392  essin = es * slat;
393  pow_es = POLAR_POW(essin);
394  t = tan(PI_Over_4 - Latitude / 2.0) / pow_es;
395 
396  if (fabs(fabs(Polar_Origin_Lat) - PI_OVER_2) > 1.0e-10)
397  rho = Polar_a_mc * t / tc;
398  else
399  rho = two_Polar_a * t / e4;
400 
401  *Easting = rho * sin(dlam) + Polar_False_Easting;
402 
403  if (Southern_Hemisphere != 0)
404  {
405  *Easting *= -1.0;
406  *Northing = rho * cos(dlam) + Polar_False_Northing;
407  }
408  else
409  *Northing = -rho * cos(dlam) + Polar_False_Northing;
410 
411  }
412  }
413  return (Error_Code);
414 } /* END OF Convert_Geodetic_To_Polar_Stereographic */
415 
416 
418  double Northing,
419  double *Latitude,
420  double *Longitude)const
421 
422 { /* BEGIN Convert_Polar_Stereographic_To_Geodetic */
423 /*
424  * The function Convert_Polar_Stereographic_To_Geodetic converts Polar
425  * Stereographic coordinates (easting and northing) to geodetic
426  * coordinates (latitude and longitude) according to the current ellipsoid
427  * and Polar Stereographic projection Parameters. If any errors occur, the
428  * code(s) are returned by the function, otherwise POLAR_NO_ERROR
429  * is returned.
430  *
431  * Easting : Easting (X), in meters (input)
432  * Northing : Northing (Y), in meters (input)
433  * Latitude : Latitude, in radians (output)
434  * Longitude : Longitude, in radians (output)
435  *
436  */
437 
438  double dy, dx;
439  double rho;
440  double t;
441  double PHI, sin_PHI;
442  double tempPHI = 0.0;
443  double essin;
444  double pow_es;
445 // double temp;
446  long Error_Code = POLAR_NO_ERROR;
447 
448 // if ((Easting > (Polar_False_Easting + Polar_Delta_Easting)) ||
449 // (Easting < (Polar_False_Easting - Polar_Delta_Easting)))
450 // { /* Easting out of range */
451 // Error_Code |= POLAR_EASTING_ERROR;
452 // }
453 // if ((Northing > (Polar_False_Northing + Polar_Delta_Northing)) ||
454 // (Northing < (Polar_False_Northing - Polar_Delta_Northing)))
455 // { /* Northing out of range */
456 // Error_Code |= POLAR_NORTHING_ERROR;
457 // }
458 // if (!Error_Code)
459 // {
460 // temp = sqrt(Easting * Easting + Northing * Northing);
461 
462 // if ((temp > (Polar_False_Easting + Polar_Delta_Easting)) ||
463 // (temp > (Polar_False_Northing + Polar_Delta_Northing)) ||
464 // (temp < (Polar_False_Easting - Polar_Delta_Easting)) ||
465 // (temp < (Polar_False_Northing - Polar_Delta_Northing)))
466 // { /* Point is outside of projection area */
467 // Error_Code |= POLAR_RADIUS_ERROR;
468 // }
469 // }
470 
471  if (!Error_Code)
472  { /* no errors */
473 
474  dy = Northing - Polar_False_Northing;
475  dx = Easting - Polar_False_Easting;
476  if ((dy == 0.0) && (dx == 0.0))
477  {
478  *Latitude = PI_OVER_2;
479  *Longitude = Polar_Origin_Long;
480 
481  }
482  else
483  {
484  if (Southern_Hemisphere != 0)
485  {
486  dy *= -1.0;
487  dx *= -1.0;
488  }
489 
490  rho = sqrt(dx * dx + dy * dy);
491  if (fabs(fabs(Polar_Origin_Lat) - PI_OVER_2) > 1.0e-10)
492  t = rho * tc / (Polar_a_mc);
493  else
494  t = rho * e4 / (two_Polar_a);
495  PHI = PI_OVER_2 - 2.0 * atan(t);
496  while (fabs(PHI - tempPHI) > 1.0e-10)
497  {
498  tempPHI = PHI;
499  sin_PHI = sin(PHI);
500  essin = es * sin_PHI;
501  pow_es = POLAR_POW(essin);
502  PHI = PI_OVER_2 - 2.0 * atan(t * pow_es);
503  }
504  *Latitude = PHI;
505  *Longitude = Polar_Origin_Long + atan2(dx, -dy);
506 
507 // if (*Longitude > M_PI)
508 // *Longitude -= TWO_PI;
509 // else if (*Longitude < -M_PI)
510 // *Longitude += TWO_PI;
511 
512 
513 // if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */
514 // *Latitude = PI_OVER_2;
515 // else if (*Latitude < -PI_OVER_2)
516 // *Latitude = -PI_OVER_2;
517 
518 // if (*Longitude > M_PI) /* force distorted values to 180, -180 degrees */
519 // *Longitude = M_PI;
520 // else if (*Longitude < -M_PI)
521 // *Longitude = -M_PI;
522 
523  }
524  if (Southern_Hemisphere != 0)
525  {
526  *Latitude *= -1.0;
527  *Longitude *= -1.0;
528  }
529 
530  }
531  return (Error_Code);
532 } /* END OF Convert_Polar_Stereographic_To_Geodetic */
533 
534 
void setFalseNorthing(double falseNorthing)
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
void Get_Polar_Stereographic_Parameters(double *a, double *f, double *Latitude_of_True_Scale, double *Longitude_Down_from_Pole, double *False_Easting, double *False_Northing) const
#define DEG_PER_RAD
Represents serializable keyword/value map.
const char * find(const char *key) const
#define TWO_PI
double y
Definition: ossimDpt.h:165
virtual const ossimString & code() const
Definition: ossimDatum.h:57
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
virtual ossimDpt forward(const ossimGpt &latLon) const
All map projections will convert the world coordinate to an easting northing (Meters).
void setFalseEasting(double falseEasting)
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
#define POLAR_NO_ERROR
#define M_PI
long Set_Polar_Stereographic_Parameters(double a, double f, double Latitude_of_True_Scale, double Longitude_Down_from_Pole, double False_Easting, double False_Northing)
ossimPolarStereoProjection(const ossimEllipsoid &ellipsoid=ossimEllipsoid(), const ossimGpt &origin=ossimGpt())
const double & getA() const
long Convert_Geodetic_To_Polar_Stereographic(double Latitude, double Longitude, double *Easting, double *Northing) const
double lonr() const
Returns the longitude in radian measure.
Definition: ossimGpt.h:76
virtual ossimGpt inverse(const ossimDpt &eastingNorthing) const
Will take a point in meters and convert it to ground.
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
const double PI_Over_4
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
long Convert_Polar_Stereographic_To_Geodetic(double Easting, double Northing, double *Latitude, double *Longitude) const
double x
Definition: ossimDpt.h:164
double latr() const
latr().
Definition: ossimGpt.h:66
const double & getFlattening() const
void setFalseEastingNorthing(double falseEasting, double falseNorthing)
#define POLAR_POW(EsSin)
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.
#define PI_OVER_2
const ossimDatum * theDatum
This is only set if we want to have built in datum shifting.