OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimAzimEquDistProjection.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 // License: See top LICENSE.txt file.
3 //
4 // Author: Garrett Potts
5 //
6 // Description:
7 //
8 // Calls Geotrans Utm projection code.
9 //*******************************************************************
10 // $Id: ossimAzimEquDistProjection.cpp 9094 2006-06-13 19:12:40Z dburken $
11 
15 #include <ossim/base/ossimTrace.h>
16 
17 
18 #define PI_OVER_2 ( M_PI / 2.0)
19 #define ONE (1.0 * M_PI / 180.0) /* 1 degree in radians */
20 
21 #define AZEQ_NO_ERROR 0x0000
22 #define AZEQ_LAT_ERROR 0x0001
23 #define AZEQ_LON_ERROR 0x0002
24 #define AZEQ_EASTING_ERROR 0x0004
25 #define AZEQ_NORTHING_ERROR 0x0008
26 #define AZEQ_ORIGIN_LAT_ERROR 0x0010
27 #define AZEQ_CENT_MER_ERROR 0x0020
28 #define AZEQ_A_ERROR 0x0040
29 #define AZEQ_INV_F_ERROR 0x0080
30 #define AZEQ_PROJECTION_ERROR 0x0100
31 
32 RTTI_DEF1(ossimAzimEquDistProjection,"ossimAzimEquDistProjection", ossimMapProjection)
33 
35  const ossimGpt& origin)
36  :ossimMapProjection(ellipsoid,
37  origin)
38 {
39  setDefaults();
40 }
41 
43  const ossimGpt& origin,
44  double falseEasting,
45  double falseNorthing)
46  :ossimMapProjection(ellipsoid,
47  origin)
48 {
49  setFalseEastingNorthing(falseEasting, falseNorthing);
50 }
51 
53 {
56  theOrigin.latr(),
57  theOrigin.lonr(),
60 
63 
65 }
66 
68 {
69  double lat, lon;
70 
72  eastingNorthing.y,
73  &lat,
74  &lon);
75 
76  return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum);
77 }
78 
80 {
81  double easting = 0.0;
82  double northing = 0.0;
83  ossimGpt gpt = latLon;
84 
85  if (theDatum)
86  {
87  if (theDatum->code() != latLon.datum()->code())
88  {
89  gpt.changeDatum(theDatum); // Shift to our datum.
90  }
91  }
92 
94  gpt.lonr(),
95  &easting,
96  &northing);
97  return ossimDpt(easting, northing);
98 }
99 
101 {
102  Azeq_False_Easting = falseEasting;
103 
104  update();
105 }
106 
108 {
109  Azeq_False_Northing = falseNorthing;
110 
111  update();
112 }
113 
115  double falseNorthing)
116 {
117  Azeq_False_Easting = falseEasting;
118  Azeq_False_Northing = falseNorthing;
119 
120  update();
121 }
122 
124 {
125  Azeq_False_Easting = 0.0;
126  Azeq_False_Northing = 0.0;
127  update();
128 }
129 
130 bool ossimAzimEquDistProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const
131 {
132  return ossimMapProjection::saveState(kwl, prefix);
133 }
134 
135 bool ossimAzimEquDistProjection::loadState(const ossimKeywordlist& kwl, const char* prefix)
136 {
137  // Must do first...
138  bool flag = ossimMapProjection::loadState(kwl, prefix);
139 
140  const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
141  setDefaults();
143  {
146  }
147 
148  update();
149 
150  return flag;
151 }
152 
154  double f,
155  double Origin_Latitude,
156  double Central_Meridian,
157  double False_Easting,
158  double False_Northing)
159 {
160 /* BEGIN Set_Azimuthal_Equidistant_Parameters */
161 /*
162  * The function Set_Azimuthal_Equidistant_Parameters receives the ellipsoid parameters and
163  * projection parameters as inputs, and sets the corresponding state
164  * variables. If any errors occur, the error code(s) are returned by the function,
165  * otherwise AZEQ_NO_ERROR is returned.
166  *
167  * a : Semi-major axis of ellipsoid, in meters (input)
168  * f : Flattening of ellipsoid (input)
169  * Origin_Latitude : Latitude in radians at which the (input)
170  * point scale factor is 1.0
171  * Central_Meridian : Longitude in radians at the center of (input)
172  * the projection
173  * False_Easting : A coordinate value in meters assigned to the
174  * central meridian of the projection. (input)
175  * False_Northing : A coordinate value in meters assigned to the
176  * origin latitude of the projection (input)
177  */
178 
179  double es2, es4, es6;
180 // double inv_f = 1 / f;
181  double temp_Northing = 0.0;
182  long Error_Code = AZEQ_NO_ERROR;
183 
184 // if (a <= 0.0)
185 // { /* Semi-major axis must be greater than zero */
186 // Error_Code |= AZEQ_A_ERROR;
187 // }
188 // if ((inv_f < 250) || (inv_f > 350))
189 // { /* Inverse flattening must be between 250 and 350 */
190 // Error_Code |= AZEQ_INV_F_ERROR;
191 // }
192 // if ((Origin_Latitude < -PI_OVER_2) || (Origin_Latitude > PI_OVER_2))
193 // { /* origin latitude out of range */
194 // Error_Code |= AZEQ_ORIGIN_LAT_ERROR;
195 // }
196 // if ((Central_Meridian < -PI) || (Central_Meridian > TWO_PI))
197 // { /* origin longitude out of range */
198 // Error_Code |= AZEQ_CENT_MER_ERROR;
199 // }
200  if (!Error_Code)
201  { /* no errors */
202  Azeq_a = a;
203  Azeq_f = f;
204  es2 = 2 * Azeq_f - Azeq_f * Azeq_f;
205  es4 = es2 * es2;
206  es6 = es4 * es2;
207  /* spherical radius */
208  Ra = Azeq_a * (1.0 - es2 / 6.0 - 17.0 * es4 / 360.0 - 67.0 * es6 / 3024.0);
209  Azeq_Origin_Lat = Origin_Latitude;
213 // if (Central_Meridian > M_PI)
214 // Central_Meridian -= TWO_PI;
215  Azeq_Origin_Long = Central_Meridian;
216  Azeq_False_Northing = False_Northing;
217  Azeq_False_Easting = False_Easting;
218 
219  if (fabs(abs_Azeq_Origin_Lat - PI_OVER_2) < 1.0e-10)
220  {
221  Azeq_Delta_Northing = 20015110.0;
222  Azeq_Delta_Easting = 20015110.0;
223  }
224  else if (abs_Azeq_Origin_Lat >= 1.0e-10)
225  {
226  if (Azeq_Origin_Long > 0.0)
227  {
229  (Azeq_Origin_Long - M_PI - ONE), &Azeq_Delta_Easting, &temp_Northing);
230  }
231  else
232  {
234  (Azeq_Origin_Long + M_PI - ONE), &Azeq_Delta_Easting, &temp_Northing);
235  }
236  Azeq_Delta_Northing = 19903915.0;
237  }
238  else
239  {
240  Azeq_Delta_Northing = 19903915.0;
241  Azeq_Delta_Easting = 19903915.0;
242  }
243  } /* End if(!Error_Code) */
244  return (Error_Code);
245 } /* End Set_Azimuthal_Equidistant_Parameters */
246 
247 
249  double *f,
250  double *Origin_Latitude,
251  double *Central_Meridian,
252  double *False_Easting,
253  double *False_Northing)const
254 {
255 /* Begin Get_Azimuthal_Equidistant_Parameters */
256 /*
257  * The function Get_Azimuthal_Equidistant_Parameters returns the current ellipsoid
258  * parameters and Azimuthal Equidistant projection parameters.
259  *
260  * a : Semi-major axis of ellipsoid, in meters (output)
261  * f : Flattening of ellipsoid (output)
262  * Origin_Latitude : Latitude in radians at which the (output)
263  * point scale factor is 1.0
264  * Central_Meridian : Longitude in radians at the center of (output)
265  * the projection
266  * False_Easting : A coordinate value in meters assigned to the
267  * central meridian of the projection. (output)
268  * False_Northing : A coordinate value in meters assigned to the
269  * origin latitude of the projection (output)
270  */
271 
272  *a = Azeq_a;
273  *f = Azeq_f;
274  *Origin_Latitude = Azeq_Origin_Lat;
275  *Central_Meridian = Azeq_Origin_Long;
276  *False_Easting = Azeq_False_Easting;
277  *False_Northing = Azeq_False_Northing;
278  return;
279 } /* End Get_Azimuthal_Equidistant_Parameters */
280 
281 
283  double Longitude,
284  double *Easting,
285  double *Northing)const
286 {
287 /* Begin Convert_Geodetic_To_Azimuthal_Equidistant */
288 /*
289  * The function Convert_Geodetic_To_Azimuthal_Equidistant converts geodetic (latitude and
290  * longitude) coordinates to Azimuthal Equidistant projection (easting and northing)
291  * coordinates, according to the current ellipsoid and Azimuthal Equidistant projection
292  * parameters. If any errors occur, the error code(s) are returned by the
293  * function, otherwise AZEQ_NO_ERROR is returned.
294  *
295  * Latitude : Latitude (phi) in radians (input)
296  * Longitude : Longitude (lambda) in radians (input)
297  * Easting : Easting (X) in meters (output)
298  * Northing : Northing (Y) in meters (output)
299  */
300 
301  double dlam; /* Longitude - Central Meridan */
302  double k_prime; /* scale factor */
303  double c; /* angular distance from center */
304  double slat = sin(Latitude);
305  double clat = cos(Latitude);
306  double cos_c;
307  double sin_dlam, cos_dlam;
308  double Ra_kprime;
309  double Ra_PI_OVER_2_Lat;
310  long Error_Code = AZEQ_NO_ERROR;
311 
312 // if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2))
313 // { /* Latitude out of range */
314 // Error_Code |= AZEQ_LAT_ERROR;
315 // }
316 // if ((Longitude < -M_PI) || (Longitude > TWO_PI))
317 // { /* Longitude out of range */
318 // Error_Code |= AZEQ_LON_ERROR;
319 // }
320  if (!Error_Code)
321  { /* no errors */
322  dlam = Longitude - Azeq_Origin_Long;
323  if (dlam > M_PI)
324  {
325  dlam -= TWO_PI;
326  }
327  if (dlam < -M_PI)
328  {
329  dlam += TWO_PI;
330  }
331 
332  sin_dlam = sin(dlam);
333  cos_dlam = cos(dlam);
334  if (fabs(abs_Azeq_Origin_Lat - PI_OVER_2) < 1.0e-10)
335  {
336  if (Azeq_Origin_Lat >= 0.0)
337  {
338  Ra_PI_OVER_2_Lat = Ra * (PI_OVER_2 - Latitude);
339  *Easting = Ra_PI_OVER_2_Lat * sin_dlam + Azeq_False_Easting;
340  *Northing = -1.0 * (Ra_PI_OVER_2_Lat * cos_dlam) + Azeq_False_Northing;
341  }
342  else
343  {
344  Ra_PI_OVER_2_Lat = Ra * (PI_OVER_2 + Latitude);
345  *Easting = Ra_PI_OVER_2_Lat * sin_dlam + Azeq_False_Easting;
346  *Northing = Ra_PI_OVER_2_Lat * cos_dlam + Azeq_False_Northing;
347  }
348  }
349  else if (abs_Azeq_Origin_Lat <= 1.0e-10)
350  {
351  cos_c = clat * cos_dlam;
352  if (fabs(fabs(cos_c) - 1.0) < 1.0e-14)
353  {
354  if (cos_c >= 0.0)
355  {
356  *Easting = Azeq_False_Easting;
357  *Northing = Azeq_False_Northing;
358  }
359  else
360  {
361  /* if cos_c == -1 */
362  Error_Code |= AZEQ_PROJECTION_ERROR;
363  }
364  }
365  else
366  {
367  c = acos(cos_c);
368  k_prime = c / sin(c);
369  Ra_kprime = Ra * k_prime;
370  *Easting = Ra_kprime * clat * sin_dlam + Azeq_False_Easting;
371  *Northing = Ra_kprime * slat + Azeq_False_Northing;
372  }
373  }
374  else
375  {
376  cos_c = (Sin_Azeq_Origin_Lat * slat) + (Cos_Azeq_Origin_Lat * clat * cos_dlam);
377  if (fabs(fabs(cos_c) - 1.0) < 1.0e-14)
378  {
379  if (cos_c >= 0.0)
380  {
381  *Easting = Azeq_False_Easting;
382  *Northing = Azeq_False_Northing;
383  }
384  else
385  {
386  /* if cos_c == -1 */
387  Error_Code |= AZEQ_PROJECTION_ERROR;
388  }
389  }
390  else
391  {
392  c = acos(cos_c);
393  k_prime = c / sin(c);
394  Ra_kprime = Ra * k_prime;
395  *Easting = Ra_kprime * clat * sin_dlam + Azeq_False_Easting;
396  *Northing = Ra_kprime * (Cos_Azeq_Origin_Lat * slat - Sin_Azeq_Origin_Lat * clat * cos_dlam) + Azeq_False_Northing;
397  }
398  }
399  }
400  return (Error_Code);
401 } /* End Convert_Geodetic_To_Azimuthal_Equidistant */
402 
403 
405  double Northing,
406  double *Latitude,
407  double *Longitude)const
408 { /* Begin Convert_Azimuthal_Equidistant_To_Geodetic */
409 /*
410  * The function Convert_Azimuthal_Equidistant_To_Geodetic converts Azimuthal_Equidistant projection
411  * (easting and northing) coordinates to geodetic (latitude and longitude)
412  * coordinates, according to the current ellipsoid and Azimuthal_Equidistant projection
413  * coordinates. If any errors occur, the error code(s) are returned by the
414  * function, otherwise AZEQ_NO_ERROR is returned.
415  *
416  * Easting : Easting (X) in meters (input)
417  * Northing : Northing (Y) in meters (input)
418  * Latitude : Latitude (phi) in radians (output)
419  * Longitude : Longitude (lambda) in radians (output)
420  */
421 
422  double dx, dy;
423  double rho; /* height above ellipsoid */
424  double c; /* angular distance from center */
425  double sin_c, cos_c, dy_sinc;
426  long Error_Code = AZEQ_NO_ERROR;
427 
428 // if ((Easting < (Azeq_False_Easting - Azeq_Delta_Easting))
429 // || (Easting > (Azeq_False_Easting + Azeq_Delta_Easting)))
430 // { /* Easting out of range */
431 // Error_Code |= AZEQ_EASTING_ERROR;
432 // }
433 // if ((Northing < (Azeq_False_Northing - Azeq_Delta_Northing))
434 // || (Northing > (Azeq_False_Northing + Azeq_Delta_Northing)))
435 // { /* Northing out of range */
436 // Error_Code |= AZEQ_NORTHING_ERROR;
437 // }
438 
439  if (!Error_Code)
440  {
441  dy = Northing - Azeq_False_Northing;
442  dx = Easting - Azeq_False_Easting;
443  rho = sqrt(dx * dx + dy * dy);
444  if (fabs(rho) <= 1.0e-10)
445  {
446  *Latitude = Azeq_Origin_Lat;
447  *Longitude = Azeq_Origin_Long;
448  }
449  else
450  {
451  c = rho / Ra;
452  sin_c = sin(c);
453  cos_c = cos(c);
454  dy_sinc = dy * sin_c;
455  *Latitude = asin((cos_c * Sin_Azeq_Origin_Lat) + ((dy_sinc * Cos_Azeq_Origin_Lat) / rho));
456  if (fabs(abs_Azeq_Origin_Lat - PI_OVER_2) < 1.0e-10)
457  {
458  if (Azeq_Origin_Lat >= 0.0)
459  *Longitude = Azeq_Origin_Long + atan2(dx, -dy);
460  else
461  *Longitude = Azeq_Origin_Long + atan2(dx, dy);
462  }
463  else
464  *Longitude = Azeq_Origin_Long + atan2((dx * sin_c), ((rho * Cos_Azeq_Origin_Lat * cos_c) - (dy_sinc * Sin_Azeq_Origin_Lat)));
465  }
466 
467  if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */
468  *Latitude = PI_OVER_2;
469  else if (*Latitude < -PI_OVER_2)
470  *Latitude = -PI_OVER_2;
471 
472 // if (*Longitude > M_PI)
473 // *Longitude -= TWO_PI;
474 // if (*Longitude < -M_PI)
475 // *Longitude += TWO_PI;
476 
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  }
483  return (Error_Code);
484 } /* End Convert_Azimuthal_Equidistant_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
long Convert_Geodetic_To_Azimuthal_Equidistant(double Latitude, double Longitude, double *Easting, double *Northing) const
double y
Definition: ossimDpt.h:165
virtual const ossimString & code() const
Definition: ossimDatum.h:57
virtual ossimDpt forward(const ossimGpt &latLon) const
All map projections will convert the world coordinate to an easting northing (Meters).
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 AZEQ_NO_ERROR
#define STATIC_TYPE_NAME(T)
Definition: ossimRtti.h:325
const ossimDatum * datum() const
datum().
Definition: ossimGpt.h:196
void setFalseEasting(double falseEasting)
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 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.
#define PI_OVER_2
void Get_Azimuthal_Equidistant_Parameters(double *a, double *f, double *Origin_Latitude, double *Central_Meridian, double *False_Easting, double *False_Northing) const
#define AZEQ_PROJECTION_ERROR
double x
Definition: ossimDpt.h:164
#define TWO_PI
double latr() const
latr().
Definition: ossimGpt.h:66
void setFalseNorthing(double falseNorthing)
const double & getFlattening() const
long Convert_Azimuthal_Equidistant_To_Geodetic(double Easting, double Northing, double *Latitude, double *Longitude) 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 Set_Azimuthal_Equidistant_Parameters(double a, double f, double Origin_Latitude, double Central_Meridian, double False_Easting, double False_Northing)
ossimAzimEquDistProjection(const ossimEllipsoid &ellipsoid=ossimEllipsoid(), const ossimGpt &origin=ossimGpt())
const ossimDatum * theDatum
This is only set if we want to have built in datum shifting.