OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
VcstDegRadConvertor.h
Go to the documentation of this file.
1 /**************************************************************************
2  *
3  * NAME: VcstDegRadConvertor.h
4  *
5  * DESCRIPTION: A template class meant to convert degrees to radians and
6  * vice versa for different data types.
7  * Due to its template nature any defined types are allowed.
8  * User types must have the
9  * =, *, +, / , and == operators overloaded in order to
10  * utilize this class.
11  *
12  * A separate class, VcstDegRadConvertorData, is also defined
13  * to hold static arrays used for bounds-checking performed by
14  * template class functions in VcstDegRadConvertor.
15  *
16  * Adapted directly from ProCmnDegRadConvertor.h published by
17  * Raytheon Company.
18  *
19  **************************************************************************/
20 
21 #ifndef VCSTDEGRADCONVERTOR_H
22 #define VCSTDEGRADCONVERTOR_H
23 
24 #include <cmath>
25 #include <VcstLogger.h>
26 #include <iostream>
27 #include <sstream>
28 
29 //
30 //--------------------------------------------------------------------------
31 //
32 
33 // *** W A R N I N G ***
34 // Do not rearrange order of enum values below without care - code
35 // dependencies exist.
36 //
37 // The following enum, struct, and array are for range-checking conversion results
38 // if selected (optional) by caller. Default case is "NOCHECK" where no range
39 // checks are performed on converted data.
40 
42  NOCHECK = 0,
44  CKDEG0TO90,
52  CKRAD0TOPI,
55 };
56 
57 // rangeCheckBounds: type for float upper/lower limits for bounds-checks.
58 
59 typedef struct {
60  float fLower; // float Lower Bound.
61  float fUpper; // float Upper Bound.
63 
64 // rangeCheckBounds64: type for double upper/lower limits for bounds-checks.
65 
66 typedef struct {
67  double bLower; // double Lower Bound.
68  double bUpper; // double Upper Bound.
70 
71 //
72 //--------------------------------------------------------------------------
73 //
74 
76 public:
77 
83 
89 
90 protected:
91 
92 private:
97 
102 
103 };
104 
105 //
106 //--------------------------------------------------------------------------
107 //
108 // *** W A R N I N G ***
109 // Do not rearrange order of enum values below without care - code
110 // dependencies exist.
111 
112 const int NUMCHECKS = 13; // Number of bounds checks
113 
114 // Array "rangeCheck[]" which follows is used for bounds-checking the
115 // results of float degree-radian conversions.
116 
117 //static//
119  { 0.0, 0.0}, // NOCHECK
120  { -90.0, 90.0}, // CKDEG90TO90
121  { 0.0, 90.0}, // CKDEG0TO90
122  { -180.0, 180.0}, // CKDEG180TO180
123  { 0.0, 180.0}, // CKDEG0TO180
124  { -360.0, 360.0}, // CKDEG360TO360
125  { 0.0, 360.0}, // CKDEG0TO360
126  { -FLOAT32_PIO2, FLOAT32_PIO2}, // CKRADPIO2TOPIO2
127  { 0.0, FLOAT32_PIO2}, // CKRAD0TOPIO2
128  { -FLOAT32_PI, FLOAT32_PI}, // CKRADPITOPI
129  { 0.0, FLOAT32_PI}, // CKRAD0TOPI
130  { -(FLOAT32_PI * 2), (FLOAT32_PI * 2)}, // CKRAD2PITO2PI
131  { 0.0, (FLOAT32_PI * 2)} // CKRAD0TO2PI
132 };
133 
134 //
135 //--------------------------------------------------------------------------
136 //
137 // *** W A R N I N G ***
138 // Do not rearrange order of enum values below without care - code
139 // dependencies exist.
140 
141 // Array "rangeCheck64[]" which follows is used for bounds-checking the
142 // results of double degree-radian conversions.
143 
144 //static//
146  { 0.0,
147  0.0}, // NOCHECK
148  { -90.0, 90.0}, // CKDEG90TO90
149  { 0.0, 90.0}, // CKDEG0TO90
150  { -180.0, 180.0}, // CKDEG180TO180
151  { 0.0, 180.0}, // CKDEG0TO180
152  { -360.0, 360.0}, // CKDEG360TO360
153  { 0.0, 360.0}, // CKDEG0TO360
154  { -PIO2, PIO2}, // CKRADPIO2TOPIO2
155  { 0.0, PIO2}, // CKRAD0TOPIO2
156  { -PI, PI}, // CKRADPITOPI
157  { 0.0, PI}, // CKRAD0TOPI
158  { -TWOPI, TWOPI}, // CKRAD2PITO2PI
159  { 0.0, TWOPI} // CKRAD0TO2PI
160 };
161 
162 //
163 //--------------------------------------------------------------------------
164 //
165 
166 template<class _T>
168 public:
169 
174  static int degToRadConversion(_T* in, _T* out, int count, int checkType =
175  NOCHECK);
176 
181  static int radToDegConversion(_T* in, _T* out, int count, int checkType =
182  NOCHECK);
183 
184 protected:
185 
186 private:
191 
196 
197 };
198 
199 //------------------------------------------------------------------------------
200 // Template Class Implementation
201 //------------------------------------------------------------------------------
202 
203 //-----------------------------------------------------------------------------
204 //-Constructor-
205 
206 template<class _T>
208  // Empty constructor
209 }
210 
211 //-Destructor-
212 
213 template<class _T>
215  // Empty destructor
216 }
217 
218 //-----------------------------------------------------------------------------
219 // degToRadConversion - Takes an array of values in the degree format,
220 // populates an output array of values in radian format
221 // Main template.
222 //-----------------------------------------------------------------------------
223 
224 template<class _T>
226  int count, int checkType) {
227  // Main template
228  // NOT IMPLEMENTED - DO NOT USE
229 
230  return (VCST_FAIL);
231 }
232 
233 //-----------------------------------------------------------------------------
234 // degToRadConversion - Takes an array of values in the degree format,
235 // populates an output array of values in radian format
236 // float specialization.
237 //-----------------------------------------------------------------------------
238 
239 template<>
240 int VcstDegRadConvertor<float>::degToRadConversion(float* inPtr, float* outPtr,
241  int count, int checkType) {
242  int status = VCST_SUCCESS;
243  bool rangeCheck = false;
244  float fLower = 0.0;
245  float fUpper = 0.0;
246 
247  // Validate range-checking option
248  if (checkType != NOCHECK) {
249  if ((checkType >= CKRADPIO2TOPIO2) && (checkType <= CKRAD0TO2PI)) {
250  rangeCheck = true;
251  fLower = VcstDegRadConvertorData::rangeCheck[checkType].fLower;
252  fUpper = VcstDegRadConvertorData::rangeCheck[checkType].fUpper;
253  } else {
255  "degToRadConversion failed checkType");
256  return VCST_FAIL;
257  }
258  }
259 
260  // loop through the elements to be converted
261  int nFillValues = 0;
262  for (int i = 0; i < count; ++i) {
263  // Error if NaN encountered.
264  if (std::isnan(*inPtr)) {
265  std::ostringstream oss;
266  oss << "degToRadConversion detected NaN at " << (i);
267  DEBUG_HIGH(VcstLogger::getLogger(), oss.str());
268  return (VCST_FAIL);
269  }
270 
271  // Bypass convert for fill values <= FLOAT32_FILL_TEST (-999.0)
272  if (*inPtr > FLOAT32_FILL_TEST) {
273  *outPtr = *inPtr * DEG2RAD;
274  if (rangeCheck == true) {
275  if (*outPtr < fLower) {
276  *outPtr = fLower;
277  } else if (*outPtr > fUpper) {
278  *outPtr = fUpper;
279  }
280  }
281 
282  } else {
283  *outPtr = *inPtr;
284  nFillValues++;
285  }
286  // increment the pointers
287  outPtr++;
288  inPtr++;
289  } // end for
290 
291  return (status);
292 }
293 
294 //-----------------------------------------------------------------------------
295 // degToRadConversion - Takes an array of values in the degree format,
296 // populates an output array of values in radian format
297 // double specialization.
298 //-----------------------------------------------------------------------------
299 
300 template<>
302  double* outPtr, int count, int checkType) {
303  int status = VCST_SUCCESS;
304  bool rangeCheck = false;
305  double bLower = 0.0;
306  double bUpper = 0.0;
307 
308  // Validate range-checking option
309  if (checkType != NOCHECK) {
310  if ((checkType >= CKRADPIO2TOPIO2) && (checkType <= CKRAD0TO2PI)) {
311  rangeCheck = true;
312  bLower = VcstDegRadConvertorData::rangeCheck64[checkType].bLower;
313  bUpper = VcstDegRadConvertorData::rangeCheck64[checkType].bUpper;
314  } else {
316  "degToRadConversion failed checkType");
317  return VCST_FAIL;
318  }
319  }
320 
321  // loop through the elements to be converted
322  int nFillValues = 0;
323  for (int i = 0; i < count; ++i) {
324  // Error if NaN encountered.
325  if (std::isnan(*inPtr)) {
326  std::ostringstream oss;
327  oss << "degToRadConversion detected NaN at " << (i);
328  DEBUG_HIGH(VcstLogger::getLogger(), oss.str());
329  return (VCST_FAIL);
330  }
331 
332  // Bypass convert for fill values <= FLOAT64_FILL_TEST (-999.0)
333  if (*inPtr > FLOAT64_FILL_TEST) {
334  *outPtr = *inPtr * DEG2RAD;
335  if (rangeCheck == true) {
336  if (*outPtr < bLower) {
337  *outPtr = bLower;
338  } else if (*outPtr > bUpper) {
339  *outPtr = bUpper;
340  }
341  }
342  } else {
343  *outPtr = *inPtr;
344  nFillValues++;
345  }
346  // increment the pointers
347  outPtr++;
348  inPtr++;
349  } // end for
350 
351  return (status);
352 }
353 
354 //-----------------------------------------------------------------------------
355 // radToDegConversion - Takes an array of values in the radian format,
356 // populates an output array of values in degree format
357 // Main template.
358 //-----------------------------------------------------------------------------
359 
360 template<class _T>
362  int count, int checkType) {
363  // Main template
364  // NOT IMPLEMENTED - DO NOT USE
365 
366  return (VCST_FAIL);
367 }
368 
369 //-----------------------------------------------------------------------------
370 // radToDegConversion - Takes an array of values in the radian format,
371 // populates an output array of values in degree format
372 // float specialization.
373 //-----------------------------------------------------------------------------
374 
375 template<>
376 int VcstDegRadConvertor<float>::radToDegConversion(float* inPtr, float* outPtr,
377  int count, int checkType) {
378  int status = VCST_SUCCESS;
379  bool rangeCheck = false;
380  float fLower = 0.0;
381  float fUpper = 0.0;
382 
383  if (checkType != NOCHECK) {
384  if ((checkType > NOCHECK) && (checkType <= CKDEG0TO360)) {
385  rangeCheck = true;
386  fLower = VcstDegRadConvertorData::rangeCheck[checkType].fLower;
387  fUpper = VcstDegRadConvertorData::rangeCheck[checkType].fUpper;
388  } else {
390  "radToDegConversion failed checkType");
391  return VCST_FAIL;
392  }
393  }
394 
395  // loop through the elements to be converted
396  int nFillValues = 0;
397  for (int i = 0; i < count; ++i) {
398  // Error if NaN encountered.
399  if (std::isnan(*inPtr)) {
400  std::ostringstream oss;
401  oss << "radToDegConversion detected NaN at " << (i);
402  DEBUG_HIGH(VcstLogger::getLogger(), oss.str());
403 
404  return (VCST_FAIL);
405  }
406 
407  // Bypass convert for fill values <= FLOAT32_FILL_TEST (-999.0)
408  if (*inPtr > FLOAT32_FILL_TEST) {
409  *outPtr = *inPtr * RAD2DEG;
410  if (rangeCheck == true) {
411  if (*outPtr < fLower) {
412  *outPtr = fLower;
413  } else if (*outPtr > fUpper) {
414  *outPtr = fUpper;
415  }
416  }
417  } else {
418  *outPtr = *inPtr;
419  nFillValues++;
420  }
421  // increment the pointers
422  outPtr++;
423  inPtr++;
424  } // end for
425 
426  return (status);
427 }
428 
429 //-----------------------------------------------------------------------------
430 // radToDegConversion - Takes an array of values in the radian format,
431 // populates an output array of values in degree format
432 // double specialization.
433 //-----------------------------------------------------------------------------
434 
435 template<>
437  double* outPtr, int count, int checkType) {
438  int status = VCST_SUCCESS;
439  bool rangeCheck = false;
440  double bLower = 0.0;
441  double bUpper = 0.0;
442 
443  // Validate range-checking option
444  if (checkType != NOCHECK) {
445  if ((checkType > NOCHECK) && (checkType <= CKDEG0TO360)) {
446  rangeCheck = true;
447  bLower = VcstDegRadConvertorData::rangeCheck64[checkType].bLower;
448  bUpper = VcstDegRadConvertorData::rangeCheck64[checkType].bUpper;
449  } else {
451  "radToDegConversion failed checkType");
452  return VCST_FAIL;
453  }
454  }
455 
456  // loop through the elements to be converted
457  int nFillValues = 0;
458  for (int i = 0; i < count; ++i) {
459  // Error if NaN encountered.
460  if (std::isnan(*inPtr)) {
461  std::ostringstream oss;
462  oss << "radToDegConversion detected NaN at " << (i);
463  DEBUG_HIGH(VcstLogger::getLogger(), oss.str());
464  return (VCST_FAIL);
465  }
466 
467  // Bypass convert for fill values <= FLOAT64_FILL_TEST (-999.0)
468  if (*inPtr > FLOAT64_FILL_TEST) {
469  *outPtr = *inPtr * RAD2DEG;
470  if (rangeCheck == true) {
471  if (*outPtr < bLower) {
472  *outPtr = bLower;
473  } else if (*outPtr > bUpper) {
474  *outPtr = bUpper;
475  }
476  }
477  } else {
478  *outPtr = *inPtr;
479  nFillValues++;
480  }
481  // increment the pointers
482  outPtr++;
483  inPtr++;
484  } // end for
485 
486  return (status);
487 }
488 
489 #endif
@ CKDEG90TO90
@ CKDEG0TO90
const int VCST_SUCCESS
Definition: VcstCmnConsts.h:46
const int VCST_FAIL
Definition: VcstCmnConsts.h:47
const int NUMCHECKS
int status
Definition: l1_czcs_hdf.c:32
static int degToRadConversion(_T *in, _T *out, int count, int checkType=NOCHECK)
@ CKDEG0TO360
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude resolving resolving GSFcd00179 Corrected handling of fill values for[Sensor|Solar][Zenith|Azimuth] resolving MODxl01751 Changed to validate LUT version against a value retrieved from the resolving MODxl02056 Changed to calculate Solar Diffuser angles without adjustment for estimated post launch changes in the MODIS orientation relative to incidentally resolving defects MODxl01766 Also resolves MODxl01947 Changed to ignore fill values in SCI_ABNORM and SCI_STATE rather than treating them as resolving MODxl01780 Changed to use spacecraft ancillary data to recognise when the mirror encoder data is being set by side A or side B and to change calculations accordingly This removes the need for seperate LUTs for Side A and Side B data it makes the new LUTs incompatible with older versions of the and vice versa Also resolves MODxl01685 A more robust GRing algorithm is being which will create a non default GRing anytime there s even a single geolocated pixel in a granule Removed obsolete messages from seed as required for compatibility with version of the SDP toolkit Corrected test output file names to end in out
Definition: HISTORY.txt:422
@ CKDEG180TO180
const float FLOAT32_PIO2
@ CKDEG360TO360
@ CKRADPITOPI
const double TWOPI
Definition: AfrtConstants.h:85
const float FLOAT32_FILL_TEST
#define PI
Definition: l3_get_org.c:6
const double FLOAT64_FILL_TEST
Definition: VcstCmnConsts.h:99
@ CKRAD0TOPIO2
const float FLOAT32_PI
#define RAD2DEG
Definition: GEO_geo.h:173
static VcstLogger & getLogger()
@ CKRAD2PITO2PI
static rangeCheckBounds64 rangeCheck64[13]
RangeCheckTypeEnum
@ CKRADPIO2TOPIO2
@ CKRAD0TO2PI
@ NOCHECK
@ CKRAD0TOPI
const double PIO2
@ CKDEG0TO180
static rangeCheckBounds rangeCheck[13]
#define DEBUG_HIGH(logger, message)
Definition: VcstLogger.h:273
int i
Definition: decode_rs.h:71
#define DEG2RAD
Definition: GEO_geo.h:174
static int radToDegConversion(_T *in, _T *out, int count, int checkType=NOCHECK)
int count
Definition: decode_rs.h:79