UNCLASSIFIED

GeographicTranslator
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Friends Macros
UPS.cpp
Go to the documentation of this file.
1 // CLASSIFICATION: UNCLASSIFIED
2 
3 /********************************************************************/
4 /* RSC IDENTIFIER: UPS
5  *
6  *
7  * ABSTRACT
8  *
9  * This component provides conversions between geodetic (latitude
10  * and longitude) coordinates and Universal Polar Stereographic (UPS)
11  * projection (hemisphere, easting, and northing) coordinates.
12  *
13  *
14  * ERROR HANDLING
15  *
16  * This component checks parameters for valid values. If an
17  * invalid value is found the error code is combined with the
18  * current error code using the bitwise or. This combining allows
19  * multiple error codes to be returned. The possible error codes
20  * are:
21  *
22  * UPS_NO_ERROR : No errors occurred in function
23  * UPS_LAT_ERROR : Latitude outside of valid range
24  * (North Pole: 83.5 to 90,
25  * South Pole: -79.5 to -90)
26  * UPS_LON_ERROR : Longitude outside of valid range
27  * (-180 to 360 degrees)
28  * UPS_HEMISPHERE_ERROR : Invalid hemisphere ('N' or 'S')
29  * UPS_EASTING_ERROR : Easting outside of valid range,
30  * (0 to 4,000,000m)
31  * UPS_NORTHING_ERROR : Northing outside of valid range,
32  * (0 to 4,000,000m)
33  * UPS_A_ERROR : Semi-major axis less than or equal to zero
34  * UPS_INV_F_ERROR : Inverse flattening outside of valid range
35  * (250 to 350)
36  *
37  *
38  * REUSE NOTES
39  *
40  * UPS is intended for reuse by any application that performs a Universal
41  * Polar Stereographic (UPS) projection.
42  *
43  *
44  * REFERENCES
45  *
46  * Further information on UPS can be found in the Reuse Manual.
47  *
48  * UPS originated from : U.S. Army Topographic Engineering Center
49  * Geospatial Information Division
50  * 7701 Telegraph Road
51  * Alexandria, VA 22310-3864
52  *
53  *
54  * LICENSES
55  *
56  * None apply to this component.
57  *
58  *
59  * RESTRICTIONS
60  *
61  * UPS has no restrictions.
62  *
63  *
64  * ENVIRONMENT
65  *
66  * UPS was tested and certified in the following environments:
67  *
68  * 1. Solaris 2.5 with GCC version 2.8.1
69  * 2. Windows 95 with MS Visual C++ version 6
70  *
71  *
72  * MODIFICATIONS
73  *
74  * Date Description
75  * ---- -----------
76  * 2-27-07 Original Code
77  *
78  *
79  */
80 
81 
82 /************************************************************************/
83 /*
84  * INCLUDES
85  */
86 
87 #include <math.h>
88 #include "UPS.h"
89 #include "PolarStereographic.h"
92 #include "UPSCoordinates.h"
93 #include "GeodeticCoordinates.h"
95 #include "ErrorMessages.h"
96 
97 /*
98  * UPS.h - Defines the function prototypes for the ups module.
99  * PolarStereographic.h - Is used to convert polar stereographic coordinates
100  * MapProjectionCoordinates.h - defines map projection coordinates
101  * UPSCoordinates.h - defines UPS coordinates
102  * GeodeticCoordinates.h - defines geodetic coordinates
103  * CoordinateConversionException.h - Exception handler
104  * ErrorMessages.h - Contains exception messages
105  */
106 
107 
108 using namespace MSP::CCS;
109 
110 
111 /***************************************************************************/
112 /*
113  * DEFINES
114  */
115 
116 #define EPSILON 1.75e-7 /* approx 1.0e-5 degrees (~1 meter) in radians */
117 
118 const double PI = 3.14159265358979323e0; /* PI */
119 const double PI_OVER = (PI/2.0e0); /* PI over 2 */
120 const double MAX_LAT = 90.0 * (PI / 180.0); /* 90 degrees in radians */
121 const double MAX_ORIGIN_LAT = 81.114528 * (PI / 180.0);
122 const double MIN_NORTH_LAT = 83.5 * (PI / 180.0);
123 const double MAX_SOUTH_LAT = -79.5 * (PI / 180.0);
124 const double MIN_EAST_NORTH = 0.0;
125 const double MAX_EAST_NORTH = 4000000.0;
126 
127 const double UPS_False_Easting = 2000000;
128 const double UPS_False_Northing = 2000000;
129 const double UPS_Origin_Longitude = 0.0;
130 
131 
132 /************************************************************************/
133 /* FUNCTIONS
134  *
135  */
136 
137 UPS::UPS( double ellipsoidSemiMajorAxis, double ellipsoidFlattening ) :
139  UPS_Origin_Latitude( MAX_ORIGIN_LAT )
140 {
141 /*
142  * The constructor receives the ellipsoid parameters and sets
143  * the corresponding state variables. If any errors occur, an exception is
144  * thrown with a description of the error.
145  *
146  * ellipsoidSemiMajorAxis : Semi-major axis of ellipsoid in meters (input)
147  * ellipsoidFlattening : Flattening of ellipsoid (input)
148  */
149 
150  double inv_f = 1 / ellipsoidFlattening;
151 
152  if (ellipsoidSemiMajorAxis <= 0.0)
153  { /* Semi-major axis must be greater than zero */
155  }
156  if ((inv_f < 250) || (inv_f > 350))
157  { /* Inverse flattening must be between 250 and 350 */
159  }
160 
161  semiMajorAxis = ellipsoidSemiMajorAxis;
162  flattening = ellipsoidFlattening;
163 
168 }
169 
170 
171 UPS::UPS( const UPS &u )
172 {
173  std::map< char, PolarStereographic* > tempPolarStereographicMap = u.polarStereographicMap;
174  polarStereographicMap['N'] = new PolarStereographic( *tempPolarStereographicMap['N'] );
175  polarStereographicMap['S'] = new PolarStereographic( *tempPolarStereographicMap['S'] );
178  UPS_Origin_Latitude = u.UPS_Origin_Latitude;
179 }
180 
181 
183 {
184  while( polarStereographicMap.begin() != polarStereographicMap.end() )
185  {
186  delete ( ( *polarStereographicMap.begin() ).second );
187  polarStereographicMap.erase( polarStereographicMap.begin() );
188  }
189 }
190 
191 
192 UPS& UPS::operator=( const UPS &u )
193 {
194  if( this != &u )
195  {
196  std::map< char, PolarStereographic* > tempPolarStereographicMap = u.polarStereographicMap;
197  polarStereographicMap['N']->operator=( *tempPolarStereographicMap['N'] );
198  polarStereographicMap['S']->operator=( *tempPolarStereographicMap['S'] );
201  UPS_Origin_Latitude = u.UPS_Origin_Latitude;
202  }
203 
204  return *this;
205 }
206 
207 
209 {
210 /*
211  * The function convertFromGeodetic converts geodetic (latitude and
212  * longitude) coordinates to UPS (hemisphere, easting, and northing)
213  * coordinates, according to the current ellipsoid parameters.
214  * If any errors occur, an exception is thrown with a description
215  * of the error.
216  *
217  * latitude : Latitude in radians (input)
218  * longitude : Longitude in radians (input)
219  * hemisphere : Hemisphere either 'N' or 'S' (output)
220  * easting : Easting/X in meters (output)
221  * northing : Northing/Y in meters (output)
222  */
223 
224  char hemisphere;
225 
226  double longitude = geodeticCoordinates->longitude();
227  double latitude = geodeticCoordinates->latitude();
228 
229  if ((latitude < -MAX_LAT) || (latitude > MAX_LAT))
230  { /* latitude out of range */
232  }
233  else if ((latitude < 0) && (latitude >= (MAX_SOUTH_LAT + EPSILON)))
235  else if ((latitude >= 0) && (latitude < (MIN_NORTH_LAT - EPSILON)))
237  if ((longitude < -PI) || (longitude > (2 * PI)))
238  { /* longitude out of range */
240  }
241 
242  if (latitude < 0)
243  {
244  UPS_Origin_Latitude = -MAX_ORIGIN_LAT;
245  hemisphere = 'S';
246  }
247  else
248  {
249  UPS_Origin_Latitude = MAX_ORIGIN_LAT;
250  hemisphere = 'N';
251  }
252 
253  PolarStereographic polarStereographic = *polarStereographicMap[hemisphere];
254  MapProjectionCoordinates* polarStereographicCoordinates = polarStereographic.convertFromGeodetic( geodeticCoordinates );
255 
256  double easting = polarStereographicCoordinates->easting();
257  double northing = polarStereographicCoordinates->northing();
258  delete polarStereographicCoordinates;
259 
260  return new UPSCoordinates( CoordinateType::universalPolarStereographic, hemisphere, easting, northing );
261 }
262 
263 
265 {
266 /*
267  * The function convertToGeodetic converts UPS (hemisphere, easting,
268  * and northing) coordinates to geodetic (latitude and longitude) coordinates
269  * according to the current ellipsoid parameters. If any errors occur, an
270  * exception is thrown with a description of the error.
271  *
272  * hemisphere : Hemisphere either 'N' or 'S' (input)
273  * easting : Easting/X in meters (input)
274  * northing : Northing/Y in meters (input)
275  * latitude : Latitude in radians (output)
276  * longitude : Longitude in radians (output)
277  */
278 
279  char hemisphere = upsCoordinates->hemisphere();
280  double easting = upsCoordinates->easting();
281  double northing = upsCoordinates->northing();
282 
283  if ((hemisphere != 'N') && (hemisphere != 'S'))
285  if ((easting < MIN_EAST_NORTH) || (easting > MAX_EAST_NORTH))
287  if ((northing < MIN_EAST_NORTH) || (northing > MAX_EAST_NORTH))
289 
290  if (hemisphere =='N')
291  {
292  UPS_Origin_Latitude = MAX_ORIGIN_LAT;
293  }
294  else if (hemisphere =='S')
295  {
296  UPS_Origin_Latitude = -MAX_ORIGIN_LAT;
297  }
298 
299  MapProjectionCoordinates polarStereographicCoordinates(
301  PolarStereographic polarStereographic = *polarStereographicMap[hemisphere];
302  GeodeticCoordinates* geodeticCoordinates =
303  polarStereographic.convertToGeodetic( &polarStereographicCoordinates );
304 
305  double latitude = geodeticCoordinates->latitude();
306 
307  if ((latitude < 0) && (latitude >= (MAX_SOUTH_LAT + EPSILON)))
308  {
309  delete geodeticCoordinates;
311  }
312  if ((latitude >= 0) && (latitude < (MIN_NORTH_LAT - EPSILON)))
313  {
314  delete geodeticCoordinates;
316  }
317 
318  return geodeticCoordinates;
319 }
320 
321 // CLASSIFICATION: UNCLASSIFIED