OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimCylEquAreaProjection.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 Cylinder Equal Area projection code.
11 //*******************************************************************
12 // $Id: ossimCylEquAreaProjection.cpp 9094 2006-06-13 19:12:40Z dburken $
15 
16 RTTI_DEF1(ossimCylEquAreaProjection, "ossimCylEquAreaProjection", ossimMapProjection)
17 
18 /***************************************************************************/
19 /*
20  * DEFINES
21  */
22 
23 #define CYEQ_NO_ERROR 0x0000
24 #define CYEQ_LAT_ERROR 0x0001
25 #define CYEQ_LON_ERROR 0x0002
26 #define CYEQ_EASTING_ERROR 0x0004
27 #define CYEQ_NORTHING_ERROR 0x0008
28 #define CYEQ_ORIGIN_LAT_ERROR 0x0010
29 #define CYEQ_CENT_MER_ERROR 0x0020
30 #define CYEQ_A_ERROR 0x0040
31 #define CYEQ_B_ERROR 0x0080
32 #define CYEQ_A_LESS_B_ERROR 0x0100
33 
34 /***************************************************************************/
35 /*
36  * DEFINES
37  */
38 
39 #ifndef PI_OVER_2
40 # define PI_OVER_2 ( M_PI / 2.0)
41 #endif
42 #ifndef TWO_PI
43 # define TWO_PI (2.0 * M_PI)
44 #endif
45 #define CYLEQAR_Q(slat, x) (1.0-es2)*(slat/(1.0-x*x)-(1.0/(2.0*es))* \
46  log((1.0-x)/(1.0+x)))
47 #define CYEQ_COEFF_TIMES_SIN(coeff, c, Beta) (coeff * sin(c * Beta))
48 #define ONE (1.0 * M_PI / 180.0) /* 1 degree in radians */
49 
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  Cyeq_False_Easting = falseEasting;
66  Cyeq_False_Northing = falseNorthing;
67  Cyeq_Max_Easting = 20037509.0;
68  Cyeq_Min_Easting = -20037509.0;
69  Cyeq_Delta_Northing = 6363886.0;
70 
71  update();
72 }
73 
75 {
76  Cyeq_False_Easting = falseEasting;
77  update();
78 }
79 
81 {
82  Cyeq_False_Northing = falseNorthing;
83  update();
84 }
85 
87  double falseNorthing)
88 {
89  Cyeq_False_Easting = falseEasting;
90  Cyeq_False_Northing = falseNorthing;
91  update();
92 }
93 
95 {
96  Cyeq_False_Easting = 0.0;
97  Cyeq_False_Northing = 0.0;
98  Cyeq_Max_Easting = 20037509.0;
99  Cyeq_Min_Easting = -20037509.0;
100  Cyeq_Delta_Northing = 6363886.0;
101 }
102 
104 {
105  Cyeq_Max_Easting = 20037509.0;
106  Cyeq_Min_Easting = -20037509.0;
107  Cyeq_Delta_Northing = 6363886.0;
108 
111  theOrigin.latr(),
112  theOrigin.lonr(),
115 
118 
120 }
121 
122 
124 {
125  double lat = 0.0;
126  double lon = 0.0;
127 
128  Convert_Cyl_Eq_Area_To_Geodetic(eastingNorthing.x,
129  eastingNorthing.y,
130  &lat,
131  &lon);
132  return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0, theDatum);
133 }
134 
136 {
137  double easting = 0.0;
138  double northing = 0.0;
139  ossimGpt gpt = latLon;
140 
141  if (theDatum)
142  {
143  if (theDatum->code() != latLon.datum()->code())
144  {
145  gpt.changeDatum(theDatum); // Shift to our datum.
146  }
147  }
148 
150  gpt.lonr(),
151  &easting,
152  &northing);
153 
154  return ossimDpt(easting, northing);
155 
156 }
157 
158 bool ossimCylEquAreaProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const
159 {
160  return ossimMapProjection::saveState(kwl, prefix);
161 }
162 
163 bool ossimCylEquAreaProjection::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 Origin_Latitude,
191  double Central_Meridian,
192  double False_Easting,
193  double False_Northing)
194 { /* Begin Set_Cyl_Eq_Area_Parameters */
195 /*
196  * The function Set_Cyl_Eq_Area_Parameters receives the ellipsoid parameters and
197  * Cylindrical Equal Area projcetion parameters as inputs, and sets the corresponding
198  * state variables. If any errors occur, the error code(s) are returned by the
199  * function, otherwise CYEQ_NO_ERROR is returned.
200  *
201  * a : Semi-major axis of ellipsoid, in meters (input)
202  * f : Flattening of ellipsoid (input)
203  * Origin_Latitude : Latitude in radians at which the (input)
204  * point scale factor is 1.0
205  * Central_Meridian : Longitude in radians at the center of (input)
206  * the projection
207  * False_Easting : A coordinate value in meters assigned to the
208  * central meridian of the projection. (input)
209  * False_Northing : A coordinate value in meters assigned to the
210  * origin latitude of the projection (input)
211  */
212 
213  double Sin_Cyeq_Origin_Lat;
214  double temp;
215 // double inv_f = 1 / f;
216  long Error_Code = CYEQ_NO_ERROR;
217 
218 // if (a <= 0.0)
219 // { /* Semi-major axis must be greater than zero */
220 // Error_Code |= CYEQ_A_ERROR;
221 // }
222 // if ((inv_f < 250) || (inv_f > 350))
223 // { /* Inverse flattening must be between 250 and 350 */
224 // Error_Code |= CYEQ_INV_F_ERROR;
225 // }
226 // if ((Origin_Latitude < -PI_OVER_2) || (Origin_Latitude > PI_OVER_2))
227 // { /* origin latitude out of range */
228 // Error_Code |= CYEQ_ORIGIN_LAT_ERROR;
229 // }
230 // if ((Central_Meridian < -PI) || (Central_Meridian > TWO_PI))
231 // { /* origin longitude out of range */
232 // Error_Code |= CYEQ_CENT_MER_ERROR;
233 // }
234  if (!Error_Code)
235  { /* no errors */
236  Cyeq_a = a;
237  Cyeq_f = f;
238  Cyeq_Origin_Lat = Origin_Latitude;
239  if (Central_Meridian > M_PI)
240  Central_Meridian -= TWO_PI;
241  Cyeq_Origin_Long = Central_Meridian;
242  Cyeq_False_Northing = False_Northing;
243  Cyeq_False_Easting = False_Easting;
244  es2 = 2 * Cyeq_f - Cyeq_f * Cyeq_f;
245  es4 = es2 * es2;
246  es6 = es4 * es2;
247  es = sqrt(es2);
248  c0 = es2 / 3.0 + 31.0 * es4 / 180.0 + 517.0 * es6 / 5040.0;
249  c1 = 23.0 * es4 / 360.0 + 251.0 * es6 / 3780.0;
250  c2 = 761.0 * es6 / 45360.0;
251  Sin_Cyeq_Origin_Lat = sin(Cyeq_Origin_Lat);
252  k0 = cos(Cyeq_Origin_Lat) / sqrt(1.0 - es2 * Sin_Cyeq_Origin_Lat * Sin_Cyeq_Origin_Lat);
253  Cyeq_a_k0 = Cyeq_a * k0;
254  two_k0 = 2.0 * k0;
255 
256  if (Cyeq_Origin_Long > 0)
257  {
261  }
262  else if (Cyeq_Origin_Long < 0)
263  {
267  }
268  else
269  {
272  }
273 
274  } /* End if(!Error_Code) */
275  return (Error_Code);
276 } /* End Set_Cyl_Eq_Area_Parameters */
277 
278 
280  double *f,
281  double *Origin_Latitude,
282  double *Central_Meridian,
283  double *False_Easting,
284  double *False_Northing)const
285 { /* Begin Get_Cyl_Eq_Area_Parameters */
286 /*
287  * The function Get_Cyl_Eq_Area_Parameters returns the current ellipsoid
288  * parameters, and Cylindrical Equal Area projection parameters.
289  *
290  * a : Semi-major axis of ellipsoid, in meters (output)
291  * f : Flattening of ellipsoid (output)
292  * Origin_Latitude : Latitude in radians at which the (output)
293  * point scale factor is 1.0
294  * Central_Meridian : Longitude in radians at the center of (output)
295  * the projection
296  * False_Easting : A coordinate value in meters assigned to the
297  * central meridian of the projection. (output)
298  * False_Northing : A coordinate value in meters assigned to the
299  * origin latitude of the projection (output)
300  */
301 
302  *a = Cyeq_a;
303  *f = Cyeq_f;
304  *Origin_Latitude = Cyeq_Origin_Lat;
305  *Central_Meridian = Cyeq_Origin_Long;
306  *False_Easting = Cyeq_False_Easting;
307  *False_Northing = Cyeq_False_Northing;
308  return;
309 } /* End Get_Cyl_Eq_Area_Parameters */
310 
311 
313  double Longitude,
314  double *Easting,
315  double *Northing)const
316 { /* Begin Convert_Geodetic_To_Cyl_Eq_Area */
317 /*
318  * The function Convert_Geodetic_To_Cyl_Eq_Area converts geodetic (latitude and
319  * longitude) coordinates to Cylindrical Equal Area projection (easting and northing)
320  * coordinates, according to the current ellipsoid and Cylindrical Equal Area projection
321  * parameters. If any errors occur, the error code(s) are returned by the
322  * function, otherwise CYEQ_NO_ERROR is returned.
323  *
324  * Latitude : Latitude (phi) in radians (input)
325  * Longitude : Longitude (lambda) in radians (input)
326  * Easting : Easting (X) in meters (output)
327  * Northing : Northing (Y) in meters (output)
328  */
329 
330  double dlam; /* Longitude - Central Meridan */
331  double qq;
332  double x;
333  double sin_lat = sin(Latitude);
334  long Error_Code = CYEQ_NO_ERROR;
335 
336 // if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2))
337 // { /* Latitude out of range */
338 // Error_Code |= CYEQ_LAT_ERROR;
339 // }
340 // if ((Longitude < -PI) || (Longitude > TWO_PI))
341 // { /* Longitude out of range */
342 // Error_Code |= CYEQ_LON_ERROR;
343 // }
344  if (!Error_Code)
345  { /* no errors */
346  dlam = Longitude - Cyeq_Origin_Long;
347 // if (dlam > PI)
348 // {
349 // dlam -= TWO_PI;
350 // }
351 // if (dlam < -PI)
352 // {
353 // dlam += TWO_PI;
354 // }
355  x = es * sin_lat;
356  qq = CYLEQAR_Q(sin_lat,x);
357  *Easting = Cyeq_a_k0 * dlam + Cyeq_False_Easting;
358  *Northing = Cyeq_a * qq / two_k0 + Cyeq_False_Northing;
359  }
360  return (Error_Code);
361 } /* End Convert_Geodetic_To_Cyl_Eq_Area */
362 
363 
365  double Northing,
366  double *Latitude,
367  double *Longitude)const
368 { /* Begin Convert_Cyl_Eq_Area_To_Geodetic */
369 /*
370  * The function Convert_Cyl_Eq_Area_To_Geodetic converts
371  * Cylindrical Equal Area projection (easting and northing) coordinates
372  * to geodetic (latitude and longitude) coordinates, according to the
373  * current ellipsoid and Cylindrical Equal Area projection
374  * coordinates. If any errors occur, the error code(s) are returned by the
375  * function, otherwise CYEQ_NO_ERROR is returned.
376  *
377  * Easting : Easting (X) in meters (input)
378  * Northing : Northing (Y) in meters (input)
379  * Latitude : Latitude (phi) in radians (output)
380  * Longitude : Longitude (lambda) in radians (output)
381  */
382 
383  double sin2beta, sin4beta, sin6beta;
384  double dx; /* Delta easting - Difference in easting (easting-FE) */
385  double dy; /* Delta northing - Difference in northing (northing-FN) */
386  double qp;
387  double beta;
388  double sin_lat = sin(PI_OVER_2);
389  double i;
390  double x;
391  long Error_Code = CYEQ_NO_ERROR;
392 
393 // if ((Easting < (Cyeq_False_Easting + Cyeq_Min_Easting))
394 // || (Easting > (Cyeq_False_Easting + Cyeq_Max_Easting)))
395 // { /* Easting out of range */
396 // Error_Code |= CYEQ_EASTING_ERROR;
397 // }
398 // if ((Northing < (Cyeq_False_Northing - fabs(Cyeq_Delta_Northing)))
399 // || (Northing > (Cyeq_False_Northing + fabs(Cyeq_Delta_Northing))))
400 // { /* Northing out of range */
401 // Error_Code |= CYEQ_NORTHING_ERROR;
402 // }
403  if (!Error_Code)
404  { /* no errors */
405  dy = Northing - Cyeq_False_Northing;
406  dx = Easting - Cyeq_False_Easting;
407  x = es * sin_lat;
408  qp = CYLEQAR_Q(sin_lat,x);
409  i = two_k0 * dy / (Cyeq_a * qp);
410  if (i > 1.0)
411  i = 1.0;
412  else if (i < -1.0)
413  i = -1.0;
414  beta = asin(i);
415  sin2beta = CYEQ_COEFF_TIMES_SIN(c0, 2.0, beta);
416  sin4beta = CYEQ_COEFF_TIMES_SIN(c1, 4.0, beta);
417  sin6beta = CYEQ_COEFF_TIMES_SIN(c2, 6.0, beta);
418  *Latitude = beta + sin2beta + sin4beta + sin6beta;
419  *Longitude = Cyeq_Origin_Long + dx / Cyeq_a_k0;
420 
421 // if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */
422 // *Latitude = PI_OVER_2;
423 // else if (*Latitude < -PI_OVER_2)
424 // *Latitude = -PI_OVER_2;
425 
426 // if (*Longitude > PI)
427 // *Longitude -= TWO_PI;
428 // if (*Longitude < -PI)
429 // *Longitude += TWO_PI;
430 
431 // if (*Longitude > PI) /* force distorted values to 180, -180 degrees */
432 // *Longitude = PI;
433 // else if (*Longitude < -PI)
434 // *Longitude = -PI;
435 
436 
437  }
438  return (Error_Code);
439 } /* End Convert_Cyl_Eq_Area_To_Geodetic */
ossim_uint32 x
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
ossimCylEquAreaProjection(const ossimEllipsoid &ellipsoid=ossimEllipsoid(), const ossimGpt &origin=ossimGpt())
void setFalseEastingNorthing(double falseEasting, double falseNorthing)
#define CYEQ_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 ossimGpt inverse(const ossimDpt &projectedPoint) const
Will take a point in meters and convert it to ground.
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
#define CYEQ_COEFF_TIMES_SIN(coeff, c, Beta)
#define PI_OVER_2
long Set_Cyl_Eq_Area_Parameters(double a, double f, double Origin_Latitude, double Central_Meridian, double False_Easting, double False_Northing)
#define TWO_PI
#define M_PI
virtual ossimDpt forward(const ossimGpt &worldPoint) const
All map projections will convert the world coordinate to an easting northing (Meters).
long Convert_Cyl_Eq_Area_To_Geodetic(double Easting, double Northing, double *Latitude, double *Longitude) const
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.
void setFalseNorthing(double falseNorthing)
void setFalseEasting(double falseEasting)
#define CYLEQAR_Q(slat, x)
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
double x
Definition: ossimDpt.h:164
double latr() const
latr().
Definition: ossimGpt.h:66
void Get_Cyl_Eq_Area_Parameters(double *a, double *f, double *Origin_Latitude, double *Central_Meridian, double *False_Easting, double *False_Northing) const
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.
long Convert_Geodetic_To_Cyl_Eq_Area(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.