OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimGeoref.cpp
Go to the documentation of this file.
2 
3 #include <cstdlib>
4 #include <cstring>
5 #include <cstdio>
6 #include <cmath>
7 #include <cctype>
8 
9 // These are Geotrans defines and code.
10 /***************************************************************************/
11 /*
12  * DEFINES
13  */
14 #define GEOREF_NO_ERROR 0x0000
15 #define GEOREF_LAT_ERROR 0x0001
16 #define GEOREF_LON_ERROR 0x0002
17 #define GEOREF_STR_ERROR 0x0004
18 #define GEOREF_STR_LAT_ERROR 0x0008
19 #define GEOREF_STR_LON_ERROR 0x0010
20 #define GEOREF_STR_LAT_MIN_ERROR 0x0020
21 #define GEOREF_STR_LON_MIN_ERROR 0x0040
22 #define GEOREF_PRECISION_ERROR 0x0080
23 
24 
26  long /* precision */ )
27 {
28  double lat, lon;
29 
30  long result = Convert_GEOREF_To_Geodetic(const_cast<char*>(georefString.c_str()),
31  &lat,
32  &lon);
33  if(result == GEOREF_NO_ERROR)
34  {
35  thePt.latr(lat);
36  thePt.lonr(lon);
37  }
38 }
39 
41 {
42  thePt = groundPt;
43 }
44 
46 {
47 }
48 
50 {
51  char resultString[100];
52 
53  long result = Convert_Geodetic_To_GEOREF(thePt.latr(),
54  thePt.lonr(),
55  precision,
56  resultString);
57  if(result == GEOREF_NO_ERROR)
58  {
59  return ossimString(resultString);
60  }
61 
62  return ossimString("");
63 }
64 
65 /***************************************************************************/
66 /*
67  * DEFINES
68  */
69 
70 #define TRUE 1
71 #define FALSE 0
72 #define LATITUDE_LOW -90 /* Minimum latitude */
73 #define LATITUDE_HIGH 90 /* Maximum latitude */
74 #define LONGITUDE_LOW -180 /* Minimum longitude */
75 #define LONGITUDE_HIGH 360 /* Maximum longitude */
76 #define MIN_PER_DEG 60 /* Number of minutes per degree */
77 #define GEOREF_MINIMUM 4 /* Minimum number of chars for GEOREF */
78 #define GEOREF_MAXIMUM 14 /* Maximum number of chars for GEOREF */
79 #define GEOREF_LETTERS 4 /* Number of letters in GEOREF string */
80 #define MAX_PRECISION 5 /* Maximum precision of minutes part */
81 #define LETTER_I 8 /* Index for letter I */
82 #define LETTER_M 12 /* Index for letter M */
83 #define LETTER_O 14 /* Index for letter O */
84 #define LETTER_Q 16 /* Index for letter Q */
85 #define LETTER_Z 25 /* Index for letter Z */
86 #define LETTER_A_OFFSET 65 /* Letter A offset in character set */
87 #define ZERO_OFFSET 48 /* Number zero offset in character set */
88 #define PI 3.14159265358979323e0 /* PI */
89 #define DEGREE_TO_RADIAN (PI / 180.0)
90 #define RADIAN_TO_DEGREE (180.0 / PI)
91 #define QUAD 15 /* Degrees per grid square */
92 #define ROUND_ERROR 0.0000005 /* Rounding factor */
93 
94 
95 /***************************************************************************/
96 /*
97  * FUNCTIONS
98  */
99 
100 
101 long Extract_Degrees (char *georef,
102  double *latitude,
103  double *longitude)
104 { /* BEGIN Extract_Degrees */
105 /*
106  * This function extracts the latitude and longitude degree parts of the
107  * GEOREF string. The latitude and longitude degree parts are the first four
108  * characters.
109  *
110  * georef : GEOREF string (input)
111  * latitude : Latitude in degrees (output)
112  * longitude : Longitude in degrees (output)
113  */
114  long i; /* counter in for loops */
115  long temp_char; /* temporary character */
116  long letter_number[GEOREF_LETTERS]; /* number corresponding to letter */
117  long error_code = GEOREF_NO_ERROR;
118 
119  for (i=0;i<GEOREF_LETTERS;i++)
120  {
121  temp_char = toupper(georef[i]);
122  temp_char = temp_char - LETTER_A_OFFSET;
123  if ((!isalpha(georef[i]))
124  || (temp_char == LETTER_I)
125  || (temp_char == LETTER_O))
126  {
127  if ((i == 0) || (i == 2))
128  error_code |= GEOREF_STR_LON_ERROR;
129  else
130  error_code |= GEOREF_STR_LAT_ERROR;
131  }
132  letter_number[i] = temp_char;
133  }
134  for (i=0;i<4;i++)
135  {
136  if (letter_number[i] > LETTER_O)
137  letter_number[i] -= 2;
138  else if (letter_number[i] > LETTER_I)
139  letter_number[i] -= 1;
140  }
141  if ((letter_number[0] > 23) || (letter_number[2] > 14))
142  error_code |= GEOREF_STR_LON_ERROR;
143  if ((letter_number[1] > 11) || (letter_number[3] > 14))
144  error_code |= GEOREF_STR_LAT_ERROR;
145  *latitude = (double)(letter_number[1]) * QUAD + (double)(letter_number[3]);
146  *longitude = (double)(letter_number[0]) * QUAD + (double)(letter_number[2]);
147  return (error_code);
148 } /* END Extract_Degrees */
149 
150 
151 long Extract_Minutes (char *georef,
152  long start,
153  long length,
154  long ERROR_TYPE,
155  double *minutes)
156 { /* BEGIN Extract_Minutes */
157 /*
158  * This function extracts the minutes from the GEOREF string. The minutes
159  * part begins at position start and has length length. The ERROR_TYPE is
160  * to allow this function to work with both latitude and longitude minutes.
161  *
162  * georef : GEOREF string (input)
163  * start : Start position in the GEOREF string (input)
164  * length : length of minutes in the GEOREF string (input)
165  * ERROR_TYPE : has a value of either GEOREF_STR_LAT_MIN_ERROR (input)
166  * or GEOREF_STR_LON_MIN_ERROR
167  * minutes: minute part (output)
168  */
169  long i; /* counter in for loop */
170  long error_code = GEOREF_NO_ERROR;
171  char temp_str[(GEOREF_MAXIMUM-GEOREF_LETTERS)/2 + 1];
172 
173  for (i=0;i<length;i++)
174  {
175  if (isdigit(georef[start+i]))
176  temp_str[i] = georef[start+i];
177  else
178  error_code |= ERROR_TYPE;
179  }
180  temp_str[length] = 0;
181  *minutes = (double)atof(temp_str); /* need atof, atoi can't handle 59999 */
182  while (length > 2)
183  {
184  *minutes = *minutes / 10;
185  length = length - 1;
186  }
187  if (*minutes > (double)MIN_PER_DEG)
188  error_code |= ERROR_TYPE;
189  return (error_code);
190 } /* END OF Extract_Minutes */
191 
192 
193 long Round_GEOREF (double value)
194 /* Round value to nearest integer, using standard engineering rule */
195 { /* Round_GEOREF */
196  double ivalue;
197  long ival;
198  double fraction = modf (value, &ivalue);
199  ival = (long)(ivalue);
200  if ((fraction > 0.5) || ((fraction == 0.5) && (ival%2 == 1)))
201  ival++;
202  return (ival);
203 } /* Round_GEOREF */
204 
205 
206 void Convert_Minutes_To_String(double minutes,
207  long precision,
208  char *str)
209 { /* BEGIN Convert_Minutes_To_String */
210 /*
211  * This function converts minutes to a string of length precision.
212  *
213  * minutes : Minutes to be converted (input)
214  * precision : Length of resulting string (input)
215  * str : String to hold converted minutes (output)
216  */
217  double divisor;
218  long min;
219  divisor = pow ((double)10.0, (int)(5 - precision));
220  if (minutes == 60.0)
221  minutes = 59.999;
222  minutes = minutes * 1000;
223  min = Round_GEOREF (minutes/divisor);
224  sprintf (str, "%*.*ld", (int)precision, (int)precision, min);
225  if (precision == 1)
226  strcat (str, "0");
227 } /* END Convert_Minutes_To_String */
228 
229 
231  double *latitude,
232  double *longitude)
233 { /* BEGIN Convert_GEOREF_To_Geodetic */
234 /*
235  * This function converts a GEOREF coordinate string to Geodetic (latitude
236  * and longitude in radians) coordinates.
237  *
238  * georef : GEOREF coordinate string. (input)
239  * latitude : Latitude in radians. (output)
240  * longitude : Longitude in radians. (output)
241  *
242  * CALLS THE FOLLOWING FUNCTIONS:
243  *
244  * Extract_Degrees
245  * Extract_Minutes
246  */
247  long start; /* Position in the GEOREF string */
248  long minutes_length; /* length of minutes in the GEOREF string */
249  long georef_length; /* length of GEOREF string */
250  double origin_long; /* Origin longitude */
251  double origin_lat; /* Origin latitude */
252  double long_minutes; /* Longitude minute part of GEOREF */
253  double lat_minutes; /* Latitude minute part of GEOREF */
254  long error_code = GEOREF_NO_ERROR;
255 
256  origin_long = (double)LONGITUDE_LOW;
257  origin_lat = (double)LATITUDE_LOW;
258  georef_length = (long)strlen(georef);
259  if ((georef_length < GEOREF_MINIMUM) || (georef_length > GEOREF_MAXIMUM)
260  || ((georef_length % 2) != 0))
261  {
262  error_code |= GEOREF_STR_ERROR;
263  }
264  if (!error_code)
265  {
266  error_code |= Extract_Degrees(georef,latitude,longitude);
267  start = GEOREF_LETTERS;
268  minutes_length = (georef_length - start) / 2;
269  if (!error_code)
270  {
271  error_code |= Extract_Minutes(georef, start, minutes_length,
272  GEOREF_STR_LON_MIN_ERROR, &long_minutes);
273  if (!error_code)
274  {
275  error_code |= Extract_Minutes(georef, (start+minutes_length),
276  minutes_length, GEOREF_STR_LAT_MIN_ERROR, &lat_minutes);
277  *latitude = *latitude + origin_lat + lat_minutes / (double)MIN_PER_DEG;
278  *longitude = *longitude + origin_long + long_minutes / (double)MIN_PER_DEG;
279  *latitude = *latitude * DEGREE_TO_RADIAN;
280  *longitude = *longitude * DEGREE_TO_RADIAN;
281  }
282  }
283  }
284  return (error_code);
285 } /* END OF Convert_GEOREF_To_Geodetic */
286 
287 
289  double longitude,
290  long precision,
291  char *georef)
292 { /* BEGIN Convert_Geodetic_To_GEOREF */
293 /*
294  * This function converts Geodetic (latitude and longitude in radians)
295  * coordinates to a GEOREF coordinate string. Precision specifies the
296  * number of digits in the GEOREF string for latitude and longitude:
297  * 0 for nearest degree
298  * 1 for nearest ten minutes
299  * 2 for nearest minute
300  * 3 for nearest tenth of a minute
301  * 4 for nearest hundredth of a minute
302  * 5 for nearest thousandth of a minute
303  *
304  * latitude : Latitude in radians. (input)
305  * longitude : Longitude in radians. (input)
306  * precision : Precision specified by the user. (input)
307  * georef : GEOREF coordinate string. (output)
308  *
309  * CALLS THE FOLLOWING FUNCTIONS:
310  *
311  * Convert_Minutes_To_String
312  */
313 
314  double long_min; /* GEOREF longitude minute part */
315  double lat_min; /* GEOREF latitude minute part */
316  double origin_long; /* Origin longitude (-180 degrees)*/
317  double origin_lat; /* Origin latitude (-90 degrees) */
318  long letter_number[GEOREF_LETTERS + 1]; /* GEOREF letters */
319  char long_min_str[MAX_PRECISION + 1]; /* Longitude minute string */
320  char lat_min_str[MAX_PRECISION + 1]; /* Latitude minute string */
321  long i; /* counter in for loop */
322  long error_code = GEOREF_NO_ERROR;
323 
324  latitude = latitude * RADIAN_TO_DEGREE;
325  longitude = longitude * RADIAN_TO_DEGREE;
326  if ((latitude < (double)LATITUDE_LOW)
327  || (latitude > (double)LATITUDE_HIGH))
328  error_code |= GEOREF_LAT_ERROR;
329  if ((longitude < (double)LONGITUDE_LOW)
330  || (longitude > (double)LONGITUDE_HIGH))
331  error_code |= GEOREF_LON_ERROR;
332  if ((precision < 0) || (precision > MAX_PRECISION))
333  error_code |= GEOREF_PRECISION_ERROR;
334  if (!error_code)
335  {
336  if (longitude > 180)
337  longitude -= 360;
338  origin_long = (double)LONGITUDE_LOW;
339  origin_lat = (double)LATITUDE_LOW;
340  letter_number[0] = (long)((longitude-origin_long) / QUAD + ROUND_ERROR);
341  longitude = longitude - ((double)letter_number[0] * QUAD + origin_long);
342  letter_number[2] = (long)(longitude + ROUND_ERROR);
343  long_min = (longitude - (double)letter_number[2]) * (double)MIN_PER_DEG;
344  letter_number[1] = (long)((latitude - origin_lat) / QUAD + ROUND_ERROR);
345  latitude = latitude - ((double)letter_number[1] * QUAD + origin_lat);
346  letter_number[3] = (long)(latitude + ROUND_ERROR);
347  lat_min = (latitude - (double)letter_number[3]) * (double)MIN_PER_DEG;
348  for (i = 0;i < 4; i++)
349  {
350  if (letter_number[i] >= LETTER_I)
351  letter_number[i] += 1;
352  if (letter_number[i] >= LETTER_O)
353  letter_number[i] += 1;
354  }
355 
356  if (letter_number[0] == 26)
357  { /* longitude of 180 degrees */
358  letter_number[0] = LETTER_Z;
359  letter_number[2] = LETTER_Q;
360  long_min = 59.999;
361  }
362  if (letter_number[1] == 13)
363  { /* latitude of 90 degrees */
364  letter_number[1] = LETTER_M;
365  letter_number[3] = LETTER_Q;
366  lat_min = 59.999;
367  }
368 
369  for (i=0;i<4;i++)
370  georef[i] = (char)(letter_number[i] + LETTER_A_OFFSET);
371  georef[4] = 0;
372  Convert_Minutes_To_String(long_min,precision,long_min_str);
373  Convert_Minutes_To_String(lat_min,precision,lat_min_str);
374  strcat(georef,long_min_str);
375  strcat(georef,lat_min_str);
376  }
377  return (error_code);
378 } /* END OF Convert_Geodetic_To_GEOREF */
long Extract_Minutes(char *georef, long start, long length, long ERROR_TYPE, double *minutes)
#define LONGITUDE_HIGH
Definition: ossimGeoref.cpp:75
#define GEOREF_LON_ERROR
Definition: ossimGeoref.cpp:16
#define LETTER_O
Definition: ossimGeoref.cpp:83
#define GEOREF_LETTERS
Definition: ossimGeoref.cpp:79
#define GEOREF_PRECISION_ERROR
Definition: ossimGeoref.cpp:22
long Round_GEOREF(double value)
#define LETTER_Z
Definition: ossimGeoref.cpp:85
#define LATITUDE_LOW
Definition: ossimGeoref.cpp:72
#define RADIAN_TO_DEGREE
Definition: ossimGeoref.cpp:90
ossimGpt thePt
Definition: ossimGeoref.h:31
#define LONGITUDE_LOW
Definition: ossimGeoref.cpp:74
#define LETTER_I
Definition: ossimGeoref.cpp:81
long Convert_Geodetic_To_GEOREF(double Latitude, double Longitude, long Precision, char *georef)
#define DEGREE_TO_RADIAN
Definition: ossimGeoref.cpp:89
#define ROUND_ERROR
Definition: ossimGeoref.cpp:92
long Extract_Degrees(char *georef, double *latitude, double *longitude)
#define LATITUDE_HIGH
Definition: ossimGeoref.cpp:73
#define GEOREF_STR_ERROR
Definition: ossimGeoref.cpp:17
#define LETTER_A_OFFSET
Definition: ossimGeoref.cpp:86
#define GEOREF_STR_LON_MIN_ERROR
Definition: ossimGeoref.cpp:21
double lonr() const
Returns the longitude in radian measure.
Definition: ossimGpt.h:76
void Convert_Minutes_To_String(double minutes, long precision, char *str)
#define GEOREF_STR_LAT_MIN_ERROR
Definition: ossimGeoref.cpp:20
#define QUAD
Definition: ossimGeoref.cpp:91
#define LETTER_Q
Definition: ossimGeoref.cpp:84
#define GEOREF_STR_LAT_ERROR
Definition: ossimGeoref.cpp:18
#define MAX_PRECISION
Definition: ossimGeoref.cpp:80
ossimString toString(long precision)
Definition: ossimGeoref.cpp:49
#define GEOREF_MINIMUM
Definition: ossimGeoref.cpp:77
#define GEOREF_STR_LON_ERROR
Definition: ossimGeoref.cpp:19
#define MIN_PER_DEG
Definition: ossimGeoref.cpp:76
double latr() const
latr().
Definition: ossimGpt.h:66
const char * c_str() const
Returns a pointer to a null-terminated array of characters representing the string&#39;s contents...
Definition: ossimString.h:396
#define LETTER_M
Definition: ossimGeoref.cpp:82
#define GEOREF_MAXIMUM
Definition: ossimGeoref.cpp:78
#define GEOREF_NO_ERROR
Definition: ossimGeoref.cpp:14
long Convert_GEOREF_To_Geodetic(char *georef, double *Latitude, double *Longitude)
#define GEOREF_LAT_ERROR
Definition: ossimGeoref.cpp:15
#define min(a, b)
Definition: auxiliary.h:75