NumCpp  2.12.1
A Templatized Header Only C++ Implementation of the Python NumPy Library
Celestial.hpp
Go to the documentation of this file.
1
28#pragma once
29
30#include <cmath>
31#include <iostream>
32#include <string>
33
36#include "NumCpp/Core/Types.hpp"
40#include "NumCpp/NdArray.hpp"
43#include "NumCpp/Utils/sqr.hpp"
45
47{
48 //================================================================================
50 class RA
51 {
52 public:
53 //============================================================================
56 RA() = default;
57
58 //============================================================================
63 explicit RA(double inDegrees) :
64 degrees_(inDegrees),
65 radians_(deg2rad(inDegrees))
66 {
67 if (inDegrees < 0 || inDegrees >= 360)
68 {
69 THROW_INVALID_ARGUMENT_ERROR("input degrees must be of the range [0, 360)");
70 }
71
72 hours_ = static_cast<uint8>(std::floor(degrees_ / 15.));
73 const double decMinutes = (degrees_ - static_cast<double>(hours_) * 15.) * 4.;
74 minutes_ = static_cast<uint8>(std::floor(decMinutes));
75 seconds_ = static_cast<double>((decMinutes - static_cast<double>(minutes_)) * 60.);
76 }
77
78 //============================================================================
85 RA(uint8 inHours, uint8 inMinutes, double inSeconds) noexcept :
86 hours_(inHours),
87 minutes_(inMinutes),
88 seconds_(inSeconds)
89 {
90 degrees_ = static_cast<double>(hours_) * 15. + static_cast<double>(minutes_) / 4. + seconds_ / 240.;
91 radians_ = deg2rad(degrees_);
92 }
93
94 //============================================================================
99 [[nodiscard]] double radians() const noexcept
100 {
101 return radians_;
102 }
103
104 //============================================================================
109 [[nodiscard]] double degrees() const noexcept
110 {
111 return degrees_;
112 }
113
114 //============================================================================
119 [[nodiscard]] uint8 hours() const noexcept
120 {
121 return hours_;
122 }
123
124 //============================================================================
129 [[nodiscard]] uint8 minutes() const noexcept
130 {
131 return minutes_;
132 }
133
134 //============================================================================
139 [[nodiscard]] double seconds() const noexcept
140 {
141 return seconds_;
142 }
143
144 //============================================================================
149 [[nodiscard]] std::string str() const
150 {
151 std::string out =
152 "RA hms: " + utils::num2str(hours_) + " hours, " + utils::num2str(minutes_) + " minutes, ";
153 out += utils::num2str(seconds_) + " seconds\nRA degrees: " + utils::num2str(degrees_) + '\n';
154 return out;
155 }
156
157 //============================================================================
160 void print() const
161 {
162 std::cout << *this;
163 }
164
165 //============================================================================
172 bool operator==(const RA& inRhs) const noexcept
173 {
174 return utils::essentiallyEqual(degrees_, inRhs.degrees_);
175 }
176
177 //============================================================================
184 bool operator!=(const RA& inRhs) const noexcept
185 {
186 return !(*this == inRhs);
187 }
188
189 //============================================================================
195 friend std::ostream& operator<<(std::ostream& inStream, const RA& inRa)
196 {
197 inStream << inRa.str();
198 return inStream;
199 }
200
201 private:
202 //====================================Attributes==============================
203 uint8 hours_{ 0 };
204 uint8 minutes_{ 0 };
205 double seconds_{ 0. };
206 double degrees_{ 0. };
207 double radians_{ 0. };
208 };
209
210 //================================================================================
212 class Dec
213 {
214 public:
215 //================================================================================
217 enum class Sign
218 {
219 NEGATIVE = 0,
220 POSITIVE
221 };
222
223 //============================================================================
226 Dec() = default;
227
228 //============================================================================
233 explicit Dec(double inDegrees) :
234 degrees_(inDegrees),
235 radians_(deg2rad(inDegrees))
236 {
237 if (inDegrees < -90 || inDegrees > 90)
238 {
239 THROW_INVALID_ARGUMENT_ERROR("input degrees must be of the range [-90, 90]");
240 }
241
242 sign_ = degrees_ < 0 ? Sign::NEGATIVE : Sign::POSITIVE;
243 const double absDegrees = std::abs(degrees_);
244 degreesWhole_ = static_cast<uint8>(std::floor(absDegrees));
245
246 const double decMinutes = (absDegrees - static_cast<double>(degreesWhole_)) * 60.;
247 minutes_ = static_cast<uint8>(std::floor(decMinutes));
248 seconds_ = (decMinutes - static_cast<double>(minutes_)) * 60.;
249 }
250
251 //============================================================================
259 Dec(Sign inSign, uint8 inDegrees, uint8 inMinutes, double inSeconds) noexcept :
260 sign_(inSign),
261 degreesWhole_(inDegrees),
262 minutes_(inMinutes),
263 seconds_(inSeconds)
264 {
265 degrees_ = static_cast<double>(degreesWhole_) + static_cast<double>(minutes_) / 60. + seconds_ / 3600.;
266 degrees_ *= sign_ == Sign::NEGATIVE ? -1 : 1;
267
268 radians_ = deg2rad(degrees_);
269 }
270
271 //============================================================================
276 [[nodiscard]] Sign sign() const noexcept
277 {
278 return sign_;
279 }
280
281 //============================================================================
286 [[nodiscard]] double degrees() const noexcept
287 {
288 return degrees_;
289 }
290
291 //============================================================================
296 [[nodiscard]] double radians() const noexcept
297 {
298 return radians_;
299 }
300
301 //============================================================================
306 [[nodiscard]] uint8 degreesWhole() const noexcept
307 {
308 return degreesWhole_;
309 }
310
311 //============================================================================
316 [[nodiscard]] uint8 minutes() const noexcept
317 {
318 return minutes_;
319 }
320
321 //============================================================================
326 [[nodiscard]] double seconds() const noexcept
327 {
328 return seconds_;
329 }
330
331 //============================================================================
336 [[nodiscard]] std::string str() const
337 {
338 std::string strSign = sign_ == Sign::NEGATIVE ? "-" : "+";
339 std::string out = "Dec dms: " + strSign + utils::num2str(degreesWhole_) + " degrees, " +
340 utils::num2str(minutes_) + " minutes, ";
341 out += utils::num2str(seconds_) + " seconds\nDec degrees = " + utils::num2str(degrees_) + '\n';
342 return out;
343 }
344
345 //============================================================================
348 void print() const
349 {
350 std::cout << *this;
351 }
352
353 //============================================================================
360 bool operator==(const Dec& inRhs) const noexcept
361 {
362 return utils::essentiallyEqual(degrees_, inRhs.degrees_);
363 }
364
365 //============================================================================
372 bool operator!=(const Dec& inRhs) const noexcept
373 {
374 return !(*this == inRhs);
375 }
376
377 //============================================================================
385 friend std::ostream& operator<<(std::ostream& inStream, const Dec& inDec)
386 {
387 inStream << inDec.str();
388 return inStream;
389 }
390
391 private:
392 //====================================Attributes==============================
393 Sign sign_{ Sign::POSITIVE };
394 uint8 degreesWhole_{ 0 };
395 uint8 minutes_{ 0 };
396 double seconds_{ 0. };
397 double degrees_{ 0. };
398 double radians_{ 0. };
399 };
400
401 //================================================================================
404 {
405 public:
406 //============================================================================
409 Celestial() = default;
410
411 //============================================================================
417 Celestial(double inRaDegrees, double inDecDegrees) :
418 ra_(inRaDegrees),
419 dec_(inDecDegrees)
420 {
421 polarToCartesian();
422 }
423
424 //============================================================================
435 Celestial(uint8 inRaHours,
436 uint8 inRaMinutes,
437 double inRaSeconds,
438 Dec::Sign inSign,
439 uint8 inDecDegreesWhole,
440 uint8 inDecMinutes,
441 double inDecSeconds) :
442 ra_(inRaHours, inRaMinutes, inRaSeconds),
443 dec_(inSign, inDecDegreesWhole, inDecMinutes, inDecSeconds)
444 {
445 polarToCartesian();
446 }
447
448 //============================================================================
454 Celestial(const RA& inRA, const Dec& inDec) noexcept :
455 ra_(inRA),
456 dec_(inDec)
457 {
458 polarToCartesian();
459 }
460
461 //============================================================================
468 Celestial(double inX, double inY, double inZ) :
469 x_(inX),
470 y_(inY),
471 z_(inZ)
472 {
473 cartesianToPolar();
474 }
475
476 //============================================================================
481 Celestial(const Cartesian& inCartesianVector) :
482 x_(inCartesianVector.x),
483 y_(inCartesianVector.y),
484 z_(inCartesianVector.z)
485 {
486 cartesianToPolar();
487 }
488
489 //============================================================================
494 Celestial(const Vec3& inCartesianVector) :
495 x_(inCartesianVector.x),
496 y_(inCartesianVector.y),
497 z_(inCartesianVector.z)
498 {
499 cartesianToPolar();
500 }
501
502 //============================================================================
507 Celestial(const NdArray<double>& inCartesianVector)
508 {
509 if (inCartesianVector.size() != 3)
510 {
511 THROW_INVALID_ARGUMENT_ERROR("NdArray input must be of length 3.");
512 }
513
514 x_ = inCartesianVector[0];
515 y_ = inCartesianVector[1];
516 z_ = inCartesianVector[2];
517
518 cartesianToPolar();
519 }
520
521 //============================================================================
526 [[nodiscard]] const Dec& dec() const noexcept
527 {
528 return dec_;
529 }
530
531 //============================================================================
536 [[nodiscard]] const RA& ra() const noexcept
537 {
538 return ra_;
539 }
540
541 //============================================================================
546 [[nodiscard]] double x() const noexcept
547 {
548 return x_;
549 }
550
551 //============================================================================
556 [[nodiscard]] double y() const noexcept
557 {
558 return y_;
559 }
560
561 //============================================================================
566 [[nodiscard]] double z() const noexcept
567 {
568 return z_;
569 }
570
571 //============================================================================
576 [[nodiscard]] NdArray<double> xyz() const
577 {
578 NdArray<double> out = { x_, y_, z_ };
579 return out;
580 }
581
582 //============================================================================
589 [[nodiscard]] double degreeSeperation(const Celestial& inOtherCelestial) const
590 {
591 return rad2deg(radianSeperation(inOtherCelestial));
592 }
593
594 //============================================================================
602 [[nodiscard]] double degreeSeperation(const NdArray<double>& inVector) const
603 {
604 return rad2deg(radianSeperation(inVector));
605 }
606
607 //============================================================================
614 [[nodiscard]] double radianSeperation(const Celestial& inOtherCelestial) const
615 {
616 return std::acos(dot(xyz(), inOtherCelestial.xyz()).item());
617 }
618
619 //============================================================================
627 [[nodiscard]] double radianSeperation(const NdArray<double>& inVector) const
628 {
629 if (inVector.size() != 3)
630 {
631 THROW_INVALID_ARGUMENT_ERROR("input vector must be of length 3.");
632 }
633
634 return std::acos(dot(xyz(), inVector.flatten()).item());
635 }
636
637 //============================================================================
642 [[nodiscard]] std::string str() const
643 {
644 std::string returnStr;
645 returnStr = ra_.str();
646 returnStr += dec_.str();
647 returnStr += "Cartesian = " + xyz().str();
648 return returnStr;
649 }
650
651 //============================================================================
654 void print() const
655 {
656 std::cout << *this;
657 }
658
659 //============================================================================
666 bool operator==(const Celestial& inRhs) const noexcept
667 {
668 return ra_ == inRhs.ra_ && dec_ == inRhs.dec_;
669 }
670
671 //============================================================================
678 bool operator!=(const Celestial& inRhs) const noexcept
679 {
680 return !(*this == inRhs);
681 }
682
683 //============================================================================
691 friend std::ostream& operator<<(std::ostream& inStream, const Celestial& inCoord)
692 {
693 inStream << inCoord.str();
694 return inStream;
695 }
696
697 private:
698 //====================================Attributes==============================
699 RA ra_{};
700 Dec dec_{};
701 double x_{ 1. };
702 double y_{ 0. };
703 double z_{ 0. };
704
705 //============================================================================
708 void cartesianToPolar()
709 {
710 double degreesRa = rad2deg(std::atan2(y_, x_));
711 if (degreesRa < 0)
712 {
713 degreesRa += 360;
714 }
715 ra_ = RA(degreesRa);
716
717 const double r = std::sqrt(utils::sqr(x_) + utils::sqr(y_) + utils::sqr(z_));
718 const double degreesDec = rad2deg(std::asin(z_ / r));
719 dec_ = Dec(degreesDec);
720 }
721
722 //============================================================================
725 void polarToCartesian() noexcept
726 {
727 const double raRadians = deg2rad(ra_.degrees());
728 const double decRadians = deg2rad(dec_.degrees());
729
730 x_ = std::cos(raRadians) * std::cos(decRadians);
731 y_ = std::sin(raRadians) * std::cos(decRadians);
732 z_ = std::sin(decRadians);
733 }
734 };
735} // namespace nc::coordinates::reference_frames
#define THROW_INVALID_ARGUMENT_ERROR(msg)
Definition: Error.hpp:37
size_type size() const noexcept
Definition: NdArrayCore.hpp:4524
self_type flatten() const
Definition: NdArrayCore.hpp:2847
std::string str() const
Definition: NdArrayCore.hpp:4582
Holds a 3D vector.
Definition: Vec3.hpp:51
Cartensian coordinates.
Definition: Cartesian.hpp:45
Holds a full celestial Celestial object.
Definition: Celestial.hpp:404
Celestial(uint8 inRaHours, uint8 inRaMinutes, double inRaSeconds, Dec::Sign inSign, uint8 inDecDegreesWhole, uint8 inDecMinutes, double inDecSeconds)
Definition: Celestial.hpp:435
Celestial(double inX, double inY, double inZ)
Definition: Celestial.hpp:468
friend std::ostream & operator<<(std::ostream &inStream, const Celestial &inCoord)
Definition: Celestial.hpp:691
double y() const noexcept
Definition: Celestial.hpp:556
const RA & ra() const noexcept
Definition: Celestial.hpp:536
Celestial(const Cartesian &inCartesianVector)
Definition: Celestial.hpp:481
double z() const noexcept
Definition: Celestial.hpp:566
bool operator==(const Celestial &inRhs) const noexcept
Definition: Celestial.hpp:666
Celestial(const RA &inRA, const Dec &inDec) noexcept
Definition: Celestial.hpp:454
Celestial(const NdArray< double > &inCartesianVector)
Definition: Celestial.hpp:507
double degreeSeperation(const NdArray< double > &inVector) const
Definition: Celestial.hpp:602
double radianSeperation(const Celestial &inOtherCelestial) const
Definition: Celestial.hpp:614
Celestial(double inRaDegrees, double inDecDegrees)
Definition: Celestial.hpp:417
std::string str() const
Definition: Celestial.hpp:642
NdArray< double > xyz() const
Definition: Celestial.hpp:576
const Dec & dec() const noexcept
Definition: Celestial.hpp:526
bool operator!=(const Celestial &inRhs) const noexcept
Definition: Celestial.hpp:678
double degreeSeperation(const Celestial &inOtherCelestial) const
Definition: Celestial.hpp:589
Celestial(const Vec3 &inCartesianVector)
Definition: Celestial.hpp:494
double x() const noexcept
Definition: Celestial.hpp:546
double radianSeperation(const NdArray< double > &inVector) const
Definition: Celestial.hpp:627
void print() const
Definition: Celestial.hpp:654
Holds a Declination object.
Definition: Celestial.hpp:213
double degrees() const noexcept
Definition: Celestial.hpp:286
Sign sign() const noexcept
Definition: Celestial.hpp:276
friend std::ostream & operator<<(std::ostream &inStream, const Dec &inDec)
Definition: Celestial.hpp:385
double radians() const noexcept
Definition: Celestial.hpp:296
uint8 minutes() const noexcept
Definition: Celestial.hpp:316
void print() const
Definition: Celestial.hpp:348
Dec(Sign inSign, uint8 inDegrees, uint8 inMinutes, double inSeconds) noexcept
Definition: Celestial.hpp:259
uint8 degreesWhole() const noexcept
Definition: Celestial.hpp:306
std::string str() const
Definition: Celestial.hpp:336
bool operator==(const Dec &inRhs) const noexcept
Definition: Celestial.hpp:360
double seconds() const noexcept
Definition: Celestial.hpp:326
Dec(double inDegrees)
Definition: Celestial.hpp:233
bool operator!=(const Dec &inRhs) const noexcept
Definition: Celestial.hpp:372
Sign
Struct Enum for positive or negative Dec angle.
Definition: Celestial.hpp:218
Holds a right ascension object.
Definition: Celestial.hpp:51
uint8 minutes() const noexcept
Definition: Celestial.hpp:129
double radians() const noexcept
Definition: Celestial.hpp:99
double seconds() const noexcept
Definition: Celestial.hpp:139
void print() const
Definition: Celestial.hpp:160
double degrees() const noexcept
Definition: Celestial.hpp:109
friend std::ostream & operator<<(std::ostream &inStream, const RA &inRa)
Definition: Celestial.hpp:195
uint8 hours() const noexcept
Definition: Celestial.hpp:119
RA(double inDegrees)
Definition: Celestial.hpp:63
bool operator==(const RA &inRhs) const noexcept
Definition: Celestial.hpp:172
std::string str() const
Definition: Celestial.hpp:149
RA(uint8 inHours, uint8 inMinutes, double inSeconds) noexcept
Definition: Celestial.hpp:85
bool operator!=(const RA &inRhs) const noexcept
Definition: Celestial.hpp:184
Definition: AER.hpp:36
std::string num2str(dtype inNumber)
Definition: num2str.hpp:44
bool essentiallyEqual(dtype inValue1, dtype inValue2) noexcept
Definition: essentiallyEqual.hpp:49
constexpr dtype sqr(dtype inValue) noexcept
Definition: sqr.hpp:42
constexpr auto deg2rad(dtype inValue) noexcept
Definition: deg2rad.hpp:47
auto sin(dtype inValue) noexcept
Definition: sin.hpp:49
NdArray< dtype > dot(const NdArray< dtype > &inArray1, const NdArray< dtype > &inArray2)
Definition: dot.hpp:47
auto abs(dtype inValue) noexcept
Definition: abs.hpp:49
auto cos(dtype inValue) noexcept
Definition: cos.hpp:49
dtype floor(dtype inValue) noexcept
Definition: floor.hpp:48
constexpr auto rad2deg(dtype inValue) noexcept
Definition: rad2deg.hpp:48
auto sqrt(dtype inValue) noexcept
Definition: sqrt.hpp:48
std::uint8_t uint8
Definition: Types.hpp:42