OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimStereographicProjection.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: ossimStereographicProjection.cpp 9094 2006-06-13 19:12:40Z dburken $
10 
13 
14 RTTI_DEF1(ossimStereographicProjection, "ossimStereographicProjection", ossimMapProjection)
15 
16 #ifndef PI_OVER_2
17 # define PI_OVER_2 ( M_PI / 2.0)
18 #endif
19 #ifndef PI_OVER_4
20 # define PI_OVER_4 ( M_PI / 4.0)
21 #endif
22 #ifndef TWO_PI
23 # define TWO_PI (2.0 * M_PI)
24 #endif
25 #define ONE (1.0 * M_PI / 180.0) /* 1 degree in radians*/
26 
27 #define STEREO_NO_ERROR 0x0000
28 #define STEREO_LAT_ERROR 0x0001
29 #define STEREO_LON_ERROR 0x0002
30 #define STEREO_ORIGIN_LAT_ERROR 0x0004
31 #define STEREO_CENT_MER_ERROR 0x0008
32 #define STEREO_EASTING_ERROR 0x0010
33 #define STEREO_NORTHING_ERROR 0x0020
34 #define STEREO_A_ERROR 0x0040
35 #define STEREO_INV_F_ERROR 0x0080
36 
38  const ossimGpt& origin)
39  :ossimMapProjection(ellipsoid, origin)
40 {
41  setDefaults();
42  update();
43 }
44 
46  const ossimGpt& origin,
47  double falseEasting,
48  double falseNorthing)
49  :ossimMapProjection(ellipsoid, origin)
50 {
51  Stereo_False_Easting = falseEasting;
52  Stereo_False_Northing = falseNorthing;
53  Stereo_Delta_Easting = 1460090226.0;
54  Stereo_Delta_Northing = 1460090226.0;
55 
56  update();
57 }
58 
60 {
63  theOrigin.latr(),
64  theOrigin.lonr(),
67 
70 
72 }
73 
75 {
76  Stereo_False_Easting = falseEasting;
77 
78  update();
79 }
80 
82 {
83  Stereo_False_Northing = falseNorthing;
84 
85  update();
86 }
87 
89 {
92  Stereo_Delta_Easting = 1460090226.0;
93  Stereo_Delta_Northing = 1460090226.0;
94 }
95 
97  double falseNorthing)
98 {
99  Stereo_False_Easting = falseEasting;
100  Stereo_False_Northing = falseNorthing;
101 
102  update();
103 }
104 
106 {
107  double lat = 0.0;
108  double lon = 0.0;
109 
110  Convert_Stereographic_To_Geodetic(eastingNorthing.x,
111  eastingNorthing.y,
112  &lat,
113  &lon);
114 
115  return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum);
116 }
117 
119 {
120  double easting = 0.0;
121  double northing = 0.0;
122  ossimGpt gpt = latLon;
123 
124  if (theDatum)
125  {
126  if (theDatum->code() != latLon.datum()->code())
127  {
128  gpt.changeDatum(theDatum); // Shift to our datum.
129  }
130  }
131 
133  gpt.lonr(),
134  &easting,
135  &northing);
136 
137  return ossimDpt(easting, northing);
138 }
139 
140 bool ossimStereographicProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const
141 {
142  return ossimMapProjection::saveState(kwl, prefix);
143 }
144 
146  const char* prefix)
147 {
148  bool flag = ossimMapProjection::loadState(kwl, prefix);
149 
150  const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
151 
152  setDefaults();
153 
155  {
158  }
159 
160  update();
161 
162  return flag;
163 }
164 /************************************************************************/
165 /* FUNCTIONS
166  *
167  */
168 
170  double f,
171  double Origin_Latitude,
172  double Central_Meridian,
173  double False_Easting,
174  double False_Northing)
175 
176 { /* BEGIN Set_Stereographic_Parameters */
177 /*
178  * The function Set_Stereographic_Parameters receives the ellipsoid
179  * parameters and Stereograpic projection parameters as inputs, and
180  * sets the corresponding state variables. If any errors occur, error
181  * code(s) are returned by the function, otherwise STEREO_NO_ERROR is returned.
182  *
183  * a : Semi-major axis of ellipsoid, in meters (input)
184  * f : Flattening of ellipsoid (input)
185  * Origin_Latitude : Latitude, in radians, at the center of (input)
186  * the projection
187  * Central_Meridian : Longitude, in radians, at the center of (input)
188  * the projection
189  * False_Easting : Easting (X) at center of projection, in meters (input)
190  * False_Northing : Northing (Y) at center of projection, in meters (input)
191  */
192 
193  double es2, es4, es6;
194  double temp = 0;
195 // double inv_f = 1 / f;
196  long Error_Code = STEREO_NO_ERROR;
197 
198 // if (a <= 0.0)
199 // { /* Semi-major axis must be greater than zero */
200 // Error_Code |= STEREO_A_ERROR;
201 // }
202 // if ((inv_f < 250) || (inv_f > 350))
203 // { /* Inverse flattening must be between 250 and 350 */
204 // Error_Code |= STEREO_INV_F_ERROR;
205 // }
206 // if ((Origin_Latitude < -PI_OVER_2) || (Origin_Latitude > PI_OVER_2))
207 // { /* origin latitude out of range */
208 // Error_Code |= STEREO_ORIGIN_LAT_ERROR;
209 // }
210 // if ((Central_Meridian < -M_PI) || (Central_Meridian > TWO_PI))
211 // { /* origin longitude out of range */
212 // Error_Code |= STEREO_CENT_MER_ERROR;
213 // }
214  if (!Error_Code)
215  { /* no errors */
216  Stereo_a = a;
217  Stereo_f = f;
218  es2 = 2 * Stereo_f - Stereo_f * Stereo_f;
219  es4 = es2 * es2;
220  es6 = es4 * es2;
221  Stereo_Ra = Stereo_a * (1.0 - es2 / 6.0 - 17.0 * es4 / 360.0 - 67.0 * es6 /3024.0);
222  Two_Stereo_Ra = 2.0 * Stereo_Ra;
223  Stereo_Origin_Lat = Origin_Latitude;
226 // if (Central_Meridian > M_PI)
227 // Central_Meridian -= TWO_PI;
228  Stereo_Origin_Long = Central_Meridian;
229  Stereo_False_Easting = False_Easting;
230  Stereo_False_Northing = False_Northing;
231  if(fabs(fabs(Stereo_Origin_Lat) - PI_OVER_2) < 1.0e-10)
232  Stereo_At_Pole = 1;
233  else
234  Stereo_At_Pole = 0;
235 
236  if ((Stereo_At_Pole) || (fabs(Stereo_Origin_Lat) < 1.0e-10))
237  {
238  Stereo_Delta_Easting = 1460090226.0;
239  }
240  else
241  {
242  if (Stereo_Origin_Long <= 0)
244  else
246  }
247 
248  } /* END OF if(!Error_Code) */
249  return (Error_Code);
250 } /* END OF Set_Stereographic_Parameters */
251 
253  double *f,
254  double *Origin_Latitude,
255  double *Central_Meridian,
256  double *False_Easting,
257  double *False_Northing)const
258 
259 { /* BEGIN Get_Stereographic_Parameters */
260 /*
261  * The function Get_Stereographic_Parameters returns the current ellipsoid
262  * parameters and Stereographic projection parameters.
263  *
264  * a : Semi-major axis of ellipsoid, in meters (output)
265  * f : Flattening of ellipsoid (output)
266  * Origin_Latitude : Latitude, in radians, at the center of (output)
267  * the projection
268  * Central_Meridian : Longitude, in radians, at the center of (output)
269  * the projection
270  * False_Easting : A coordinate value, in meters, assigned to the
271  * central meridian of the projection. (output)
272  * False_Northing : A coordinate value, in meters, assigned to the
273  * origin latitude of the projection (output)
274  */
275 
276  *a = Stereo_a;
277  *f = Stereo_f;
278  *Origin_Latitude = Stereo_Origin_Lat;
279  *Central_Meridian = Stereo_Origin_Long;
280  *False_Easting = Stereo_False_Easting;
281  *False_Northing = Stereo_False_Northing;
282 
283  return;
284 } /* END OF Get_Stereographic_Parameters */
285 
287  double Longitude,
288  double *Easting,
289  double *Northing)const
290 
291 { /* BEGIN Convert_Geodetic_To_Stereographic */
292 
293 /*
294  * The function Convert_Geodetic_To_Stereographic converts geodetic
295  * coordinates (latitude and longitude) to Stereographic coordinates
296  * (easting and northing), according to the current ellipsoid
297  * and Stereographic projection parameters. If any errors occur, error
298  * code(s) are returned by the function, otherwise STEREO_NO_ERROR is returned.
299  *
300  * Latitude : Latitude, in radians (input)
301  * Longitude : Longitude, in radians (input)
302  * Easting : Easting (X), in meters (output)
303  * Northing : Northing (Y), in meters (output)
304  */
305 
306  double g, k;
307  double num = 0;
308  double Ra_k = 0;
309  double slat = sin(Latitude);
310  double clat = cos(Latitude);
311  double dlam; /* Longitude - Central Meridan */
312  double cos_dlam;
313  long Error_Code = STEREO_NO_ERROR;
314 
315 // if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2))
316 // { /* Latitude out of range */
317 // Error_Code |= STEREO_LAT_ERROR;
318 // }
319 // if ((Longitude < -M_PI) || (Longitude > TWO_PI))
320 // { /* Longitude out of range */
321 // Error_Code|= STEREO_LON_ERROR;
322 // }
323  if (!Error_Code)
324  { /* no errors */
325 
326 
327  dlam = Longitude - Stereo_Origin_Long;
328 // if (dlam > M_PI)
329 // {
330 // dlam -= TWO_PI;
331 // }
332 // if (dlam < -M_PI)
333 // {
334 // dlam += TWO_PI;
335 // }
336 
337  cos_dlam = cos(dlam);
338  g = 1.0 + Sin_Stereo_Origin_Lat * slat + Cos_Stereo_Origin_Lat * clat * cos_dlam;
339  if (fabs(g) <= 1.0e-10)
340  { /* Point is out of view. Will return longitude out of range message
341  since no point out of view is implemented. */
342  Error_Code |= STEREO_LON_ERROR;
343  }
344  else
345  {
346  if (Stereo_At_Pole)
347  {
348  if (fabs(fabs(Latitude) - PI_OVER_2) < 1.0e-10)
349  {
350  *Easting = Stereo_False_Easting;
351  *Northing = Stereo_False_Northing;
352  }
353  else
354  {
355  if (Stereo_Origin_Lat > 0)
356  {
357  num = Two_Stereo_Ra * tan(PI_OVER_4 - Latitude / 2.0);
358  *Easting = Stereo_False_Easting + num * sin(dlam);
359  *Northing = Stereo_False_Northing + (-num * cos_dlam);
360  }
361  else
362  {
363  num = Two_Stereo_Ra * tan(PI_OVER_4 + Latitude / 2.0);
364  *Easting = Stereo_False_Easting + num * sin(dlam);
365  *Northing = Stereo_False_Northing + num * cos_dlam;
366  }
367  }
368  }
369  else
370  {
371  if (fabs(Stereo_Origin_Lat) <= 1.0e-10)
372  {
373  k = 2.0 / (1.0 + clat * cos_dlam);
374  Ra_k = Stereo_Ra * k;
375  *Northing = Stereo_False_Northing + Ra_k * slat;
376  }
377  else
378  {
379  k = 2.0 / g;
380  Ra_k = Stereo_Ra * k;
381  *Northing = Stereo_False_Northing + Ra_k * (Cos_Stereo_Origin_Lat * slat - Sin_Stereo_Origin_Lat * clat * cos_dlam);
382  }
383  *Easting = Stereo_False_Easting + Ra_k * clat * sin(dlam);
384  }
385  }
386  }
387  return (Error_Code);
388 } /* END OF Convert_Geodetic_To_Stereographic */
389 
391  double Northing,
392  double *Latitude,
393  double *Longitude)const
394 { /* BEGIN Convert_Stereographic_To_Geodetic */
395 /*
396  * The function Convert_Stereographic_To_Geodetic converts Stereographic projection
397  * (easting and northing) coordinates to geodetic (latitude and longitude)
398  * coordinates, according to the current ellipsoid and Stereographic projection
399  * coordinates. If any errors occur, the error code(s) are returned by the
400  * function, otherwise STEREO_NO_ERROR is returned.
401  *
402  * Easting : Easting (X), in meters (input)
403  * Northing : Northing (Y), in meters (input)
404  * Latitude : Latitude (phi), in radians (output)
405  * Longitude : Longitude (lambda), in radians (output)
406  */
407 
408  double dx, dy;
409  double rho, c;
410  double sin_c, cos_c;
411  double dy_sin_c;
412  long Error_Code = STEREO_NO_ERROR;
413 
414 // if ((Easting < (Stereo_False_Easting - Stereo_Delta_Easting))
415 // ||(Easting > (Stereo_False_Easting + Stereo_Delta_Easting)))
416 // { /* Easting out of range */
417 // Error_Code |= STEREO_EASTING_ERROR;
418 // }
419 // if ((Northing < (Stereo_False_Northing - Stereo_Delta_Northing))
420 // || (Northing > (Stereo_False_Northing + Stereo_Delta_Northing)))
421 // { /* Northing out of range */
422 // Error_Code |= STEREO_NORTHING_ERROR;
423 // }
424  if (!Error_Code)
425  { /* no errors */
426 
427  dy = Northing - Stereo_False_Northing;
428  dx = Easting - Stereo_False_Easting;
429  rho = sqrt(dx * dx + dy * dy);
430  if (fabs(rho) <= 1.0e-10)
431  {
432  *Latitude = Stereo_Origin_Lat;
433  *Longitude = Stereo_Origin_Long;
434  }
435  else
436  {
437  c = 2.0 * atan(rho / (Two_Stereo_Ra));
438  sin_c = sin(c);
439  cos_c = cos(c);
440  dy_sin_c = dy * sin_c;
441  if (Stereo_At_Pole)
442  {
443  if (Stereo_Origin_Lat > 0)
444  *Longitude = Stereo_Origin_Long + atan2(dx, -dy);
445  else
446  *Longitude = Stereo_Origin_Long + atan2(dx, dy);
447  }
448  else
449  *Longitude = Stereo_Origin_Long + atan2(dx * sin_c, (rho * Cos_Stereo_Origin_Lat * cos_c - dy_sin_c * Sin_Stereo_Origin_Lat));
450  *Latitude = asin(cos_c * Sin_Stereo_Origin_Lat + ((dy_sin_c * Cos_Stereo_Origin_Lat) / rho));
451  }
452 
453 // if (fabs(*Latitude) < 2.2e-8) /* force lat to 0 to avoid -0 degrees */
454 // *Latitude = 0.0;
455 // if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */
456 // *Latitude = PI_OVER_2;
457 // else if (*Latitude < -PI_OVER_2)
458 // *Latitude = -PI_OVER_2;
459 
460 // if (*Longitude > M_PI)
461 // {
462 // if (*Longitude - M_PI < 3.5e-6)
463 // *Longitude = M_PI;
464 // else
465 // *Longitude -= TWO_PI;
466 // }
467 // if (*Longitude < -M_PI)
468 // {
469 // if (fabs(*Longitude + M_PI) < 3.5e-6)
470 // *Longitude = -M_PI;
471 // else
472 // *Longitude += TWO_PI;
473 // }
474 //
475 // if (fabs(*Longitude) < 2.0e-7) /* force lon to 0 to avoid -0 degrees */
476 // *Longitude = 0.0;
477 // if (*Longitude > M_PI) /* force distorted values to 180, -180 degrees */
478 // *Longitude = M_PI;
479 // else if (*Longitude < -M_PI)
480 // *Longitude = -M_PI;
481  }
482  return (Error_Code);
483 } /* END OF Convert_Stereographic_To_Geodetic */
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
#define DEG_PER_RAD
Represents serializable keyword/value map.
const char * find(const char *key) const
double y
Definition: ossimDpt.h:165
long Set_Stereographic_Parameters(double a, double f, double Origin_Latitude, double Central_Meridian, double False_Easting, double False_Northing)
virtual const ossimString & code() const
Definition: ossimDatum.h:57
#define STEREO_LON_ERROR
ossimStereographicProjection(const ossimEllipsoid &ellipsoid=ossimEllipsoid(), const ossimGpt &origin=ossimGpt())
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
void setFalseEastingNorthing(double falseEasting, double falseNorthing)
#define M_PI
virtual ossimDpt forward(const ossimGpt &latLon) const
All map projections will convert the world coordinate to an easting northing (Meters).
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
const double & getA() const
long Convert_Stereographic_To_Geodetic(double Easting, double Northing, double *Latitude, double *Longitude) const
double lonr() const
Returns the longitude in radian measure.
Definition: ossimGpt.h:76
long Convert_Geodetic_To_Stereographic(double Latitude, double Longitude, double *Easting, double *Northing) const
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
void Get_Stereographic_Parameters(double *a, double *f, double *Origin_Latitude, double *Central_Meridian, double *False_Easting, double *False_Northing) const
virtual ossimGpt inverse(const ossimDpt &eastingNorthing) const
Will take a point in meters and convert it to ground.
double x
Definition: ossimDpt.h:164
#define STEREO_NO_ERROR
double latr() const
latr().
Definition: ossimGpt.h:66
const double & getFlattening() const
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.
void setFalseNorthing(double falseNorthing)
const ossimDatum * theDatum
This is only set if we want to have built in datum shifting.