NumCpp  2.12.0
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)
86 noexcept :
87 hours_(inHours),
88 minutes_(inMinutes),
89 seconds_(inSeconds)
90 {
91 degrees_ = static_cast<double>(hours_) * 15. + static_cast<double>(minutes_) / 4. + seconds_ / 240.;
92 radians_ = deg2rad(degrees_);
93 }
94
95 //============================================================================
100 [[nodiscard]] double radians() const noexcept
101 {
102 return radians_;
103 }
104
105 //============================================================================
110 [[nodiscard]] double degrees() const noexcept
111 {
112 return degrees_;
113 }
114
115 //============================================================================
120 [[nodiscard]] uint8 hours() const noexcept
121 {
122 return hours_;
123 }
124
125 //============================================================================
130 [[nodiscard]] uint8 minutes() const noexcept
131 {
132 return minutes_;
133 }
134
135 //============================================================================
140 [[nodiscard]] double seconds() const noexcept
141 {
142 return seconds_;
143 }
144
145 //============================================================================
150 [[nodiscard]] std::string str() const
151 {
152 std::string out =
153 "RA hms: " + utils::num2str(hours_) + " hours, " + utils::num2str(minutes_) + " minutes, ";
154 out += utils::num2str(seconds_) + " seconds\nRA degrees: " + utils::num2str(degrees_) + '\n';
155 return out;
156 }
157
158 //============================================================================
161 void print() const
162 {
163 std::cout << *this;
164 }
165
166 //============================================================================
173 bool operator==(const RA& inRhs) const noexcept
174 {
175 return utils::essentiallyEqual(degrees_, inRhs.degrees_);
176 }
177
178 //============================================================================
185 bool operator!=(const RA& inRhs) const noexcept
186 {
187 return !(*this == inRhs);
188 }
189
190 //============================================================================
196 friend std::ostream& operator<<(std::ostream& inStream, const RA& inRa)
197 {
198 inStream << inRa.str();
199 return inStream;
200 }
201
202 private:
203 //====================================Attributes==============================
204 uint8 hours_{ 0 };
205 uint8 minutes_{ 0 };
206 double seconds_{ 0. };
207 double degrees_{ 0. };
208 double radians_{ 0. };
209 };
210
211 //================================================================================
213 class Dec
214 {
215 public:
216 //================================================================================
218 enum class Sign
219 {
220 NEGATIVE = 0,
221 POSITIVE
222 };
223
224 //============================================================================
227 Dec() = default;
228
229 //============================================================================
234 explicit Dec(double inDegrees) :
235 degrees_(inDegrees),
236 radians_(deg2rad(inDegrees))
237 {
238 if (inDegrees < -90 || inDegrees > 90)
239 {
240 THROW_INVALID_ARGUMENT_ERROR("input degrees must be of the range [-90, 90]");
241 }
242
243 sign_ = degrees_ < 0 ? Sign::NEGATIVE : Sign::POSITIVE;
244 const double absDegrees = std::abs(degrees_);
245 degreesWhole_ = static_cast<uint8>(std::floor(absDegrees));
246
247 const double decMinutes = (absDegrees - static_cast<double>(degreesWhole_)) * 60.;
248 minutes_ = static_cast<uint8>(std::floor(decMinutes));
249 seconds_ = (decMinutes - static_cast<double>(minutes_)) * 60.;
250 }
251
252 //============================================================================
260 Dec(Sign inSign, uint8 inDegrees, uint8 inMinutes, double inSeconds) noexcept :
261 sign_(inSign),
262 degreesWhole_(inDegrees),
263 minutes_(inMinutes),
264 seconds_(inSeconds)
265 {
266 degrees_ = static_cast<double>(degreesWhole_) + static_cast<double>(minutes_) / 60. + seconds_ / 3600.;
267 degrees_ *= sign_ == Sign::NEGATIVE ? -1 : 1;
268
269 radians_ = deg2rad(degrees_);
270 }
271
272 //============================================================================
277 [[nodiscard]] Sign sign() const noexcept
278 {
279 return sign_;
280 }
281
282 //============================================================================
287 [[nodiscard]] double degrees() const noexcept
288 {
289 return degrees_;
290 }
291
292 //============================================================================
297 [[nodiscard]] double radians() const noexcept
298 {
299 return radians_;
300 }
301
302 //============================================================================
307 [[nodiscard]] uint8 degreesWhole() const noexcept
308 {
309 return degreesWhole_;
310 }
311
312 //============================================================================
317 [[nodiscard]] uint8 minutes() const noexcept
318 {
319 return minutes_;
320 }
321
322 //============================================================================
327 [[nodiscard]] double seconds() const noexcept
328 {
329 return seconds_;
330 }
331
332 //============================================================================
337 [[nodiscard]] std::string str() const
338 {
339 std::string strSign = sign_ == Sign::NEGATIVE ? "-" : "+";
340 std::string out = "Dec dms: " + strSign + utils::num2str(degreesWhole_) + " degrees, " +
341 utils::num2str(minutes_) + " minutes, ";
342 out += utils::num2str(seconds_) + " seconds\nDec degrees = " + utils::num2str(degrees_) + '\n';
343 return out;
344 }
345
346 //============================================================================
349 void print() const
350 {
351 std::cout << *this;
352 }
353
354 //============================================================================
361 bool operator==(const Dec& inRhs) const noexcept
362 {
363 return utils::essentiallyEqual(degrees_, inRhs.degrees_);
364 }
365
366 //============================================================================
373 bool operator!=(const Dec& inRhs) const noexcept
374 {
375 return !(*this == inRhs);
376 }
377
378 //============================================================================
386 friend std::ostream& operator<<(std::ostream& inStream, const Dec& inDec)
387 {
388 inStream << inDec.str();
389 return inStream;
390 }
391
392 private:
393 //====================================Attributes==============================
394 Sign sign_{ Sign::POSITIVE };
395 uint8 degreesWhole_{ 0 };
396 uint8 minutes_{ 0 };
397 double seconds_{ 0. };
398 double degrees_{ 0. };
399 double radians_{ 0. };
400 };
401
402 //================================================================================
405 {
406 public:
407 //============================================================================
410 Celestial() = default;
411
412 //============================================================================
418 Celestial(double inRaDegrees, double inDecDegrees) :
419 ra_(inRaDegrees),
420 dec_(inDecDegrees)
421 {
422 polarToCartesian();
423 }
424
425 //============================================================================
436 Celestial(uint8 inRaHours,
437 uint8 inRaMinutes,
438 double inRaSeconds,
439 Dec::Sign inSign,
440 uint8 inDecDegreesWhole,
441 uint8 inDecMinutes,
442 double inDecSeconds) :
443 ra_(inRaHours, inRaMinutes, inRaSeconds),
444 dec_(inSign, inDecDegreesWhole, inDecMinutes, inDecSeconds)
445 {
446 polarToCartesian();
447 }
448
449 //============================================================================
455 Celestial(const RA& inRA, const Dec& inDec) noexcept :
456 ra_(inRA),
457 dec_(inDec)
458 {
459 polarToCartesian();
460 }
461
462 //============================================================================
469 Celestial(double inX, double inY, double inZ) :
470 x_(inX),
471 y_(inY),
472 z_(inZ)
473 {
474 cartesianToPolar();
475 }
476
477 //============================================================================
482 Celestial(const Cartesian& inCartesianVector) :
483 x_(inCartesianVector.x),
484 y_(inCartesianVector.y),
485 z_(inCartesianVector.z)
486 {
487 cartesianToPolar();
488 }
489
490 //============================================================================
495 Celestial(const Vec3& inCartesianVector) :
496 x_(inCartesianVector.x),
497 y_(inCartesianVector.y),
498 z_(inCartesianVector.z)
499 {
500 cartesianToPolar();
501 }
502
503 //============================================================================
508 Celestial(const NdArray<double>& inCartesianVector)
509 {
510 if (inCartesianVector.size() != 3)
511 {
512 THROW_INVALID_ARGUMENT_ERROR("NdArray input must be of length 3.");
513 }
514
515 x_ = inCartesianVector[0];
516 y_ = inCartesianVector[1];
517 z_ = inCartesianVector[2];
518
519 cartesianToPolar();
520 }
521
522 //============================================================================
527 [[nodiscard]] const Dec& dec() const noexcept
528 {
529 return dec_;
530 }
531
532 //============================================================================
537 [[nodiscard]] const RA& ra() const noexcept
538 {
539 return ra_;
540 }
541
542 //============================================================================
547 [[nodiscard]] double x() const noexcept
548 {
549 return x_;
550 }
551
552 //============================================================================
557 [[nodiscard]] double y() const noexcept
558 {
559 return y_;
560 }
561
562 //============================================================================
567 [[nodiscard]] double z() const noexcept
568 {
569 return z_;
570 }
571
572 //============================================================================
577 [[nodiscard]] NdArray<double> xyz() const
578 {
579 NdArray<double> out = { x_, y_, z_ };
580 return out;
581 }
582
583 //============================================================================
590 [[nodiscard]] double degreeSeperation(const Celestial& inOtherCelestial) const
591 {
592 return rad2deg(radianSeperation(inOtherCelestial));
593 }
594
595 //============================================================================
603 [[nodiscard]] double degreeSeperation(const NdArray<double>& inVector) const
604 {
605 return rad2deg(radianSeperation(inVector));
606 }
607
608 //============================================================================
615 [[nodiscard]] double radianSeperation(const Celestial& inOtherCelestial) const
616 {
617 return std::acos(dot(xyz(), inOtherCelestial.xyz()).item());
618 }
619
620 //============================================================================
628 [[nodiscard]] double radianSeperation(const NdArray<double>& inVector) const
629 {
630 if (inVector.size() != 3)
631 {
632 THROW_INVALID_ARGUMENT_ERROR("input vector must be of length 3.");
633 }
634
635 return std::acos(dot(xyz(), inVector.flatten()).item());
636 }
637
638 //============================================================================
643 [[nodiscard]] std::string str() const
644 {
645 std::string returnStr;
646 returnStr = ra_.str();
647 returnStr += dec_.str();
648 returnStr += "Cartesian = " + xyz().str();
649 return returnStr;
650 }
651
652 //============================================================================
655 void print() const
656 {
657 std::cout << *this;
658 }
659
660 //============================================================================
667 bool operator==(const Celestial& inRhs) const noexcept
668 {
669 return ra_ == inRhs.ra_ && dec_ == inRhs.dec_;
670 }
671
672 //============================================================================
679 bool operator!=(const Celestial& inRhs) const noexcept
680 {
681 return !(*this == inRhs);
682 }
683
684 //============================================================================
692 friend std::ostream& operator<<(std::ostream& inStream, const Celestial& inCoord)
693 {
694 inStream << inCoord.str();
695 return inStream;
696 }
697
698 private:
699 //====================================Attributes==============================
700 RA ra_{};
701 Dec dec_{};
702 double x_{ 1. };
703 double y_{ 0. };
704 double z_{ 0. };
705
706 //============================================================================
709 void cartesianToPolar()
710 {
711 double degreesRa = rad2deg(std::atan2(y_, x_));
712 if (degreesRa < 0)
713 {
714 degreesRa += 360;
715 }
716 ra_ = RA(degreesRa);
717
718 const double r = std::sqrt(utils::sqr(x_) + utils::sqr(y_) + utils::sqr(z_));
719 const double degreesDec = rad2deg(std::asin(z_ / r));
720 dec_ = Dec(degreesDec);
721 }
722
723 //============================================================================
726 void polarToCartesian() noexcept
727 {
728 const double raRadians = deg2rad(ra_.degrees());
729 const double decRadians = deg2rad(dec_.degrees());
730
731 x_ = std::cos(raRadians) * std::cos(decRadians);
732 y_ = std::sin(raRadians) * std::cos(decRadians);
733 z_ = std::sin(decRadians);
734 }
735 };
736} // 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:405
Celestial(uint8 inRaHours, uint8 inRaMinutes, double inRaSeconds, Dec::Sign inSign, uint8 inDecDegreesWhole, uint8 inDecMinutes, double inDecSeconds)
Definition: Celestial.hpp:436
Celestial(double inX, double inY, double inZ)
Definition: Celestial.hpp:469
friend std::ostream & operator<<(std::ostream &inStream, const Celestial &inCoord)
Definition: Celestial.hpp:692
double y() const noexcept
Definition: Celestial.hpp:557
const RA & ra() const noexcept
Definition: Celestial.hpp:537
Celestial(const Cartesian &inCartesianVector)
Definition: Celestial.hpp:482
double z() const noexcept
Definition: Celestial.hpp:567
bool operator==(const Celestial &inRhs) const noexcept
Definition: Celestial.hpp:667
Celestial(const RA &inRA, const Dec &inDec) noexcept
Definition: Celestial.hpp:455
Celestial(const NdArray< double > &inCartesianVector)
Definition: Celestial.hpp:508
double degreeSeperation(const NdArray< double > &inVector) const
Definition: Celestial.hpp:603
double radianSeperation(const Celestial &inOtherCelestial) const
Definition: Celestial.hpp:615
Celestial(double inRaDegrees, double inDecDegrees)
Definition: Celestial.hpp:418
std::string str() const
Definition: Celestial.hpp:643
NdArray< double > xyz() const
Definition: Celestial.hpp:577
const Dec & dec() const noexcept
Definition: Celestial.hpp:527
bool operator!=(const Celestial &inRhs) const noexcept
Definition: Celestial.hpp:679
double degreeSeperation(const Celestial &inOtherCelestial) const
Definition: Celestial.hpp:590
Celestial(const Vec3 &inCartesianVector)
Definition: Celestial.hpp:495
double x() const noexcept
Definition: Celestial.hpp:547
double radianSeperation(const NdArray< double > &inVector) const
Definition: Celestial.hpp:628
void print() const
Definition: Celestial.hpp:655
Holds a Declination object.
Definition: Celestial.hpp:214
double degrees() const noexcept
Definition: Celestial.hpp:287
Sign sign() const noexcept
Definition: Celestial.hpp:277
friend std::ostream & operator<<(std::ostream &inStream, const Dec &inDec)
Definition: Celestial.hpp:386
double radians() const noexcept
Definition: Celestial.hpp:297
uint8 minutes() const noexcept
Definition: Celestial.hpp:317
void print() const
Definition: Celestial.hpp:349
Dec(Sign inSign, uint8 inDegrees, uint8 inMinutes, double inSeconds) noexcept
Definition: Celestial.hpp:260
uint8 degreesWhole() const noexcept
Definition: Celestial.hpp:307
std::string str() const
Definition: Celestial.hpp:337
bool operator==(const Dec &inRhs) const noexcept
Definition: Celestial.hpp:361
double seconds() const noexcept
Definition: Celestial.hpp:327
Dec(double inDegrees)
Definition: Celestial.hpp:234
bool operator!=(const Dec &inRhs) const noexcept
Definition: Celestial.hpp:373
Sign
Struct Enum for positive or negative Dec angle.
Definition: Celestial.hpp:219
Holds a right ascension object.
Definition: Celestial.hpp:51
uint8 minutes() const noexcept
Definition: Celestial.hpp:130
double radians() const noexcept
Definition: Celestial.hpp:100
double seconds() const noexcept
Definition: Celestial.hpp:140
void print() const
Definition: Celestial.hpp:161
double degrees() const noexcept
Definition: Celestial.hpp:110
friend std::ostream & operator<<(std::ostream &inStream, const RA &inRa)
Definition: Celestial.hpp:196
uint8 hours() const noexcept
Definition: Celestial.hpp:120
RA(double inDegrees)
Definition: Celestial.hpp:63
bool operator==(const RA &inRhs) const noexcept
Definition: Celestial.hpp:173
std::string str() const
Definition: Celestial.hpp:150
bool operator!=(const RA &inRhs) const noexcept
Definition: Celestial.hpp:185
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