OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimEckert6Projection.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 Eckert6 projection code.
11 //*******************************************************************
12 // $Id: ossimEckert6Projection.cpp 17815 2010-08-03 13:23:14Z dburken $
13 
14 /***************************************************************************/
15 /*
16  * DEFINES
17  */
19 
21 
22 RTTI_DEF1(ossimEckert6Projection, "ossimEckert6Projection", ossimMapProjection)
23 
24 #define ECK6_NO_ERROR 0x0000
25 #define ECK6_LAT_ERROR 0x0001
26 #define ECK6_LON_ERROR 0x0002
27 #define ECK6_EASTING_ERROR 0x0004
28 #define ECK6_NORTHING_ERROR 0x0008
29 #define ECK6_CENT_MER_ERROR 0x0020
30 #define ECK6_A_ERROR 0x0040
31 #define ECK6_B_ERROR 0x0080
32 #define ECK6_A_LESS_B_ERROR 0x0100
33 
34 #ifndef PI_OVER_2
35 # define PI_OVER_2 ( M_PI / 2.0)
36 #endif
37 #ifndef TWO_PI
38 # define TWO_PI (2.0 * M_PI)
39 #endif
40 
41 #define MAX_LAT ( (M_PI * 90.0) / 180.0 ) /* 90 degrees in radians */
42 
43 /***************************************************************************/
44 /*
45  * GLOBALS
46  */
47 
48 const double one_PLUS_PI_OVER_2 = (1.0 + M_PI / 2.0);
49 
51  const ossimGpt& origin)
52  :ossimMapProjection(ellipsoid, origin)
53 {
54  setDefaults();
55 }
56 
58  const ossimGpt& origin,
59  double falseEasting,
60  double falseNorthing)
61  :ossimMapProjection(ellipsoid, origin)
62 {
63  Eck6_False_Easting = falseEasting;
64  Eck6_False_Northing = falseNorthing;
65  Eck6_Delta_Northing = 8451144.0;
66  Eck6_Max_Easting = 16902288.0;
67  Eck6_Min_Easting = -16902288.0;
68 
69  update();
70 }
71 
73 {
76  theOrigin.lonr(),
79 
82 
84 }
85 
87 {
88  double lat = 0.0;
89  double lon = 0.0;
90 
91  Convert_Eckert6_To_Geodetic(eastingNorthing.x,
92  eastingNorthing.y,
93  &lat,
94  &lon);
95 
96  return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum);
97 }
98 
100 {
101  double easting = 0.0;
102  double northing = 0.0;
103  ossimGpt gpt = latLon;
104 
105  if (theDatum)
106  {
107  if (theDatum->code() != latLon.datum()->code())
108  {
109  gpt.changeDatum(theDatum); // Shift to our datum.
110  }
111  }
112 
114  gpt.lonr(),
115  &easting,
116  &northing);
117 
118  return ossimDpt(easting, northing);
119 }
120 
122 {
123  Eck6_False_Easting = falseEasting;
124  update();
125 }
126 
128 {
129  Eck6_False_Northing = falseNorthing;
130  update();
131 }
132 
134  double falseNorthing)
135 {
136  Eck6_False_Easting = falseEasting;
137  Eck6_False_Northing = falseNorthing;
138  update();
139 }
140 
142 {
143  Eck6_Delta_Northing = 8451144.0;
144  Eck6_Max_Easting = 16902288.0;
145  Eck6_Min_Easting = -16902288.0;
146  Eck6_False_Easting = 0.0;
147  Eck6_False_Northing = 0.0;
148 
149  update();
150 }
151 
152 void ossimEckert6Projection::setCentralMeridian(double centralMeridian)
153 {
154  Eck6_Origin_Long = centralMeridian;
155  update();
156 }
157 
158 bool ossimEckert6Projection::saveState(ossimKeywordlist& kwl, const char* prefix) const
159 {
160  return ossimMapProjection::saveState(kwl, prefix);
161 }
162 
163 bool ossimEckert6Projection::loadState(const ossimKeywordlist& kwl, const char* prefix)
164 {
165  bool flag = ossimMapProjection::loadState(kwl, prefix);
166 
167  const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
168 
169  setDefaults();
170 
172  {
175  }
176 
177  update();
178 
179  return flag;
180 }
181 
182 /***************************************************************************/
183 /*
184  * FUNCTIONS
185  */
186 
187 
189  double f,
190  double Central_Meridian,
191  double False_Easting,
192  double False_Northing)
193 { /* Begin Set_Eckert6_Parameters */
194 /*
195  * The function Set_Eckert6_Parameters receives the ellipsoid parameters and
196  * Eckert VI projection parameters as inputs, and sets the corresponding state
197  * variables. If any errors occur, the error code(s) are returned by the
198  * function, otherwise ECK6_NO_ERROR is returned.
199  *
200  * a : Semi-major axis of ellipsoid, in meters (input)
201  * f : Flattening of ellipsoid (input)
202  * Central_Meridian : Longitude in radians at the center of (input)
203  * the projection
204  * False_Easting : A coordinate value in meters assigned to the
205  * central meridian of the projection. (input)
206  * False_Northing : A coordinate value in meters assigned to the
207  * origin latitude of the projection (input)
208  */
209 
210  double Ra; /* Spherical radius */
211 // double inv_f = 1 / f;
212  long Error_Code = ECK6_NO_ERROR;
213 
214 // if (a <= 0.0)
215 // { /* Semi-major axis must be greater than zero */
216 // Error_Code |= ECK6_A_ERROR;
217 // }
218 // if ((inv_f < 250) || (inv_f > 350))
219 // { /* Inverse flattening must be between 250 and 350 */
220 // Error_Code |= ECK6_INV_F_ERROR;
221 // }
222 // if ((Central_Meridian < -PI) || (Central_Meridian > TWO_PI))
223 // { /* origin longitude out of range */
224 // Error_Code |= ECK6_CENT_MER_ERROR;
225 // }
226  if (!Error_Code)
227  { /* no errors */
228  Eck6_a = a;
229  Eck6_f = f;
230  es2 = 2 * Eck6_f - Eck6_f * Eck6_f;
231  es4 = es2 * es2;
232  es6 = es4 * es2;
233  /* spherical radius */
234  Ra = Eck6_a * (1.0 - es2 / 6.0 - 17.0 * es4 / 360.0 - 67.0 * es6 /3024.0);
235  Ra_Over_Sqrt_Two_Plus_PI = Ra / (sqrt(2.0 + M_PI));
237 // if (Central_Meridian > PI)
238 // Central_Meridian -= TWO_PI;
239  Eck6_Origin_Long = Central_Meridian;
240  Eck6_False_Easting = False_Easting;
241  Eck6_False_Northing = False_Northing;
242  if (Eck6_Origin_Long > 0)
243  {
244  Eck6_Max_Easting = 17555761.0;
245  Eck6_Min_Easting = -17653839.0;
246  }
247  else if (Eck6_Origin_Long < 0)
248  {
249  Eck6_Max_Easting = 17653838.0;
250  Eck6_Min_Easting = -17555761.0;
251  }
252  else
253  {
254  Eck6_Max_Easting = 17653838.0;
255  Eck6_Min_Easting = -17653838.0;
256  }
257 
258  } /* End if(!Error_Code) */
259  return (Error_Code);
260 } /* End Set_Eckert6_Parameters */
261 
262 
264  double *f,
265  double *Central_Meridian,
266  double *False_Easting,
267  double *False_Northing)const
268 { /* Begin Get_Eckert6_Parameters */
269 /*
270  * The function Get_Eckert6_Parameters returns the current ellipsoid
271  * parameters and Eckert VI projection parameters.
272  *
273  * a : Semi-major axis of ellipsoid, in meters (output)
274  * f : Flattening of ellipsoid (output)
275  * Central_Meridian : Longitude in radians at the center of (output)
276  * the projection
277  * False_Easting : A coordinate value in meters assigned to the
278  * central meridian of the projection. (output)
279  * False_Northing : A coordinate value in meters assigned to the
280  * origin latitude of the projection (output)
281  */
282 
283  *a = Eck6_a;
284  *f = Eck6_f;
285  *Central_Meridian = Eck6_Origin_Long;
286  *False_Easting = Eck6_False_Easting;
287  *False_Northing = Eck6_False_Northing;
288 
289  return;
290 } /* End Get_Eckert6_Parameters */
291 
292 
294  double Longitude,
295  double *Easting,
296  double *Northing)const
297 
298 { /* Begin Convert_Geodetic_To_Eckert6 */
299 /*
300  * The function Convert_Geodetic_To_Eckert6 converts geodetic (latitude and
301  * longitude) coordinates to Eckert VI projection (easting and northing)
302  * coordinates, according to the current ellipsoid and Eckert VI projection
303  * parameters. If any errors occur, the error code(s) are returned by the
304  * function, otherwise ECK6_NO_ERROR is returned.
305  *
306  * Latitude : Latitude (phi) in radians (input)
307  * Longitude : Longitude (lambda) in radians (input)
308  * Easting : Easting (X) in meters (output)
309  * Northing : Northing (Y) in meters (output)
310  */
311 
312  double slat = sin(Latitude);
313  double dlam; /* Longitude - Central Meridan */
314  double theta = Latitude;
315  double delta_theta = 1.0;
316  double dt_tolerance = 4.85e-10; /* approximately 1/1000th of
317  an arc second or 1/10th meter */
318  long Error_Code = ECK6_NO_ERROR;
319 
320 // if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2))
321 // { /* Latitude out of range */
322 // Error_Code |= ECK6_LAT_ERROR;
323 // }
324 // if ((Longitude < -PI) || (Longitude > TWO_PI))
325 // { /* Longitude out of range */
326 // Error_Code|= ECK6_LON_ERROR;
327 // }
328 
329  if (!Error_Code)
330  { /* no errors */
331 
332  dlam = Longitude - Eck6_Origin_Long;
333 // if (dlam > PI)
334 // {
335 // dlam -= TWO_PI;
336 // }
337 // if (dlam < -PI)
338 // {
339 // dlam += TWO_PI;
340 // }
341  while (fabs(delta_theta) > dt_tolerance)
342  {
343  delta_theta = -(theta + sin(theta) - one_PLUS_PI_OVER_2 *
344  slat) / (1.0 + cos(theta));
345  theta += delta_theta;
346  }
347  *Easting = Ra_Over_Sqrt_Two_Plus_PI * dlam * (1.0 + cos(theta)) +
349  *Northing = 2.0 * Ra_Over_Sqrt_Two_Plus_PI * theta + Eck6_False_Northing;
350 
351  }
352  return (Error_Code);
353 
354 } /* End Convert_Geodetic_To_Eckert6 */
355 
356 
358  double Northing,
359  double *Latitude,
360  double *Longitude)const
361 { /* Begin Convert_Eckert6_To_Geodetic */
362 /*
363  * The function Convert_Eckert6_To_Geodetic converts Eckert VI projection
364  * (easting and northing) coordinates to geodetic (latitude and longitude)
365  * coordinates, according to the current ellipsoid and Eckert VI projection
366  * coordinates. If any errors occur, the error code(s) are returned by the
367  * function, otherwise ECK6_NO_ERROR is returned.
368  *
369  * Easting : Easting (X) in meters (input)
370  * Northing : Northing (Y) in meters (input)
371  * Latitude : Latitude (phi) in radians (output)
372  * Longitude : Longitude (lambda) in radians (output)
373  */
374 
375  double dx, dy;
376  double theta;
377  double i;
378 
379  long Error_Code = ECK6_NO_ERROR;
380 
381 // if ((Easting < (Eck6_False_Easting + Eck6_Min_Easting))
382 // || (Easting > (Eck6_False_Easting + Eck6_Max_Easting)))
383 // { /* Easting out of range */
384 // Error_Code |= ECK6_EASTING_ERROR;
385 // }
386 // if ((Northing < (Eck6_False_Northing - Eck6_Delta_Northing))
387 // || (Northing > (Eck6_False_Northing + Eck6_Delta_Northing)))
388 // { /* Northing out of range */
389 // Error_Code |= ECK6_NORTHING_ERROR;
390 // }
391 
392  if (!Error_Code)
393  {
394  dy = Northing - Eck6_False_Northing;
395  dx = Easting - Eck6_False_Easting;
396  theta = Inv_Ra_Over_Sqrt_Two_Plus_PI * dy / 2.0;
397  i = (theta + sin(theta)) / one_PLUS_PI_OVER_2;
398  if (i > 1.0)
399  *Latitude = MAX_LAT;
400  else if (i < -1.0)
401  *Latitude = -MAX_LAT;
402  else
403  *Latitude = asin(i);
404  *Longitude = Eck6_Origin_Long + Inv_Ra_Over_Sqrt_Two_Plus_PI * dx / (1 + cos(theta));
405 
406 // if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */
407 // *Latitude = PI_OVER_2;
408 // else if (*Latitude < -PI_OVER_2)
409 // *Latitude = -PI_OVER_2;
410 
411 // if (*Longitude > PI)
412 // *Longitude -= TWO_PI;
413 // if (*Longitude < -PI)
414 // *Longitude += TWO_PI;
415 
416 // if (*Longitude > PI) /* force distorted values to 180, -180 degrees */
417 // *Longitude = PI;
418 // else if (*Longitude < -PI)
419 // *Longitude = -PI;
420 
421  }
422  return (Error_Code);
423 
424 } /* End Convert_Eckert6_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.
long Set_Eckert6_Parameters(double a, double f, double Central_Meridian, double False_Easting, double False_Northing)
long Convert_Eckert6_To_Geodetic(double Easting, double Northing, double *Latitude, double *Longitude) const
#define DEG_PER_RAD
Represents serializable keyword/value map.
ossimEckert6Projection(const ossimEllipsoid &ellipsoid=ossimEllipsoid(), const ossimGpt &origin=ossimGpt())
const char * find(const char *key) const
double y
Definition: ossimDpt.h:165
virtual const ossimString & code() const
Definition: ossimDatum.h:57
void setFalseNorthing(double falseNorthing)
#define MAX_LAT
long Convert_Geodetic_To_Eckert6(double Latitude, double Longitude, double *Easting, double *Northing) const
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
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
const ossimDatum * datum() const
datum().
Definition: ossimGpt.h:196
#define M_PI
const double & getA() const
double lonr() const
Returns the longitude in radian measure.
Definition: ossimGpt.h:76
void Get_Eckert6_Parameters(double *a, double *f, double *Central_Meridian, double *False_Easting, double *False_Northing) const
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
double x
Definition: ossimDpt.h:164
double latr() const
latr().
Definition: ossimGpt.h:66
#define ECK6_NO_ERROR
const double one_PLUS_PI_OVER_2
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.
virtual ossimGpt inverse(const ossimDpt &eastingNorthing) const
Will take a point in meters and convert it to ground.
void setFalseEastingNorthing(double falseEasting, double falseNorthing)
void setFalseEasting(double falseEasting)
void setCentralMeridian(double centralMeridian)
virtual ossimDpt forward(const ossimGpt &latLon) const
All map projections will convert the world coordinate to an easting northing (Meters).
const ossimDatum * theDatum
This is only set if we want to have built in datum shifting.