CppEphem
CEAngle.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * CEAngle.cpp: CppEphem *
3  * ----------------------------------------------------------------------- *
4  * Copyright © 2019 JCardenzana *
5  * ----------------------------------------------------------------------- *
6  * *
7  * This program is free software: you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation, either version 3 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License *
18  * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19  * *
20  ***************************************************************************/
21 
31 #include <algorithm>
32 
33 #include "CEAngle.h"
34 #include "CEException.h"
35 
36 /**********************************************************************/
40 {
41  init_members();
42 }
43 
44 
45 /**********************************************************************/
52 CEAngle::CEAngle(const double& angle)
53 {
54  init_members();
56 }
57 
58 
59 /**********************************************************************/
64 CEAngle::CEAngle(const CEAngle& other)
65 {
66  init_members();
67  copy_members(other);
68 }
69 
70 
71 /**********************************************************************/
75 {
76  free_members();
77 }
78 
79 
80 /**********************************************************************/
86 CEAngle& CEAngle::operator=(const CEAngle& other)
87 {
88  if (this != &other) {
89  free_members();
90  init_members();
91  copy_members(other);
92  }
93  return *this;
94 }
95 
96 
97 /**********************************************************************/
103 CEAngle& CEAngle::operator=(const double& other)
104 {
105  free_members();
106  init_members();
108  return *this;
109 }
110 
111 
112 /**********************************************************************/
115 CEAngle::operator double()
116 {
117  return angle_;
118 }
119 
120 
121 /**********************************************************************/
124 CEAngle::operator double() const
125 {
126  return angle_;
127 }
128 
129 
130 /**********************************************************************/
143 CEAngle CEAngle::Hms(const char* angle_str,
144  const char& delim)
145 {
146  CEAngle angle;
147  angle.SetAngle(angle_str, CEAngleType::HMS, delim);
148  return angle;
149 }
150 
151 
152 /**********************************************************************/
165 CEAngle CEAngle::Hms(const std::vector<double>& angle_vec)
166 {
167  CEAngle angle;
168  angle.SetAngle(angle_vec, CEAngleType::HMS);
169  return angle;
170 }
171 
172 
173 /**********************************************************************/
179 std::string CEAngle::HmsStr(const char& delim) const
180 {
181  // Get the angle as a vector
182  std::vector<double> hms_d = HmsVect();
183 
184  // Assemble the string using the specified delimiter
185  return CppEphem::StrOpt::join_angle(hms_d, delim);
186 }
187 
188 
189 /**********************************************************************/
200 std::vector<double> CEAngle::HmsVect(void) const
201 {
202  // Stores the resulting values
203  std::vector<int> HMS_i(4);
204 
205  // Stores the sign
206  char pm;
207  iauA2tf(9, angle_, &pm, &HMS_i[0]);
208 
209  // Convert the values into doubles
210  std::vector<double> HMS_d(HMS_i.size());
211  // Scale the fraction to be a true fraction
212  HMS_d[0] = double(HMS_i[0]);
213  HMS_d[1] = double(HMS_i[1]);
214  HMS_d[2] = double(HMS_i[2]);
215  HMS_d[3] = double(HMS_i[3])/1.0e9;
216  // Multiply the degree by a negative
217  if (pm == '-') HMS_d[0] *= -1;
218 
219  return HMS_d;
220 }
221 
222 
223 /**********************************************************************/
235 CEAngle CEAngle::Dms(const char* angle_str,
236  const char& delim)
237 {
238  CEAngle angle;
239  angle.SetAngle(angle_str, CEAngleType::DMS, delim);
240  return angle;
241 }
242 
243 
244 /**********************************************************************/
257 CEAngle CEAngle::Dms(const std::vector<double>& angle_vec)
258 {
259  CEAngle angle;
260  angle.SetAngle(angle_vec, CEAngleType::DMS);
261  return angle;
262 }
263 
264 
265 /**********************************************************************/
271 std::string CEAngle::DmsStr(const char& delim) const
272 {
273  // Get the angle as a vector
274  std::vector<double> dms_d = DmsVect();
275 
276  // Assemble the string using the specified delimiter
277  return CppEphem::StrOpt::join_angle(dms_d, delim);
278 }
279 
280 
281 /**********************************************************************/
292 std::vector<double> CEAngle::DmsVect(void) const
293 {
294  // Variables for holding the results
295  char sign;
296  std::vector<int> DMS_i(4, 0.0);
297 
298  // Run the appropriate SOFA value
299  iauA2af(9, angle_, &sign, &DMS_i[0]);
300 
301  // Fill the values into a double vector
302  std::vector<double> DMS_d(4, 0.0);
303  DMS_d[0] = DMS_i[0] * (sign == '-' ? -1.0 : 1.0);
304  DMS_d[1] = DMS_i[1];
305  DMS_d[2] = DMS_i[2];
306  DMS_d[3] = DMS_i[3] * 1.0e-9;
307 
308  return DMS_d ;
309 }
310 
311 
312 /**********************************************************************/
318 CEAngle CEAngle::Deg(const double& angle)
319 {
320  return CEAngle(angle * DD2R);
321 }
322 
323 
324 /**********************************************************************/
329 double CEAngle::Deg(void) const
330 {
331  return angle_ * DR2D;
332 }
333 
334 
335 /**********************************************************************/
341 CEAngle CEAngle::Rad(const double& angle)
342 {
343  return CEAngle(angle);
344 }
345 
346 
347 /**********************************************************************/
352 double CEAngle::Rad(void) const
353 {
354  return angle_;
355 }
356 
357 
358 /**********************************************************************/
370 void CEAngle::SetAngle(const double& angle,
371  const CEAngleType& angle_type)
372 {
373  // Set from degree angle
374  if (angle_type == CEAngleType::DEGREES) {
375  angle_ = angle * DD2R;
376  }
377  // Set from radians angle
378  else if (angle_type == CEAngleType::RADIANS) {
379  angle_ = angle;
380  }
381  // Otherwise throw an exception
382  else {
384  "CEAngle::SetAngle(const double&, const CEAngleType&)",
385  "[ERROR] Method cannot be called with the provided CEAngleType");
386  }
387 
388  return;
389 }
390 
391 
392 /**********************************************************************/
401 void CEAngle::SetAngle(const char* angle_str,
402  const CEAngleType& angle_type,
403  const char& delim)
404 {
405  // Angle is a degree or radian
406  if ((angle_type == CEAngleType::DEGREES) || (angle_type == CEAngleType::RADIANS)) {
407  SetAngle(std::stod(angle_str), angle_type);
408  }
409 
410  // Otherwise the angle is a delimited string (i.e. something like HH:MM:SS)
411  else {
412 
413  // Create a string vector to hold the parsed values
414  std::vector<std::string> angle_vec;
415  angle_vec.reserve(4);
416 
417  // Handle specific delimitors
418  if (delim != 0) {
419 
420  // Split the string
421  CppEphem::StrOpt::split(angle_str, delim, &angle_vec);
422 
423  // Throw an error if the string was not properly split
424  if (angle_vec.size() < 3) {
426  "CEAngle::SetAngle(const string&, const CEAngleType&, const char&)",
427  "Could not find specified delimiter: " + std::string(1,delim));
428  }
429 
430  // Now format the string in the appropriate way
431  std::vector<double> angle_dbl;
432  for (auto& ang : angle_vec) {
433  angle_dbl.push_back(std::stod(ang));
434  }
435  SetAngle(angle_dbl, angle_type);
436  }
437 
438  // Handle delimiter agnostic format
439  else if (delim == 0) {
440 
441  // Create vector of delimiters to be tried
442  std::vector<char> delim_list = {':', ' '};
443 
444  // Loop through the list of delimiters
445  for (char d : delim_list) {
446  // Check if the delimiter is in the string
447  if (std::string(angle_str).find(d) != std::string::npos) {
448  // Try to set the angle
449  SetAngle(angle_str, angle_type, d);
450  }
451  }
452  }
453  }
454 
455  return;
456 }
457 
458 
459 /**********************************************************************/
467 void CEAngle::SetAngle(const std::vector<double>& angle_vec,
468  const CEAngleType& angle_type)
469 {
470  // Hours minutes seconds
471  if (angle_type == CEAngleType::HMS) {
472  SetAngle_HmsVect(angle_vec);
473  }
474  // Degrees arcmins arcseconds
475  else if (angle_type == CEAngleType::DMS) {
476  SetAngle_DmsVect(angle_vec);
477  }
478  // Otherwise, all done
479  else {
481  "CEAngle::SetAngle(const std::vector<double>&, const CEAngleType&)",
482  "[ERROR] Unknown angle type");
483  }
484 }
485 
486 
487 /**********************************************************************/
497 void CEAngle::SetAngle_HmsVect(const std::vector<double>& angle)
498 {
499  // Get the angle sign
500  char pm = (angle[0] >= 0.0) ? '+' : '-';
501 
502  // Do the conversion
503  double ang(0.0);
504  double sec = (angle.size() == 4) ? angle[2]+angle[3] : angle[2];
505  int err = iauTf2a(pm, std::abs(angle[0]), int(angle[1]), sec, &ang);
506 
507  // Handle the error
508  if (err) {
509  std::string msg = "[ERROR] ";
510  switch(err) {
511  // Hours out of bounds
512  case 1:
513  msg += "Hour value \'" + std::to_string(angle[0]) + "\' not in range 0-23";
514  throw CEException::invalid_value("CEAngle::SetAngle_HmsVect", msg);
515  // Minutes out of bounds
516  case 2:
517  msg += "Minutes value \'" + std::to_string(angle[1]) + "\' not in range 0-59";
518  throw CEException::invalid_value("CEAngle::SetAngle_HmsVect", msg);
519  // Seconds out of bounds
520  case 3:
521  msg += "Seconds value \'" + std::to_string(sec) + "\' not in range 0-59.999...";
522  throw CEException::invalid_value("CEAngle::SetAngle_HmsVect", msg);
523  }
524  }
525 
526  // Set the angle
528  return;
529 }
530 
531 
532 /**********************************************************************/
542 void CEAngle::SetAngle_DmsVect(const std::vector<double>& angle)
543 {
544  // Get the angle's sign
545  char sign = (angle[0] < 0.0) ? '-' : '+';
546 
547  // Convert the values to an angle in degrees
548  double ang(0.0);
549  double sec = (angle.size() == 4) ? angle[2]+angle[3] : angle[2];
550 
551  // Pass the values to the appropriate SOFA algorithm
552  int err = iauAf2a(sign, int(angle[0]), int(angle[1]), sec, &ang);
553 
554  // Handle the error
555  if (err) {
556  std::string msg = "[ERROR] ";
557  switch(err) {
558  // Hours out of bounds
559  case 1:
560  msg += "Degree value \'" + std::to_string(angle[0]) + "\' not in range 0-359";
561  throw CEException::invalid_value("CEAngle::SetAngle_DmsVect", msg);
562  // Minutes out of bounds
563  case 2:
564  msg += "Arcmin value \'" + std::to_string(angle[1]) + "\' not in range 0-59";
565  throw CEException::invalid_value("CEAngle::SetAngle_DmsVect", msg);
566  // Seconds out of bounds
567  case 3:
568  msg += "Arcsec value \'" + std::to_string(sec) + "\' not in range 0-59.999...";
569  throw CEException::invalid_value("CEAngle::SetAngle_DmsVect", msg);
570  }
571  }
572 
573  // Set the angle
575  return;
576 }
577 
578 
579 /**********************************************************************/
582 void CEAngle::free_members(void)
583 {
584  // Nothing to do here
585  return;
586 }
587 
588 
589 /**********************************************************************/
594 void CEAngle::copy_members(const CEAngle& other)
595 {
596  angle_ = other.angle_;
597 }
598 
599 
600 /**********************************************************************/
603 void CEAngle::init_members(void)
604 {
605  angle_ = 0.0;
606 }
CEAngle::Dms
static CEAngle Dms(const char *angle_str, const char &delim=0)
Return double constructed from a string representing degrees, minutes, seconds.
Definition: CEAngle.cpp:234
CEAngle::~CEAngle
virtual ~CEAngle()
Destructor.
Definition: CEAngle.cpp:73
CEAngle::DmsStr
std::string DmsStr(const char &delim=':') const
Return string representing the angle in DD:MM:SS.
Definition: CEAngle.cpp:270
CEAngle::DmsVect
std::vector< double > DmsVect(void) const
Return vector of doubles representing the {degrees, arcmin, arcsec, arcsec-fraction}.
Definition: CEAngle.cpp:291
CEAngleType
CEAngleType
Definition: CEAngle.h:30
CEAngle::free_members
void free_members(void)
Free allocated data members.
Definition: CEAngle.cpp:581
CppEphem::StrOpt::join_angle
std::string join_angle(const std::vector< double > &values, const char &delim)
Method for splitting a string based on some delimiter into a vector of strings.
Definition: CENamespace.cpp:267
CEAngle::HmsVect
std::vector< double > HmsVect(void) const
Return vector of doubles representing the {hours, min, sec, sec-fraction}.
Definition: CEAngle.cpp:199
CEException.h
CEAngle
Definition: CEAngle.h:38
CEAngle::Rad
double Rad(void) const
Return angle in radians as a double.
Definition: CEAngle.cpp:351
CEAngle::SetAngle
void SetAngle(const double &angle, const CEAngleType &angle_type=CEAngleType::RADIANS)
Set the angle from a double.
Definition: CEAngle.cpp:369
CEException::invalid_delimiter
Definition: CEException.h:80
CEAngle.h
CEAngle::SetAngle_DmsVect
void SetAngle_DmsVect(const std::vector< double > &angle)
Set the angle from a vector of doubles of the form {degrees, arcmin, arcsec}.
Definition: CEAngle.cpp:541
CEAngleType::DEGREES
CEAngle::copy_members
void copy_members(const CEAngle &other)
Copy data members from another CEAngle object.
Definition: CEAngle.cpp:593
CEAngle::angle_
double angle_
Angle stored in radians.
Definition: CEAngle.h:93
CEAngle::operator=
CEAngle & operator=(const CEAngle &other)
Copy assignment operator.
Definition: CEAngle.cpp:85
CEAngle::init_members
void init_members(void)
Initialize data members.
Definition: CEAngle.cpp:602
CEAngleType::RADIANS
CEException::invalid_value
Definition: CEException.h:73
CEAngle::Deg
double Deg(void) const
Return angle in degrees as a double.
Definition: CEAngle.cpp:328
CEAngle::Hms
static CEAngle Hms(const char *angle_str, const char &delim=0)
Return angle constructed from a string representing hours, minutes, seconds.
Definition: CEAngle.cpp:142
CEAngle::CEAngle
CEAngle()
Default constructor.
Definition: CEAngle.cpp:38
CppEphem::StrOpt::split
void split(const std::string &s, const char &delim, std::vector< std::string > *elems)
Method for splitting a string based on some delimiter into a vector of strings.
Definition: CENamespace.cpp:209
CEAngleType::DMS
CEAngleType::HMS
CEAngle::HmsStr
std::string HmsStr(const char &delim=':') const
Return string representing the angle in HH:MM:SS.
Definition: CEAngle.cpp:178
CEAngle::SetAngle_HmsVect
void SetAngle_HmsVect(const std::vector< double > &angle)
Set the angle from a vector of doubles representing {hours, minutes, seconds}.
Definition: CEAngle.cpp:496