dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
utm.c
Go to the documentation of this file.
1 /***************************************************************************/
2 /* RSC IDENTIFIER: UTM
3  *
4  * ABSTRACT
5  *
6  * This component provides conversions between geodetic coordinates
7  * (latitude and longitudes) and Universal Transverse Mercator (UTM)
8  * projection (zone, hemisphere, easting, and northing) coordinates.
9  *
10  * ERROR HANDLING
11  *
12  * This component checks parameters for valid values. If an invalid value
13  * is found, the error code is combined with the current error code using
14  * the bitwise or. This combining allows multiple error codes to be
15  * returned. The possible error codes are:
16  *
17  * UTM_NO_ERROR : No errors occurred in function
18  * UTM_LAT_ERROR : Latitude outside of valid range
19  * (-80.5 to 84.5 degrees)
20  * UTM_LON_ERROR : intitude outside of valid range
21  * (-180 to 360 degrees)
22  * UTM_EASTING_ERROR : Easting outside of valid range
23  * (100,000 to 900,000 meters)
24  * UTM_NORTHING_ERROR : Northing outside of valid range
25  * (0 to 10,000,000 meters)
26  * UTM_ZONE_ERROR : Zone outside of valid range (1 to 60)
27  * UTM_HEMISPHERE_ERROR : Invalid hemisphere ('N' or 'S')
28  * UTM_ZONE_OVERRIDE_ERROR: Zone outside of valid range
29  * (1 to 60) and within 1 of 'natural' zone
30  * UTM_A_ERROR : Semi-major axis less than or equal to zero
31  * UTM_INV_F_ERROR : Inverse flattening outside of valid range
32  * (250 to 350)
33  *
34  * REUSE NOTES
35  *
36  * UTM is intended for reuse by any application that performs a Universal
37  * Transverse Mercator (UTM) projection or its inverse.
38  *
39  * REFERENCES
40  *
41  * Further information on UTM can be found in the Reuse Manual.
42  *
43  * UTM originated from : U.S. Army Topographic Engineering Center
44  * Geospatial Information Division
45  * 7701 Telegraph Road
46  * Alexandria, VA 22310-3864
47  *
48  * LICENSES
49  *
50  * None apply to this component.
51  *
52  * RESTRICTIONS
53  *
54  * UTM has no restrictions.
55  *
56  * ENVIRONMENT
57  *
58  * UTM was tested and certified in the following environments:
59  *
60  * 1. Solaris 2.5 with GCC, version 2.8.1
61  * 2. MSDOS with MS Visual C++, version 6
62  *
63  * MODIFICATIONS
64  *
65  * Date Description
66  * ---- -----------
67  * 10-02-97 Original Code
68  *
69  */
70 
71 
72 /***************************************************************************/
73 /*
74  * INCLUDES
75  */
76 #include "tranmerc.h"
77 #include "utm.h"
78 /*
79  * tranmerc.h - Is used to convert transverse mercator coordinates
80  * utm.h - Defines the function prototypes for the utm module.
81  */
82 
83 
84 /***************************************************************************/
85 /*
86  * DEFINES
87  */
88 
89 #define PI 3.14159265358979323e0 /* PI */
90 #define MIN_LAT ( (-80.5 * PI) / 180.0 ) /* -80.5 degrees in radians */
91 #define MAX_LAT ( (84.5 * PI) / 180.0 ) /* 84.5 degrees in radians */
92 #define MIN_EASTING 100000
93 #define MAX_EASTING 900000
94 #define MIN_NORTHING 0
95 #define MAX_NORTHING 10000000
96 
97 /***************************************************************************/
98 /*
99  * GLOBAL DECLARATIONS
100  */
101 
102 static double UTM_a = 6378137.0; /* Semi-major axis of ellipsoid in meters */
103 static double UTM_f = 1 / 298.257223563; /* Flattening of ellipsoid */
104 static int UTM_Override = 0; /* Zone override flag */
105 
106 
107 /***************************************************************************/
108 /*
109  * FUNCTIONS
110  *
111  */
112 
113 int Set_UTM_Parameters(double a,
114  double f,
115  int override)
116 {
117 /*
118  * The function Set_UTM_Parameters receives the ellipsoid parameters and
119  * UTM zone override parameter as inputs, and sets the corresponding state
120  * variables. If any errors occur, the error code(s) are returned by the
121  * function, otherwise UTM_NO_ERROR is returned.
122  *
123  * a : Semi-major axis of ellipsoid, in meters (input)
124  * f : Flattening of ellipsoid (input)
125  * override : UTM override zone, zero indicates no override (input)
126  */
127 
128  double inv_f = 1 / f;
129  int Error_Code = UTM_NO_ERROR;
130 
131  if (a <= 0.0)
132  { /* Semi-major axis must be greater than zero */
133  Error_Code |= UTM_A_ERROR;
134  }
135  if ((inv_f < 250) || (inv_f > 350))
136  { /* Inverse flattening must be between 250 and 350 */
137  Error_Code |= UTM_INV_F_ERROR;
138  }
139  if ((override < 0) || (override > 60))
140  {
141  Error_Code |= UTM_ZONE_OVERRIDE_ERROR;
142  }
143  if (!Error_Code)
144  { /* no errors */
145  UTM_a = a;
146  UTM_f = f;
147  UTM_Override = override;
148  }
149  return (Error_Code);
150 } /* END OF Set_UTM_Parameters */
151 
152 
153 void Get_UTM_Parameters(double *a,
154  double *f,
155  int *override)
156 {
157 /*
158  * The function Get_UTM_Parameters returns the current ellipsoid
159  * parameters and UTM zone override parameter.
160  *
161  * a : Semi-major axis of ellipsoid, in meters (output)
162  * f : Flattening of ellipsoid (output)
163  * override : UTM override zone, zero indicates no override (output)
164  */
165 
166  *a = UTM_a;
167  *f = UTM_f;
168  *override = UTM_Override;
169 } /* END OF Get_UTM_Parameters */
170 
171 
172 int Convert_Geodetic_To_UTM (double Latitude,
173  double intitude,
174  int *Zone,
175  char *Hemisphere,
176  double *Easting,
177  double *Northing)
178 {
179 /*
180  * The function Convert_Geodetic_To_UTM converts geodetic (latitude and
181  * intitude) coordinates to UTM projection (zone, hemisphere, easting and
182  * northing) coordinates according to the current ellipsoid and UTM zone
183  * override parameters. If any errors occur, the error code(s) are returned
184  * by the function, otherwise UTM_NO_ERROR is returned.
185  *
186  * Latitude : Latitude in radians (input)
187  * intitude : intitude in radians (input)
188  * Zone : UTM zone (output)
189  * Hemisphere : North or South hemisphere (output)
190  * Easting : Easting (X) in meters (output)
191  * Northing : Northing (Y) in meters (output)
192  */
193 
194  int Lat_Degrees;
195  int int_Degrees;
196  int temp_zone;
197  int Error_Code = UTM_NO_ERROR;
198  double Origin_Latitude = 0;
199  double Central_Meridian = 0;
200  double False_Easting = 500000;
201  double False_Northing = 0;
202  double Scale = 0.9996;
203 
204  if ((Latitude < MIN_LAT) || (Latitude > MAX_LAT))
205  { /* Latitude out of range */
206  Error_Code |= UTM_LAT_ERROR;
207  }
208  if ((intitude < -PI) || (intitude > (2*PI)))
209  { /* intitude out of range */
210  Error_Code |= UTM_LON_ERROR;
211  }
212  if (!Error_Code)
213  { /* no errors */
214  if((Latitude > -1.0e-9) && (Latitude < 0))
215  Latitude = 0.0;
216  if (intitude < 0)
217  intitude += (2*PI) + 1.0e-10;
218 
219  Lat_Degrees = (int)(Latitude * 180.0 / PI);
220  int_Degrees = (int)(intitude * 180.0 / PI);
221 
222  if (intitude < PI)
223  temp_zone = (int)(31 + ((intitude * 180.0 / PI) / 6.0));
224  else
225  temp_zone = (int)(((intitude * 180.0 / PI) / 6.0) - 29);
226 
227  if (temp_zone > 60)
228  temp_zone = 1;
229  /* UTM special cases */
230  if ((Lat_Degrees > 55) && (Lat_Degrees < 64) && (int_Degrees > -1)
231  && (int_Degrees < 3))
232  temp_zone = 31;
233  if ((Lat_Degrees > 55) && (Lat_Degrees < 64) && (int_Degrees > 2)
234  && (int_Degrees < 12))
235  temp_zone = 32;
236  if ((Lat_Degrees > 71) && (int_Degrees > -1) && (int_Degrees < 9))
237  temp_zone = 31;
238  if ((Lat_Degrees > 71) && (int_Degrees > 8) && (int_Degrees < 21))
239  temp_zone = 33;
240  if ((Lat_Degrees > 71) && (int_Degrees > 20) && (int_Degrees < 33))
241  temp_zone = 35;
242  if ((Lat_Degrees > 71) && (int_Degrees > 32) && (int_Degrees < 42))
243  temp_zone = 37;
244 
245  if (UTM_Override)
246  {
247  if ((temp_zone == 1) && (UTM_Override == 60))
248  temp_zone = UTM_Override;
249  else if ((temp_zone == 60) && (UTM_Override == 1))
250  temp_zone = UTM_Override;
251  else if ((Lat_Degrees > 71) && (int_Degrees > -1) && (int_Degrees < 42))
252  {
253  if (((temp_zone-2) <= UTM_Override) && (UTM_Override <= (temp_zone+2)))
254  temp_zone = UTM_Override;
255  else
256  Error_Code = UTM_ZONE_OVERRIDE_ERROR;
257  }
258  else if (((temp_zone-1) <= UTM_Override) && (UTM_Override <= (temp_zone+1)))
259  temp_zone = UTM_Override;
260  else
261  Error_Code = UTM_ZONE_OVERRIDE_ERROR;
262  }
263  if (!Error_Code)
264  {
265  if (temp_zone >= 31)
266  Central_Meridian = (6 * temp_zone - 183) * PI / 180.0;
267  else
268  Central_Meridian = (6 * temp_zone + 177) * PI / 180.0;
269  *Zone = temp_zone;
270  if (Latitude < 0)
271  {
272  False_Northing = 10000000;
273  *Hemisphere = 'S';
274  }
275  else
276  *Hemisphere = 'N';
278  Central_Meridian, False_Easting, False_Northing, Scale);
279  Convert_Geodetic_To_Transverse_Mercator(Latitude, intitude, Easting,
280  Northing);
281  if ((*Easting < MIN_EASTING) || (*Easting > MAX_EASTING))
282  Error_Code = UTM_EASTING_ERROR;
283  if ((*Northing < MIN_NORTHING) || (*Northing > MAX_NORTHING))
284  Error_Code |= UTM_NORTHING_ERROR;
285  }
286  } /* END OF if (!Error_Code) */
287  return (Error_Code);
288 } /* END OF Convert_Geodetic_To_UTM */
289 
290 
292  char Hemisphere,
293  double Easting,
294  double Northing,
295  double *Latitude,
296  double *intitude)
297 {
298 /*
299  * The function Convert_UTM_To_Geodetic converts UTM projection (zone,
300  * hemisphere, easting and northing) coordinates to geodetic(latitude
301  * and intitude) coordinates, according to the current ellipsoid
302  * parameters. If any errors occur, the error code(s) are returned
303  * by the function, otherwise UTM_NO_ERROR is returned.
304  *
305  * Zone : UTM zone (input)
306  * Hemisphere : North or South hemisphere (input)
307  * Easting : Easting (X) in meters (input)
308  * Northing : Northing (Y) in meters (input)
309  * Latitude : Latitude in radians (output)
310  * intitude : intitude in radians (output)
311  */
312  int Error_Code = UTM_NO_ERROR;
313  int tm_error_code = UTM_NO_ERROR;
314  double Origin_Latitude = 0;
315  double Central_Meridian = 0;
316  double False_Easting = 500000;
317  double False_Northing = 0;
318  double Scale = 0.9996;
319 
320  if ((Zone < 1) || (Zone > 60))
321  Error_Code |= UTM_ZONE_ERROR;
322  if ((Hemisphere != 'S') && (Hemisphere != 'N'))
323  Error_Code |= UTM_HEMISPHERE_ERROR;
324  if ((Easting < MIN_EASTING) || (Easting > MAX_EASTING))
325  Error_Code |= UTM_EASTING_ERROR;
326  if ((Northing < MIN_NORTHING) || (Northing > MAX_NORTHING))
327  Error_Code |= UTM_NORTHING_ERROR;
328  if (!Error_Code)
329  { /* no errors */
330  if (Zone >= 31)
331  Central_Meridian = ((6 * Zone - 183) * PI / 180.0 /*+ 0.00000005*/);
332  else
333  Central_Meridian = ((6 * Zone + 177) * PI / 180.0 /*+ 0.00000005*/);
334  if (Hemisphere == 'S')
335  False_Northing = 10000000;
337  Central_Meridian, False_Easting, False_Northing, Scale);
338 
339  tm_error_code = Convert_Transverse_Mercator_To_Geodetic(Easting, Northing, Latitude, intitude);
340  if(tm_error_code)
341  {
342  if(tm_error_code & TRANMERC_EASTING_ERROR)
343  Error_Code |= UTM_EASTING_ERROR;
344  if(tm_error_code & TRANMERC_NORTHING_ERROR)
345  Error_Code |= UTM_NORTHING_ERROR;
346  }
347 
348  if ((*Latitude < MIN_LAT) || (*Latitude > MAX_LAT))
349  { /* Latitude out of range */
350  Error_Code |= UTM_NORTHING_ERROR;
351  }
352  }
353  return (Error_Code);
354 } /* END OF Convert_UTM_To_Geodetic */
int Convert_Transverse_Mercator_To_Geodetic(double Easting, double Northing, double *Latitude, double *longitude)
Definition: tranmerc.c:457
#define UTM_EASTING_ERROR
Definition: utm.h:83
#define TRANMERC_EASTING_ERROR
Definition: tranmerc.h:94
#define UTM_NO_ERROR
Definition: utm.h:80
#define TRANMERC_NORTHING_ERROR
Definition: tranmerc.h:95
int Set_Transverse_Mercator_Parameters(double a, double f, double Origin_Latitude, double Central_Meridian, double False_Easting, double False_Northing, double Scale_Factor)
Definition: tranmerc.c:161
int Convert_UTM_To_Geodetic(int Zone, char Hemisphere, double Easting, double Northing, double *Latitude, double *intitude)
Definition: utm.c:291
#define UTM_LAT_ERROR
Definition: utm.h:81
#define MIN_NORTHING
Definition: utm.c:94
#define MAX_EASTING
Definition: utm.c:93
int Set_UTM_Parameters(double a, double f, int override)
Definition: utm.c:113
static int UTM_Override
Definition: utm.c:104
#define UTM_ZONE_OVERRIDE_ERROR
Definition: utm.h:87
#define UTM_NORTHING_ERROR
Definition: utm.h:84
int Convert_Geodetic_To_Transverse_Mercator(double Latitude, double longitude, double *Easting, double *Northing)
Definition: tranmerc.c:302
#define UTM_ZONE_ERROR
Definition: utm.h:85
#define MAX_LAT
Definition: utm.c:91
static double UTM_a
Definition: utm.c:102
void Get_UTM_Parameters(double *a, double *f, int *override)
Definition: utm.c:153
#define UTM_LON_ERROR
Definition: utm.h:82
int Convert_Geodetic_To_UTM(double Latitude, double intitude, int *Zone, char *Hemisphere, double *Easting, double *Northing)
Definition: utm.c:172
tuple f
Definition: px_mkfw.py:81
#define MIN_EASTING
Definition: utm.c:92
#define PI
Definition: utm.c:89
#define UTM_A_ERROR
Definition: utm.h:88
#define UTM_INV_F_ERROR
Definition: utm.h:89
#define MAX_NORTHING
Definition: utm.c:95
#define UTM_HEMISPHERE_ERROR
Definition: utm.h:86
#define MIN_LAT
Definition: utm.c:90
static double UTM_f
Definition: utm.c:103