OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimEckert4Projection.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 Eckert4 projection code.
11 //*******************************************************************
12 // $Id: ossimEckert4Projection.cpp 9094 2006-06-13 19:12:40Z dburken $
14 
16 
17 RTTI_DEF1(ossimEckert4Projection, "ossimEckert4Projection", ossimMapProjection)
18 
19 
20 /***************************************************************************/
21 /*
22  * DEFINES
23  */
24 
25 #ifndef PI_OVER_2
26 # define PI_OVER_2 ( M_PI / 2.0)
27 #endif
28 #ifndef TWO_PI
29 # define TWO_PI (2.0 * M_PI)
30 #endif
31 #define NUM(Theta, SinTheta, CosTheta) (Theta + SinTheta * CosTheta + 2.0 * SinTheta)
32 
33 
34 #define ECK4_NO_ERROR 0x0000
35 #define ECK4_LAT_ERROR 0x0001
36 #define ECK4_LON_ERROR 0x0002
37 #define ECK4_EASTING_ERROR 0x0004
38 #define ECK4_NORTHING_ERROR 0x0008
39 #define ECK4_CENT_MER_ERROR 0x0020
40 #define ECK4_A_ERROR 0x0040
41 #define ECK4_B_ERROR 0x0080
42 #define ECK4_A_LESS_B_ERROR 0x0100
43 
44 /***************************************************************************/
45 /*
46  * GLOBALS
47  */
48 
49 const double two_PLUS_PI_OVER_2 = (2.0 + M_PI / 2.0);
50 
52  const ossimGpt& origin)
53  :ossimMapProjection(ellipsoid, origin)
54 {
55  setDefaults();
56  update();
57 }
58 
60  const ossimGpt& origin,
61  double falseEasting,
62  double falseNorthing)
63  :ossimMapProjection(ellipsoid, origin)
64 {
65 
66  Eck4_False_Easting = falseEasting;
67  Eck4_False_Northing = falseNorthing;
68  Eck4_Delta_Northing = 8451144.0;
69  Eck4_Max_Easting = 16902288.0;
70  Eck4_Min_Easting = -16902288.0;
71 
72  update();
73 }
74 
75 
77 {
78 
81  theOrigin.lonr(),
84 
87 
89 }
90 
92 {
93  double lat = 0.0;
94  double lon = 0.0;
95 
96  Convert_Eckert4_To_Geodetic(eastingNorthing.x,
97  eastingNorthing.y,
98  &lat,
99  &lon);
100 
101  return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum);
102 }
103 
105 {
106  double easting = 0.0;
107  double northing = 0.0;
108  ossimGpt gpt = latLon;
109 
110  if (theDatum)
111  {
112  if (theDatum->code() != latLon.datum()->code())
113  {
114  gpt.changeDatum(theDatum); // Shift to our datum.
115  }
116  }
117 
119  gpt.lonr(),
120  &easting,
121  &northing);
122 
123  return ossimDpt(easting, northing);
124 }
125 
127 {
128  Eck4_False_Easting = falseEasting;
129  update();
130 }
131 
133 {
134  Eck4_False_Northing = falseNorthing;
135  update();
136 }
137 
139  double falseNorthing)
140 {
141  Eck4_False_Easting = falseEasting;
142  Eck4_False_Northing = falseNorthing;
143  update();
144 }
145 
147 {
148  Eck4_Delta_Northing = 8451144.0;
149  Eck4_Max_Easting = 16902288.0;
150  Eck4_Min_Easting = -16902288.0;
151  Eck4_False_Easting = 0.0;
152  Eck4_False_Northing = 0.0;
153 }
154 
155 bool ossimEckert4Projection::saveState(ossimKeywordlist& kwl, const char* prefix) const
156 {
157  return ossimMapProjection::saveState(kwl, prefix);
158 }
159 
160 bool ossimEckert4Projection::loadState(const ossimKeywordlist& kwl, const char* prefix)
161 {
162  bool flag = ossimMapProjection::loadState(kwl, prefix);
163 
164  const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
165 
166  setDefaults();
167 
169  {
172  }
173 
174  update();
175 
176  return flag;
177 }
178 
179 /***************************************************************************/
180 /*
181  * FUNCTIONS
182  */
183 
184 
186  double f,
187  double Central_Meridian,
188  double False_Easting,
189  double False_Northing)
190 
191 { /* Begin Set_Eckert4_Parameters */
192 /*
193  * The function Set_Eckert4_Parameters receives the ellipsoid parameters and
194  * projection parameters as inputs, and sets the corresponding state
195  * variables. If any errors occur, the error code(s) are returned by the
196  * function, otherwise ECK4_NO_ERROR is returned.
197  *
198  * a : Semi-major axis of ellipsoid, in meters (input)
199  * f : Flattening of ellipsoid (input)
200  * Central_Meridian : Longitude in radians at the center of (input)
201  * the projection
202  * False_Easting : A coordinate value in meters assigned to the
203  * central meridian of the projection. (input)
204  * False_Northing : A coordinate value in meters assigned to the
205  * origin latitude of the projection (input)
206  */
207 
208  double Ra; /* Spherical radius */
209 // double inv_f = 1 / f;
210  long Error_Code = ECK4_NO_ERROR;
211 
212 // if (a <= 0.0)
213 // { /* Semi-major axis must be greater than zero */
214 // Error_Code |= ECK4_A_ERROR;
215 // }
216 // if ((inv_f < 250) || (inv_f > 350))
217 // { /* Inverse flattening must be between 250 and 350 */
218 // Error_Code |= ECK4_INV_F_ERROR;
219 // }
220 // if ((Central_Meridian < -PI) || (Central_Meridian > TWO_PI))
221 // { /* origin longitude out of range */
222 // Error_Code |= ECK4_CENT_MER_ERROR;
223 // }
224  if (!Error_Code)
225  { /* no errors */
226  Eck4_a = a;
227  Eck4_f = f;
228  es2 = 2 * Eck4_f - Eck4_f * Eck4_f;
229  es4 = es2 * es2;
230  es6 = es4 * es2;
231  /* spherical radius */
232  Ra = Eck4_a * (1.0 - es2 / 6.0 - 17.0 * es4 / 360.0 - 67.0 * es6 / 3024.0);
233  Ra0 = 0.4222382 * Ra;
234  Ra1 = 1.3265004 * Ra;
235 // if (Central_Meridian > PI)
236 // Central_Meridian -= TWO_PI;
237  Eck4_Origin_Long = Central_Meridian;
238  Eck4_False_Easting = False_Easting;
239  Eck4_False_Northing = False_Northing;
240  if (Eck4_Origin_Long > 0)
241  {
242  Eck4_Max_Easting = 16808386.0;
243  Eck4_Min_Easting = -16902288.0;
244  }
245  else if (Eck4_Origin_Long < 0)
246  {
247  Eck4_Max_Easting = 16902288.0;
248  Eck4_Min_Easting = -16808386.0;
249  }
250  else
251  {
252  Eck4_Max_Easting = 16902288.0;
253  Eck4_Min_Easting = -16902288.0;
254  }
255 
256  } /* End if(!Error_Code) */
257  return (Error_Code);
258 } /* End Set_Eckert4_Parameters */
259 
260 
262  double *f,
263  double *Central_Meridian,
264  double *False_Easting,
265  double *False_Northing)const
266 { /* Begin Get_Eckert4_Parameters */
267 /*
268  * The function Get_Eckert4_Parameters returns the current ellipsoid
269  * parameters and Eckert IV projection parameters.
270  *
271  * a : Semi-major axis of ellipsoid, in meters (output)
272  * f : Flattening of ellipsoid (output)
273  * Central_Meridian : Longitude in radians at the center of (output)
274  * the projection
275  * False_Easting : A coordinate value in meters assigned to the
276  * central meridian of the projection. (output)
277  * False_Northing : A coordinate value in meters assigned to the
278  * origin latitude of the projection (output)
279  */
280 
281  *a = Eck4_a;
282  *f = Eck4_f;
283  *Central_Meridian = Eck4_Origin_Long;
284  *False_Easting = Eck4_False_Easting;
285  *False_Northing = Eck4_False_Northing;
286  return;
287 } /* End Get_Eckert4_Parameters */
288 
289 
291  double Longitude,
292  double *Easting,
293  double *Northing)const
294 
295 { /* Begin Convert_Geodetic_To_Eckert4 */
296 /*
297  * The function Convert_Geodetic_To_Eckert4 converts geodetic (latitude and
298  * longitude) coordinates to Eckert IV projection (easting and northing)
299  * coordinates, according to the current ellipsoid, spherical radius and
300  * Eckert IV projection parameters.
301  * If any errors occur, the error code(s) are returned by the
302  * function, otherwise ECK4_NO_ERROR is returned.
303  *
304  * Latitude : Latitude (phi) in radians (input)
305  * Longitude : Longitude (lambda) in radians (input)
306  * Easting : Easting (X) in meters (output)
307  * Northing : Northing (Y) in meters (output)
308  */
309 
310  double slat = sin(Latitude);
311  double sin_theta, cos_theta;
312  double num;
313  double dlam; /* Longitude - Central Meridan */
314  double theta = Latitude / 2.0;
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 = ECK4_NO_ERROR;
319 
320 // if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2))
321 // { /* Latitude out of range */
322 // Error_Code |= ECK4_LAT_ERROR;
323 // }
324 // if ((Longitude < -PI) || (Longitude > TWO_PI))
325 // { /* Longitude out of range */
326 // Error_Code|= ECK4_LON_ERROR;
327 // }
328 
329  if (!Error_Code)
330  { /* no errors */
331 
332  dlam = Longitude - Eck4_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  sin_theta = sin(theta);
344  cos_theta = cos(theta);
345  num = NUM(theta, sin_theta, cos_theta);
346  delta_theta = -(num - two_PLUS_PI_OVER_2 * slat) /
347  (2.0 * cos_theta * (1.0 + cos_theta));
348  theta += delta_theta;
349  }
350  *Easting = Ra0 * dlam * (1.0 + cos(theta)) + Eck4_False_Easting;
351  *Northing = Ra1 * sin(theta) + Eck4_False_Northing;
352  }
353 
354  return (Error_Code);
355 
356 } /* End Convert_Geodetic_To_Eckert4 */
357 
358 
360  double Northing,
361  double *Latitude,
362  double *Longitude)const
363 { /* Begin Convert_Eckert4_To_Geodetic */
364 /*
365  * The function Convert_Eckert4_To_Geodetic converts Eckert IV projection
366  * (easting and northing) coordinates to geodetic (latitude and longitude)
367  * coordinates, according to the current ellipsoid, spherical radius and
368  * Eckert IV projection coordinates.
369  * If any errors occur, the error code(s) are returned by the
370  * function, otherwise ECK4_NO_ERROR is returned.
371  *
372  * Easting : Easting (X) in meters (input)
373  * Northing : Northing (Y) in meters (input)
374  * Latitude : Latitude (phi) in radians (output)
375  * Longitude : Longitude (lambda) in radians (output)
376  */
377 
378  double theta;
379  double sin_theta, cos_theta;
380  double num;
381  double dx, dy;
382  double i;
383 
384  long Error_Code = ECK4_NO_ERROR;
385 
386 // if ((Easting < (Eck4_False_Easting + Eck4_Min_Easting))
387 // || (Easting > (Eck4_False_Easting + Eck4_Max_Easting)))
388 // { /* Easting out of range */
389 // Error_Code |= ECK4_EASTING_ERROR;
390 // }
391 // if ((Northing < (Eck4_False_Northing - Eck4_Delta_Northing))
392 // || (Northing > (Eck4_False_Northing + Eck4_Delta_Northing)))
393 // { /* Northing out of range */
394 // Error_Code |= ECK4_NORTHING_ERROR;
395 // }
396 
397  if (!Error_Code)
398  {
399  dy = Northing - Eck4_False_Northing;
400  dx = Easting - Eck4_False_Easting;
401  i = dy / Ra1;
402  if (i > 1.0)
403  i = 1.0;
404  else if (i < -1.0)
405  i = -1.0;
406 
407  theta = asin(i);
408  sin_theta = sin(theta);
409  cos_theta = cos(theta);
410  num = NUM(theta, sin_theta, cos_theta);
411 
412  *Latitude = asin(num / two_PLUS_PI_OVER_2);
413  *Longitude = Eck4_Origin_Long + dx / (Ra0 * (1 + cos_theta));
414 
415 // if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */
416 // *Latitude = PI_OVER_2;
417 // else if (*Latitude < -PI_OVER_2)
418 // *Latitude = -PI_OVER_2;
419 
420 // if (*Longitude > PI)
421 // *Longitude -= TWO_PI;
422 // if (*Longitude < -PI)
423 // *Longitude += TWO_PI;
424 
425 // if (*Longitude > PI) /* force distorted values to 180, -180 degrees */
426 // *Longitude = PI;
427 // else if (*Longitude < -PI)
428 // *Longitude = -PI;
429 
430  }
431  return (Error_Code);
432 
433 } /* End Convert_Eckert4_To_Geodetic */
434 
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 setFalseNorthing(double falseNorthing)
void setFalseEasting(double falseEasting)
long Set_Eckert4_Parameters(double a, double f, double Central_Meridian, double False_Easting, double False_Northing)
#define ECK4_NO_ERROR
#define DEG_PER_RAD
Represents serializable keyword/value map.
const char * find(const char *key) const
double y
Definition: ossimDpt.h:165
virtual const ossimString & code() const
Definition: ossimDatum.h:57
virtual ossimDpt forward(const ossimGpt &worldPoint) const
All map projections will convert the world coordinate to an easting northing (Meters).
void Get_Eckert4_Parameters(double *a, double *f, double *Central_Meridian, double *False_Easting, double *False_Northing) const
#define NUM(Theta, SinTheta, CosTheta)
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)
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
#define M_PI
const double & getA() const
double lonr() const
Returns the longitude in radian measure.
Definition: ossimGpt.h:76
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
const double two_PLUS_PI_OVER_2
ossimEckert4Projection(const ossimEllipsoid &ellipsoid=ossimEllipsoid(), const ossimGpt &origin=ossimGpt())
virtual ossimGpt inverse(const ossimDpt &projectedPoint) const
Will take a point in meters and convert it to ground.
double x
Definition: ossimDpt.h:164
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.
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
long Convert_Eckert4_To_Geodetic(double Easting, double Northing, double *Latitude, double *Longitude) const
long Convert_Geodetic_To_Eckert4(double Latitude, double Longitude, double *Easting, double *Northing) const
const ossimDatum * theDatum
This is only set if we want to have built in datum shifting.