OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimMillerProjection.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 Miller projection code.
11 //*******************************************************************
12 // $Id: ossimMillerProjection.cpp 17815 2010-08-03 13:23:14Z dburken $
13 
14 #include <math.h>
17 
18 RTTI_DEF1(ossimMillerProjection, "ossimMillerProjection", ossimMapProjection)
19 /***************************************************************************/
20 /*
21  * DEFINES
22  */
23 
24 #ifndef PI_OVER_2
25 # define PI_OVER_2 ( M_PI / 2.0)
26 #endif
27 #ifndef TWO_PI
28 # define TWO_PI (2.0 * M_PI)
29 #endif
30 
31 #define MILL_NO_ERROR 0x0000
32 #define MILL_LAT_ERROR 0x0001
33 #define MILL_LON_ERROR 0x0002
34 #define MILL_EASTING_ERROR 0x0004
35 #define MILL_NORTHING_ERROR 0x0008
36 #define MILL_CENT_MER_ERROR 0x0020
37 #define MILL_A_ERROR 0x0040
38 #define MILL_B_ERROR 0x0080
39 #define MILL_A_LESS_B_ERROR 0x0100
40 
42  const ossimGpt& origin)
43  :ossimMapProjection(ellipsoid, origin)
44 {
45  setDefaults();
46  update();
47 // Mill_Delta_Northing = 14675058.0;
48 // Mill_Max_Easting = 20015110.0;
49 // Mill_Min_Easting = -20015110.0;
50 }
51 
53  const ossimGpt& origin,
54  double falseEasting,
55  double falseNorthing)
56  :ossimMapProjection(ellipsoid, origin)
57 {
58 
59  Mill_False_Easting = falseEasting;
60  Mill_False_Northing = falseNorthing;
61  Mill_Delta_Northing = 14675058.0;
62  Mill_Max_Easting = 20015110.0;
63  Mill_Min_Easting = -20015110.0;
64 
65  update();
66 }
67 
69 {
72  theOrigin.lonr(),
75 
78 
80 }
81 
82 void ossimMillerProjection::setFalseEasting(double falseEasting)
83 {
84  Mill_False_Easting = falseEasting;
85  update();
86 }
87 
88 void ossimMillerProjection::setFalseNorthing(double falseNorthing)
89 {
90  Mill_False_Northing = falseNorthing;
91  update();
92 }
93 
95 {
96  Mill_False_Easting = 0.0;
97  Mill_False_Northing = 0.0;
98  Mill_Delta_Northing = 14675058.0;
99  Mill_Max_Easting = 20015110.0;
100  Mill_Min_Easting = -20015110.0;
101 }
102 
103 void ossimMillerProjection::setCentralMeridian(double centralMeridian)
104 {
105  Mill_Origin_Long = centralMeridian;
106  update();
107 }
108 
110  double falseNorthing)
111 {
112  Mill_False_Easting = falseEasting;
113  Mill_False_Northing = falseNorthing;
114 
115  update();
116 }
117 
119 {
120  double lat = 0.0;
121  double lon = 0.0;
122 
123  Convert_Miller_To_Geodetic(eastingNorthing.x,
124  eastingNorthing.y,
125  &lat,
126  &lon);
127 
128  return ossimGpt(lat*DEG_PER_RAD, lon*DEG_PER_RAD, 0.0, theDatum);
129 }
130 
132 {
133  double easting = 0.0;
134  double northing = 0.0;
135  ossimGpt gpt = latLon;
136 
137  if (theDatum)
138  {
139  if (theDatum->code() != latLon.datum()->code())
140  {
141  gpt.changeDatum(theDatum); // Shift to our datum.
142  }
143  }
144 
146  gpt.lonr(),
147  &easting,
148  &northing);
149 
150  return ossimDpt(easting, northing);
151 }
152 
153 bool ossimMillerProjection::saveState(ossimKeywordlist& kwl, const char* prefix) const
154 {
155  return ossimMapProjection::saveState(kwl, prefix);
156 }
157 
159  const char* prefix)
160 {
161  bool flag = ossimMapProjection::loadState(kwl, prefix);
162 
163  const char* type = kwl.find(prefix, ossimKeywordNames::TYPE_KW);
164 
165  setDefaults();
166 
168  {
171  }
172 
173  update();
174 
175  return flag;
176 }
177 
178 /***************************************************************************/
179 /*
180  * FUNCTIONS
181  */
182 
184  double f,
185  double Central_Meridian ,
186  double False_Easting,
187  double False_Northing)
188 { /* Begin Set_Miller_Parameters */
189 /*
190  * The function Set_Miller_Parameters receives the ellipsoid parameters and
191  * Miller Cylindrical projcetion parameters as inputs, and sets the corresponding
192  * state variables. If any errors occur, the error code(s) are returned by the
193  * function, otherwise MILL_NO_ERROR is returned.
194  *
195  * a : Semi-major axis of ellipsoid, in meters (input)
196  * f : Flattening of ellipsoid (input)
197  * Central_Meridian : Longitude in radians at the center of (input)
198  * the projection
199  * False_Easting : A coordinate value in meters assigned to the
200  * central meridian of the projection. (input)
201  * False_Northing : A coordinate value in meters assigned to the
202  * origin latitude of the projection (input)
203  */
204 
205 // double inv_f = 1 / f;
206  long Error_Code = MILL_NO_ERROR;
207 
208 // if (a <= 0.0)
209 // { /* Semi-major axis must be greater than zero */
210 // Error_Code |= MILL_A_ERROR;
211 // }
212 // if ((inv_f < 250) || (inv_f > 350))
213 // { /* Inverse flattening must be between 250 and 350 */
214 // Error_Code |= MILL_INV_F_ERROR;
215 // }
216 // if ((Central_Meridian < -PI) || (Central_Meridian > TWO_PI))
217 // { /* origin longitude out of range */
218 // Error_Code |= MILL_CENT_MER_ERROR;
219 // }
220  if (!Error_Code)
221  { /* no errors */
222  Mill_a = a;
223  Mill_f = f;
224  es2 = 2 * Mill_f - Mill_f * Mill_f;
225  es4 = es2 * es2;
226  es6 = es4 * es2;
227  /* spherical radius */
228  Ra = Mill_a * (1.0 - es2 / 6.0 - 17.0 * es4 / 360.0 - 67.0 * es6 /3024.0);
229 // if (Central_Meridian > PI)
230 // Central_Meridian -= TWO_PI;
231  Mill_Origin_Long = Central_Meridian;
232  Mill_False_Easting = False_Easting;
233  Mill_False_Northing = False_Northing;
234  if (Mill_Origin_Long > 0)
235  {
236  Mill_Max_Easting = 19903915.0;
237  Mill_Min_Easting = -20015110.0;
238  }
239  else if (Mill_Origin_Long < 0)
240  {
241  Mill_Max_Easting = 20015110.0;
242  Mill_Min_Easting = -19903915.0;
243  }
244  else
245  {
246  Mill_Max_Easting = 20015110.0;
247  Mill_Min_Easting = -20015110.0;
248  }
249  } /* End if(!Error_Code) */
250  return (Error_Code);
251 } /* End Set_Miller_Parameters */
252 
253 
255  double *f,
256  double *Central_Meridian,
257  double *False_Easting,
258  double *False_Northing)const
259 { /* Begin Get_Miller_Parameters */
260 /*
261  * The function Get_Miller_Parameters returns the current ellipsoid
262  * parameters and Miller Cylindrical projection parameters.
263  *
264  * a : Semi-major axis of ellipsoid, in meters (output)
265  * f : Flattening of ellipsoid (output)
266  * Central_Meridian : Longitude in radians at the center of (output)
267  * the projection
268  * False_Easting : A coordinate value in meters assigned to the
269  * central meridian of the projection. (output)
270  * False_Northing : A coordinate value in meters assigned to the
271  * origin latitude of the projection (output)
272  */
273 
274  *a = Mill_a;
275  *f = Mill_f;
276  *Central_Meridian = Mill_Origin_Long;
277  *False_Easting = Mill_False_Easting;
278  *False_Northing = Mill_False_Northing;
279 
280  return;
281 } /* End Get_Miller_Parameters */
282 
283 
285  double Longitude,
286  double *Easting,
287  double *Northing)const
288 
289 { /* Begin Convert_Geodetic_To_Miller */
290 /*
291  * The function Convert_Geodetic_To_Miller converts geodetic (latitude and
292  * longitude) coordinates to Miller Cylindrical projection (easting and northing)
293  * coordinates, according to the current ellipsoid and Miller Cylindrical projection
294  * parameters. If any errors occur, the error code(s) are returned by the
295  * function, otherwise MILL_NO_ERROR is returned.
296  *
297  * Latitude : Latitude (phi) in radians (input)
298  * Longitude : Longitude (lambda) in radians (input)
299  * Easting : Easting (X) in meters (output)
300  * Northing : Northing (Y) in meters (output)
301  */
302 
303  double slat = sin(0.8 * Latitude);
304  double dlam; /* Longitude - Central Meridan */
305 
306  long Error_Code = MILL_NO_ERROR;
307 
308 // if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2))
309 // { /* Latitude out of range */
310 // Error_Code |= MILL_LAT_ERROR;
311 // }
312 // if ((Longitude < -PI) || (Longitude > TWO_PI))
313 // { /* Longitude out of range */
314 // Error_Code|= MILL_LON_ERROR;
315 // }
316 
317  if (!Error_Code)
318  { /* no errors */
319  dlam = Longitude - Mill_Origin_Long;
320 // if (dlam > PI)
321 // {
322 // dlam -= TWO_PI;
323 // }
324 // if (dlam < -PI)
325 // {
326 // dlam += TWO_PI;
327 // }
328  *Easting = Ra * dlam + Mill_False_Easting;
329  *Northing = (Ra / 1.6) * log((1.0 + slat) /
330  (1.0 - slat)) + Mill_False_Northing;
331  }
332  return (Error_Code);
333 } /* End Convert_Geodetic_To_Miller */
334 
335 
337  double Northing,
338  double *Latitude,
339  double *Longitude)const
340 { /* Begin Convert_Miller_To_Geodetic */
341 /*
342  * The function Convert_Miller_To_Geodetic converts Miller Cylindrical projection
343  * (easting and northing) coordinates to geodetic (latitude and longitude)
344  * coordinates, according to the current ellipsoid and Miller Cylindrical projection
345  * coordinates. If any errors occur, the error code(s) are returned by the
346  * function, otherwise MILL_NO_ERROR is returned.
347  *
348  * Easting : Easting (X) in meters (input)
349  * Northing : Northing (Y) in meters (input)
350  * Latitude : Latitude (phi) in radians (output)
351  * Longitude : Longitude (lambda) in radians (output)
352  */
353 
354  double dx, dy;
355  long Error_Code = MILL_NO_ERROR;
356 
357 // if ((Easting < (Mill_False_Easting + Mill_Min_Easting))
358 // || (Easting > (Mill_False_Easting + Mill_Max_Easting)))
359 // { /* Easting out of range */
360 // Error_Code |= MILL_EASTING_ERROR;
361 // }
362 // if ((Northing < (Mill_False_Northing - Mill_Delta_Northing)) ||
363 // (Northing > (Mill_False_Northing + Mill_Delta_Northing) ))
364 // { /* Northing out of range */
365 // Error_Code |= MILL_NORTHING_ERROR;
366 // }
367 
368  if (!Error_Code)
369  {
370  dy = Northing - Mill_False_Northing;
371  dx = Easting - Mill_False_Easting;
372  *Latitude = atan(sinh(0.8 * dy / Ra)) / 0.8;
373  *Longitude = Mill_Origin_Long + dx / Ra;
374 
375 // if (*Latitude > PI_OVER_2) /* force distorted values to 90, -90 degrees */
376 // *Latitude = PI_OVER_2;
377 // else if (*Latitude < -PI_OVER_2)
378 // *Latitude = -PI_OVER_2;
379 
380 // if (*Longitude > PI)
381 // *Longitude -= TWO_PI;
382 // if (*Longitude < -PI)
383 // *Longitude += TWO_PI;
384 
385 // if (*Longitude > PI) /* force distorted values to 180, -180 degrees */
386 // *Longitude = PI;
387 // else if (*Longitude < -PI)
388 // *Longitude = -PI;
389 
390  }
391  return (Error_Code);
392 } /* End Convert_Miller_To_Geodetic */
virtual ossimDpt forward(const ossimGpt &latLon) const
All map projections will convert the world coordinate to an easting northing (Meters).
#define MILL_NO_ERROR
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.
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
const char * find(const char *key) const
double y
Definition: ossimDpt.h:165
virtual const ossimString & code() const
Definition: ossimDatum.h:57
long Set_Miller_Parameters(double a, double f, double Central_Meridian, double False_Easting, double False_Northing)
void setFalseEasting(double falseEasting)
static const char * TYPE_KW
long Convert_Miller_To_Geodetic(double Easting, double Northing, double *Latitude, double *Longitude) const
void changeDatum(const ossimDatum *datum)
This will actually perform a shift.
Definition: ossimGpt.cpp:316
ossimMillerProjection(const ossimEllipsoid &ellipsoid=ossimEllipsoid(), const ossimGpt &origin=ossimGpt())
#define STATIC_TYPE_NAME(T)
Definition: ossimRtti.h:325
const ossimDatum * datum() const
datum().
Definition: ossimGpt.h:196
void setFalseEastingNorthing(double falseEasting, double falseNorthing)
long Convert_Geodetic_To_Miller(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.
virtual ossimGpt inverse(const ossimDpt &eastingNorthing) 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
void setFalseNorthing(double falseNorthing)
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.
void setCentralMeridian(double centralMeridian)
void Get_Miller_Parameters(double *a, double *f, double *Central_Meridian, double *False_Easting, double *False_Northing) const
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
const ossimDatum * theDatum
This is only set if we want to have built in datum shifting.