OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimGnomonicProjection.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: ossimGnomonicProjection.cpp 9094 2006-06-13 19:12:40Z dburken $
12 
13 RTTI_DEF1(ossimGnomonicProjection, "ossimGnomonicProjection", ossimMapProjection)
14 
15 #ifndef PI_OVER_2
16 # define PI_OVER_2 ( M_PI / 2.0)
17 #endif
18 #ifndef TWO_PI
19 # define TWO_PI (2.0 * M_PI)
20 #endif
21 
22 #define GNOM_NO_ERROR 0x0000
23 #define GNOM_LAT_ERROR 0x0001
24 #define GNOM_LON_ERROR 0x0002
25 #define GNOM_EASTING_ERROR 0x0004
26 #define GNOM_NORTHING_ERROR 0x0008
27 #define GNOM_ORIGIN_LAT_ERROR 0x0010
28 #define GNOM_CENT_MER_ERROR 0x0020
29 #define GNOM_A_ERROR 0x0040
30 #define GNOM_INV_F_ERROR 0x0080
31 
33  const ossimGpt& origin)
34  :ossimMapProjection(ellipsoid, origin)
35 {
36  setDefaults();
37  update();
38 }
39 
41  const ossimGpt& origin,
42  double falseEasting,
43  double falseNorthing)
44  :ossimMapProjection(ellipsoid, origin)
45 {
46  Gnom_False_Easting = falseEasting;
47  Gnom_False_Northing = falseNorthing;
48 
49  update();
50 }
51 
53 {
56  theOrigin.latr(),
57  theOrigin.lonr(),
60 
63 
65 }
66 
68 {
69  Gnom_False_Easting = falseEasting;
70 
71  update();
72 }
73 
75 {
76  Gnom_False_Northing = falseNorthing;
77 
78  update();
79 }
80 
82 {
83  Gnom_False_Easting = 0.0;
84  Gnom_False_Northing = 0.0;
85  Gnom_Delta_Northing = 40000000;
86  Gnom_Delta_Easting = 40000000;
87 }
88 
90  double falseNorthing)
91 {
92  Gnom_False_Easting = falseEasting;
93  Gnom_False_Northing = falseNorthing;
94 
95  update();
96 }
97 
99 {
100  double lat = 0.0;
101  double lon = 0.0;
102 
103  Convert_Gnomonic_To_Geodetic(eastingNorthing.x,
104  eastingNorthing.y,
105  &lat,
106  &lon);
107 
108  return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum);
109 }
110 
112 {
113  double easting = 0.0;
114  double northing = 0.0;
115  ossimGpt gpt = latLon;
116 
117  if (theDatum)
118  {
119  if (theDatum->code() != latLon.datum()->code())
120  {
121  gpt.changeDatum(theDatum); // Shift to our datum.
122  }
123  }
124 
126  gpt.lonr(),
127  &easting,
128  &northing);
129 
130  return ossimDpt(easting, northing);
131 }
132 
133 bool ossimGnomonicProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const
134 {
135  return ossimMapProjection::saveState(kwl, prefix);
136 }
137 
139  const char* prefix)
140 {
141  bool flag = ossimMapProjection::loadState(kwl, prefix);
142 
143  const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
144 
145  setDefaults();
146 
148  {
151  }
152 
153  update();
154 
155  return flag;
156 
157 }
158 
159 /***************************************************************************/
160 /*
161  * FUNCTIONS
162  */
163 
165  double f,
166  double Origin_Latitude,
167  double Central_Meridian,
168  double False_Easting,
169  double False_Northing)
170 { /* BEGIN Set_Gnomonic_Parameters */
171 /*
172  * The function Set_Gnomonic_Parameters receives the ellipsoid parameters and
173  * projection parameters as inputs, and sets the corresponding state
174  * variables. If any errors occur, the error code(s) are returned by the function,
175  * otherwise GNOM_NO_ERROR is returned.
176  *
177  * a : Semi-major axis of ellipsoid, in meters (input)
178  * f : Flattening of ellipsoid (input)
179  * Origin_Latitude : Latitude in radians at which the (input)
180  * point scale factor is 1.0
181  * Central_Meridian : Longitude in radians at the center of (input)
182  * the projection
183  * False_Easting : A coordinate value in meters assigned to the
184  * central meridian of the projection. (input)
185  * False_Northing : A coordinate value in meters assigned to the
186  * origin latitude of the projection (input)
187  */
188 
189  double es2, es4, es6;
190 // double inv_f = 1 / f;
191  long Error_Code = GNOM_NO_ERROR;
192 
193 // if (a <= 0.0)
194 // { /* Semi-major axis must be greater than zero */
195 // Error_Code |= GNOM_A_ERROR;
196 // }
197 // if ((inv_f < 250) || (inv_f > 350))
198 // { /* Inverse flattening must be between 250 and 350 */
199 // Error_Code |= GNOM_INV_F_ERROR;
200 // }
201 // if ((Origin_Latitude < -PI_OVER_2) || (Origin_Latitude > PI_OVER_2))
202 // { /* origin latitude out of range */
203 // Error_Code |= GNOM_ORIGIN_LAT_ERROR;
204 // }
205 // if ((Central_Meridian < -PI) || (Central_Meridian > TWO_PI))
206 // { /* origin longitude out of range */
207 // Error_Code |= GNOM_CENT_MER_ERROR;
208 // }
209  if (!Error_Code)
210  { /* no errors */
211  Gnom_a = a;
212  Gnom_f = f;
213  es2 = 2 * Gnom_f - Gnom_f * Gnom_f;
214  es4 = es2 * es2;
215  es6 = es4 * es2;
216  /* spherical radius */
217  Ra = Gnom_a * (1.0 - es2 / 6.0 - 17.0 * es4 / 360.0 - 67.0 * es6 / 3024.0);
218  Gnom_Origin_Lat = Origin_Latitude;
222 // if (Central_Meridian > PI)
223 // Central_Meridian -= TWO_PI;
224  Gnom_Origin_Long = Central_Meridian;
225  Gnom_False_Northing = False_Northing;
226  Gnom_False_Easting = False_Easting;
227  } /* End if(!Error_Code) */
228  return (Error_Code);
229 } /* End Set_Gnomonic_Parameters */
230 
231 
233  double *f,
234  double *Origin_Latitude,
235  double *Central_Meridian,
236  double *False_Easting,
237  double *False_Northing)const
238 { /* Begin Get_Gnomonic_Parameters */
239 /*
240  * The function Get_Gnomonic_Parameters returns the current ellipsoid
241  * parameters and Gnomonic projection parameters.
242  *
243  * a : Semi-major axis of ellipsoid, in meters (output)
244  * f : Flattening of ellipsoid (output)
245  * Origin_Latitude : Latitude in radians at which the (output)
246  * point scale factor is 1.0
247  * Central_Meridian : Longitude in radians at the center of (output)
248  * the projection
249  * False_Easting : A coordinate value in meters assigned to the
250  * central meridian of the projection. (output)
251  * False_Northing : A coordinate value in meters assigned to the
252  * origin latitude of the projection (output)
253  */
254 
255  *a = Gnom_a;
256  *f = Gnom_f;
257  *Origin_Latitude = Gnom_Origin_Lat;
258  *Central_Meridian = Gnom_Origin_Long;
259  *False_Easting = Gnom_False_Easting;
260  *False_Northing = Gnom_False_Northing;
261 
262  return;
263 } /* End Get_Gnomonic_Parameters */
264 
265 
267  double Longitude,
268  double *Easting,
269  double *Northing)const
270 { /* Begin Convert_Geodetic_To_Gnomonic */
271 /*
272  * The function Convert_Geodetic_To_Gnomonic converts geodetic (latitude and
273  * longitude) coordinates to Gnomonic projection (easting and northing)
274  * coordinates, according to the current ellipsoid and Gnomonic projection
275  * parameters. If any errors occur, the error code(s) are returned by the
276  * function, otherwise GNOM_NO_ERROR is returned.
277  *
278  * Latitude : Latitude (phi) in radians (input)
279  * Longitude : Longitude (lambda) in radians (input)
280  * Easting : Easting (X) in meters (output)
281  * Northing : Northing (Y) in meters (output)
282  */
283 
284  double dlam; /* Longitude - Central Meridan */
285  double cos_c;
286  double k_prime; /* scale factor */
287  double Ra_kprime;
288  double slat = sin(Latitude);
289  double clat = cos(Latitude);
290  double Ra_cotlat;
291  double sin_dlam, cos_dlam;
292  double temp_Easting, temp_Northing;
293  long Error_Code = GNOM_NO_ERROR;
294 
295 // if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2))
296 // { /* Latitude out of range */
297 // Error_Code |= GNOM_LAT_ERROR;
298 // }
299 // if ((Longitude < -PI) || (Longitude > TWO_PI))
300 // { /* Longitude out of range */
301 // Error_Code |= GNOM_LON_ERROR;
302 // }
303  dlam = Longitude - Gnom_Origin_Long;
304  sin_dlam = sin(dlam);
305  cos_dlam = cos(dlam);
306  cos_c = Sin_Gnom_Origin_Lat * slat + Cos_Gnom_Origin_Lat * clat * cos_dlam;
307  if (cos_c <= 1.0e-10)
308  { /* Point is out of view. Will return longitude out of range message
309  since no point out of view is implemented. */
310  Error_Code |= GNOM_LON_ERROR;
311  }
312  if (!Error_Code)
313  { /* no errors */
314 // if (dlam > PI)
315 // {
316 // dlam -= TWO_PI;
317 // }
318 // if (dlam < -PI)
319 // {
320 // dlam += TWO_PI;
321 // }
322  if (fabs(abs_Gnom_Origin_Lat - PI_OVER_2) < 1.0e-10)
323  {
324  Ra_cotlat = Ra * (clat / slat);
325  temp_Easting = Ra_cotlat * sin_dlam;
326  temp_Northing = Ra_cotlat * cos_dlam;
327  if (Gnom_Origin_Lat >= 0.0)
328  {
329  *Easting = temp_Easting + Gnom_False_Easting;
330  *Northing = -1.0 * temp_Northing + Gnom_False_Northing;
331  }
332  else
333  {
334  *Easting = -1.0 * temp_Easting + Gnom_False_Easting;
335  *Northing = temp_Northing + Gnom_False_Northing;
336  }
337  }
338  else if (abs_Gnom_Origin_Lat <= 1.0e-10)
339  {
340  *Easting = Ra * tan(dlam) + Gnom_False_Easting;
341  *Northing = Ra * tan(Latitude) / cos_dlam + Gnom_False_Northing;
342  }
343  else
344  {
345  k_prime = 1 / cos_c;
346  Ra_kprime = Ra * k_prime;
347  *Easting = Ra_kprime * clat * sin_dlam + Gnom_False_Easting;
348  *Northing = Ra_kprime * (Cos_Gnom_Origin_Lat * slat - Sin_Gnom_Origin_Lat * clat * cos_dlam) + Gnom_False_Northing;
349  }
350  }
351  return (Error_Code);
352 } /* End Convert_Geodetic_To_Gnomonic */
353 
354 
356  double Northing,
357  double *Latitude,
358  double *Longitude)const
359 { /* Begin Convert_Gnomonic_To_Geodetic */
360 /*
361  * The function Convert_Gnomonic_To_Geodetic converts Gnomonic projection
362  * (easting and northing) coordinates to geodetic (latitude and longitude)
363  * coordinates, according to the current ellipsoid and Gnomonic projection
364  * coordinates. If any errors occur, the error code(s) are returned by the
365  * function, otherwise GNOM_NO_ERROR is returned.
366  *
367  * Easting : Easting (X) in meters (input)
368  * Northing : Northing (Y) in meters (input)
369  * Latitude : Latitude (phi) in radians (output)
370  * Longitude : Longitude (lambda) in radians (output)
371  */
372 
373  double dx, dy;
374  double rho;
375  double c;
376  double sin_c, cos_c;
377  double dy_sinc;
378  long Error_Code = GNOM_NO_ERROR;
379 
380 // if ((Easting < (Gnom_False_Easting - Gnom_Delta_Easting))
381 // || (Easting > (Gnom_False_Easting + Gnom_Delta_Easting)))
382 // { /* Easting out of range */
383 // Error_Code |= GNOM_EASTING_ERROR;
384 // }
385 // if ((Northing < (Gnom_False_Northing - Gnom_Delta_Northing))
386 // || (Northing > (Gnom_False_Northing + Gnom_Delta_Northing)))
387 // { /* Northing out of range */
388 // Error_Code |= GNOM_NORTHING_ERROR;
389 // }
390  if (!Error_Code)
391  {
392  dy = Northing - Gnom_False_Northing;
393  dx = Easting - Gnom_False_Easting;
394  rho = sqrt(dx * dx + dy * dy);
395  if (fabs(rho) <= 1.0e-10)
396  {
397  *Latitude = Gnom_Origin_Lat;
398  *Longitude = Gnom_Origin_Long;
399  }
400  else
401  {
402  c = atan(rho / Ra);
403  sin_c = sin(c);
404  cos_c = cos(c);
405  dy_sinc = dy * sin_c;
406  *Latitude = asin((cos_c * Sin_Gnom_Origin_Lat) + ((dy_sinc * Cos_Gnom_Origin_Lat) / rho));
407  if (fabs(abs_Gnom_Origin_Lat - PI_OVER_2) < 1.0e-10)
408  {
409  if (Gnom_Origin_Lat >= 0.0)
410  *Longitude = Gnom_Origin_Long + atan2(dx, -dy);
411  else
412  *Longitude = Gnom_Origin_Long + atan2(dx, dy);
413  }
414  else
415  *Longitude = Gnom_Origin_Long + atan2((dx * sin_c), (rho * Cos_Gnom_Origin_Lat * cos_c - dy_sinc * Sin_Gnom_Origin_Lat));
416  }
417 // if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */
418 // *Latitude = PI_OVER_2;
419 // else if (*Latitude < -PI_OVER_2)
420 // *Latitude = -PI_OVER_2;
421 // if (*Longitude > PI)
422 // *Longitude -= TWO_PI;
423 // if (*Longitude < -PI)
424 // *Longitude += TWO_PI;
425 // if (*Longitude > PI) /* force distorted values to 180, -180 degrees */
426 // *Longitude = PI;
427 // else if (*Longitude < -PI)
428 // *Longitude = -PI;
429  }
430  return (Error_Code);
431 } /* End Convert_Gnomonic_To_Geodetic */
void setFalseEasting(double falseEasting)
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 setFalseEastingNorthing(double falseEasting, double falseNorthing)
#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 &eastingNorthing) const
Will take a point in meters and convert it to ground.
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) 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
const ossimDatum * datum() const
datum().
Definition: ossimGpt.h:196
long Set_Gnomonic_Parameters(double a, double f, double Origin_Latitude, double Central_Meridian, double False_Easting, double False_Northing)
ossimGnomonicProjection(const ossimEllipsoid &ellipsoid=ossimEllipsoid(), const ossimGpt &origin=ossimGpt())
long Convert_Geodetic_To_Gnomonic(double Latitude, double Longitude, double *Easting, double *Northing) 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.
#define PI_OVER_2
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
void Get_Gnomonic_Parameters(double *a, double *f, double *Origin_Latitude, double *Central_Meridian, double *False_Easting, double *False_Northing) const
virtual ossimDpt forward(const ossimGpt &latLon) const
All map projections will convert the world coordinate to an easting northing (Meters).
#define GNOM_LON_ERROR
void setFalseNorthing(double falseNorthing)
double x
Definition: ossimDpt.h:164
double latr() const
latr().
Definition: ossimGpt.h:66
long Convert_Gnomonic_To_Geodetic(double Easting, double Northing, double *Latitude, double *Longitude) 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.
#define GNOM_NO_ERROR
const ossimDatum * theDatum
This is only set if we want to have built in datum shifting.