1.3.49
 
Loading...
Searching...
No Matches
helios_vector_types.h
Go to the documentation of this file.
1
16#ifndef HELIOS_VECTOR_TYPES
17#define HELIOS_VECTOR_TYPES
18
19#ifndef M_PI
20#define M_PI 3.14159265358979323846
21#endif
22
23typedef unsigned int uint;
24
25#include <cassert>
26#include <string>
27#include <vector>
28// #include <stdexcept>
29#include <cmath>
30#include <iomanip>
31#include <limits>
32
34
38namespace helios {
39
41
44 struct int2 {
45
47 int x;
49 int y;
50
52 /* initializes to zero */
53 constexpr int2() : x(0), y(0) {
54 }
55
57 explicit int2(const std::vector<int> &v) {
58 if (v.size() != 2) {
59 throw(std::runtime_error("ERROR: vector for initialization of int2 must have length 2."));
60 }
61 x = v[0];
62 y = v[1];
63 }
65 constexpr explicit int2(const int v[2]) : x(v[0]), y(v[1]) {
66 }
67
69 constexpr int2(int v0, int v1) : x(v0), y(v1) {
70 }
71
72
74 constexpr int2 operator+(const int2 &a) const noexcept;
76 inline int2 &operator+=(const int2 &a) noexcept;
78 inline int2 &operator-=(const int2 &a) noexcept;
80 constexpr int2 operator-(const int2 &a) const noexcept;
82 constexpr bool operator==(const int2 &a) const noexcept;
84 constexpr bool operator!=(const int2 &a) const noexcept;
86 constexpr int2 operator-() const noexcept;
87
89 friend std::ostream &operator<<(std::ostream &os, const helios::int2 &vec) {
90 return os << "helios::int2<" << vec.x << ", " << vec.y << ">";
91 }
92 };
93
95
100 constexpr int2 make_int2(int x, int y) {
101 return {x, y};
102 }
103
105
109 inline int2 make_int2(int X[2]) {
110 return {X[0], X[1]};
111 }
112
113 constexpr int2 int2::operator+(const int2 &a) const noexcept {
114 return {a.x + x, a.y + y};
115 }
116
117 inline int2 &int2::operator+=(const int2 &a) noexcept {
118 this->x += a.x;
119 this->y += a.y;
120 return *this;
121 }
122
123 inline int2 &int2::operator-=(const int2 &a) noexcept {
124 this->x -= a.x;
125 this->y -= a.y;
126 return *this;
127 }
128
129 constexpr int2 int2::operator-(const int2 &a) const noexcept {
130 return {x - a.x, y - a.y};
131 }
132
133 constexpr bool int2::operator==(const int2 &a) const noexcept {
134 return a.x == x && a.y == y;
135 }
136
137 constexpr bool int2::operator!=(const int2 &a) const noexcept {
138 return a.x != x || a.y != y;
139 }
140
141 constexpr int2 int2::operator-() const noexcept {
142 return {-x, -y};
143 }
144
146
147 struct int3 {
148
150 int x;
152 int y;
154 int z;
155
157 /* initializes to zero */
158 constexpr int3() : x(0), y(0), z(0) {
159 }
160
162 explicit int3(const std::vector<int> &v) {
163 if (v.size() != 3) {
164 throw(std::runtime_error("ERROR: vector for initialization of int3 must have length 3."));
165 }
166 x = v[0];
167 y = v[1];
168 z = v[2];
169 }
171 constexpr explicit int3(const int v[3]) : x(v[0]), y(v[1]), z(v[2]) {
172 }
173
175 constexpr int3(int v0, int v1, int v2) : x(v0), y(v1), z(v2) {
176 }
177
179 constexpr int3 operator+(const int3 &a) const noexcept;
181 inline int3 &operator+=(const int3 &a) noexcept;
183 inline int3 &operator-=(const int3 &a) noexcept;
185 constexpr int3 operator-(const int3 &a) const noexcept;
187 constexpr bool operator==(const int3 &a) const noexcept;
189 constexpr bool operator!=(const int3 &a) const noexcept;
191 constexpr int3 operator-() const noexcept;
192
194 friend std::ostream &operator<<(std::ostream &os, const helios::int3 &vec) {
195 return os << "helios::int3<" << vec.x << ", " << vec.y << ", " << vec.z << ">";
196 }
197 };
198
200 constexpr int3 make_int3(int X, int Y, int Z) {
201 return {X, Y, Z};
202 }
203
205 constexpr int3 make_int3(int X[3]) {
206 return {X[0], X[1], X[2]};
207 }
208
209 constexpr int3 int3::operator+(const int3 &a) const noexcept {
210 return {a.x + x, a.y + y, a.z + z};
211 }
212
213 inline int3 &int3::operator+=(const int3 &a) noexcept {
214 this->x += a.x;
215 this->y += a.y;
216 this->z += a.z;
217 return *this;
218 }
219
220 inline int3 &int3::operator-=(const int3 &a) noexcept {
221 this->x -= a.x;
222 this->y -= a.y;
223 this->z -= a.z;
224 return *this;
225 }
226
227 constexpr int3 int3::operator-(const int3 &a) const noexcept {
228 return {x - a.x, y - a.y, z - a.z};
229 }
230
231 constexpr bool int3::operator==(const int3 &a) const noexcept {
232 return a.x == x && a.y == y && a.z == z;
233 }
234
235 constexpr bool int3::operator!=(const int3 &a) const noexcept {
236 return a.x != x || a.y != y || a.z != z;
237 }
238
239 constexpr int3 int3::operator-() const noexcept {
240 return {-x, -y, -z};
241 }
242
244
245 struct int4 {
246
247
249 int x;
251 int y;
253 int z;
255 int w;
256
258 /* initializes to zero */
259 constexpr int4() : x(0), y(0), z(0), w(0) {
260 }
261
263 explicit int4(const std::vector<int> &v) {
264 if (v.size() != 4) {
265 throw(std::runtime_error("ERROR: vector for initialization of int4 must have length 4."));
266 }
267 x = v[0];
268 y = v[1];
269 z = v[2];
270 w = v[3];
271 }
272
274 explicit constexpr int4(const int v[4]) : x(v[0]), y(v[1]), z(v[2]), w(v[3]) {
275 }
276
278 constexpr int4(int v0, int v1, int v2, int v3) : x(v0), y(v1), z(v2), w(v3) {
279 }
280
282 constexpr int4 operator+(const int4 &a) const noexcept;
284 inline int4 &operator+=(const int4 &a) noexcept;
286 inline int4 &operator-=(const int4 &a) noexcept;
288 constexpr int4 operator-(const int4 &a) const noexcept;
290 constexpr bool operator==(const int4 &a) const noexcept;
292 constexpr bool operator!=(const int4 &a) const noexcept;
294 constexpr int4 operator-() const noexcept;
295
297 friend std::ostream &operator<<(std::ostream &os, const helios::int4 &vec) {
298 return os << "helios::int4<" << vec.x << ", " << vec.y << ", " << vec.z << ", " << vec.w << ">";
299 }
300 };
301
303 constexpr int4 make_int4(int x, int y, int z, int w) {
304 return {x, y, z, w};
305 }
306
308 constexpr int4 make_int4(const int X[4]) {
309 return {X[0], X[1], X[2], X[3]};
310 }
311
312 constexpr int4 int4::operator+(const int4 &a) const noexcept {
313 return {a.x + x, a.y + y, a.z + z, a.w + w};
314 }
315
316 inline int4 &int4::operator+=(const int4 &a) noexcept {
317 this->x += a.x;
318 this->y += a.y;
319 this->z += a.z;
320 this->w += a.w;
321 return *this;
322 }
323
324 inline int4 &int4::operator-=(const int4 &a) noexcept {
325 this->x -= a.x;
326 this->y -= a.y;
327 this->z -= a.z;
328 this->w -= a.w;
329 return *this;
330 }
331
332 constexpr int4 int4::operator-(const int4 &a) const noexcept {
333 return {x - a.x, y - a.y, z - a.z, w - a.w};
334 }
335
336 constexpr bool int4::operator==(const int4 &a) const noexcept {
337 return a.x == x && a.y == y && a.z == z && a.w == w;
338 }
339
340 constexpr bool int4::operator!=(const int4 &a) const noexcept {
341 return a.x != x || a.y != y || a.z != z || a.w != w;
342 }
343
344 constexpr int4 int4::operator-() const noexcept {
345 return {-x, -y, -z, -w};
346 }
347
349
352 struct uint2 {
353
354
356 unsigned int x;
358 unsigned int y;
359
361 /* initializes to zero */
362 constexpr uint2() : x(0u), y(0u) {
363 }
364
366 explicit uint2(const std::vector<unsigned int> &v) {
367 if (v.size() != 2) {
368 throw(std::runtime_error("ERROR: vector for initialization of uint2 must have length 2."));
369 }
370 x = v[0];
371 y = v[1];
372 }
374 constexpr explicit uint2(const unsigned int v[2]) : x(v[0]), y(v[1]) {
375 }
376
378 constexpr uint2(unsigned int v0, unsigned int v1) : x(v0), y(v1) {
379 }
380
381
383 constexpr uint2 operator+(const uint2 &a) const noexcept;
385 inline uint2 &operator+=(const uint2 &a) noexcept;
387 inline uint2 &operator-=(const uint2 &a) noexcept;
389 constexpr uint2 operator-(const uint2 &a) const noexcept;
391 constexpr bool operator==(const uint2 &a) const noexcept;
393 constexpr bool operator!=(const uint2 &a) const noexcept;
395 constexpr uint2 operator-() const noexcept;
396
398 friend std::ostream &operator<<(std::ostream &os, const helios::uint2 &vec) {
399 return os << "helios::uint2<" << vec.x << ", " << vec.y << ">";
400 }
401 };
402
404
409 constexpr uint2 make_uint2(unsigned int x, unsigned int y) {
410 return {x, y};
411 }
412
414
418 constexpr uint2 make_uint2(unsigned int X[2]) {
419 return {X[0], X[1]};
420 }
421
422 constexpr uint2 uint2::operator+(const uint2 &a) const noexcept {
423 return {a.x + x, a.y + y};
424 }
425
426 inline uint2 &uint2::operator+=(const uint2 &a) noexcept {
427 this->x += a.x;
428 this->y += a.y;
429 return *this;
430 }
431
432 inline uint2 &uint2::operator-=(const uint2 &a) noexcept {
433 this->x -= a.x;
434 this->y -= a.y;
435 return *this;
436 }
437
438 constexpr uint2 uint2::operator-(const uint2 &a) const noexcept {
439 return {x - a.x, y - a.y};
440 }
441
442 constexpr bool uint2::operator==(const uint2 &a) const noexcept {
443 return a.x == x && a.y == y;
444 }
445
446 constexpr bool uint2::operator!=(const uint2 &a) const noexcept {
447 return a.x != x || a.y != y;
448 }
449
450 constexpr uint2 uint2::operator-() const noexcept {
451 return {-x, -y};
452 }
453
454
456
459 struct uint3 {
460
461
463 unsigned int x;
465 unsigned int y;
467 unsigned int z;
468
470
473 constexpr uint3() : x(0u), y(0u), z(0u) {
474 }
475
477 explicit uint3(const std::vector<unsigned int> &v) {
478 if (v.size() != 3) {
479 throw(std::runtime_error("ERROR: vector for initialization of uint3 must have length 3."));
480 }
481 x = v[0];
482 y = v[1];
483 z = v[2];
484 }
486 constexpr explicit uint3(const unsigned int v[3]) : x(v[0]), y(v[1]), z(v[2]) {
487 }
488
490 constexpr uint3(unsigned int v0, unsigned int v1, unsigned int v2) : x(v0), y(v1), z(v2) {
491 }
492
494 constexpr uint3 operator+(const uint3 &a) const noexcept;
496 inline uint3 &operator+=(const uint3 &a) noexcept;
498 inline uint3 &operator-=(const uint3 &a) noexcept;
500 constexpr uint3 operator-(const uint3 &a) const noexcept;
502 constexpr bool operator==(const uint3 &a) const noexcept;
504 constexpr bool operator!=(const uint3 &a) const noexcept;
506 constexpr uint3 operator-() const noexcept;
507
509 friend std::ostream &operator<<(std::ostream &os, const helios::uint3 &vec) {
510 return os << "helios::uint3<" << vec.x << ", " << vec.y << ", " << vec.z << ">";
511 }
512 };
513
515
521 constexpr uint3 make_uint3(unsigned int X, unsigned int Y, unsigned int Z) {
522 return {X, Y, Z};
523 }
524
526
530 constexpr uint3 make_uint3(unsigned int X[3]) {
531 return {X[0], X[1], X[2]};
532 }
533
534 constexpr uint3 uint3::operator+(const uint3 &a) const noexcept {
535 return {a.x + x, a.y + y, a.z + z};
536 }
537
538 inline uint3 &uint3::operator+=(const uint3 &a) noexcept {
539 this->x += a.x;
540 this->y += a.y;
541 this->z += a.z;
542 return *this;
543 }
544
545 inline uint3 &uint3::operator-=(const uint3 &a) noexcept {
546 this->x -= a.x;
547 this->y -= a.y;
548 this->z -= a.z;
549 return *this;
550 }
551
552 constexpr uint3 uint3::operator-(const uint3 &a) const noexcept {
553 return {x - a.x, y - a.y, z - a.z};
554 }
555
556 constexpr bool uint3::operator==(const uint3 &a) const noexcept {
557 return a.x == x && a.y == y && a.z == z;
558 }
559
560 constexpr bool uint3::operator!=(const uint3 &a) const noexcept {
561 return a.x != x || a.y != y || a.z != z;
562 }
563
564 constexpr uint3 uint3::operator-() const noexcept {
565 return {-x, -y, -z};
566 }
567
568
570
573 struct uint4 {
574
576 unsigned int x;
578 unsigned int y;
580 unsigned int z;
582 unsigned int w;
583
585
588 constexpr uint4() : x(0u), y(0u), z(0u), w(0u) {
589 }
590
592 explicit uint4(const std::vector<unsigned int> &v) {
593 if (v.size() != 4) {
594 throw(std::runtime_error("ERROR: vector for initialization of uint4 must have length 4."));
595 }
596 x = v[0];
597 y = v[1];
598 z = v[2];
599 w = v[3];
600 }
601
603 constexpr explicit uint4(const unsigned int v[4]) : x(v[0]), y(v[1]), z(v[2]), w(v[3]) {
604 }
605
607 constexpr uint4(unsigned int v0, unsigned int v1, unsigned int v2, unsigned int v3) : x(v0), y(v1), z(v2), w(v3) {
608 }
609
611 constexpr uint4 operator+(const uint4 &a) const noexcept;
613 inline uint4 &operator+=(const uint4 &a) noexcept;
615 inline uint4 &operator-=(const uint4 &a) noexcept;
617 constexpr uint4 operator-(const uint4 &a) const noexcept;
619 constexpr bool operator==(const uint4 &a) const noexcept;
621 constexpr bool operator!=(const uint4 &a) const noexcept;
623 constexpr uint4 operator-() const noexcept;
624
626 friend std::ostream &operator<<(std::ostream &os, const helios::uint4 &vec) {
627 return os << "helios::uint4<" << vec.x << ", " << vec.y << ", " << vec.z << ", " << vec.w << ">";
628 }
629 };
630
632
639 constexpr uint4 make_uint4(unsigned int x, unsigned int y, unsigned int z, unsigned int w) {
640 return {x, y, z, w};
641 }
642
644
648 constexpr uint4 make_uint4(const unsigned int X[4]) {
649 return {X[0], X[1], X[2], X[3]};
650 }
651
652 constexpr uint4 uint4::operator+(const uint4 &a) const noexcept {
653 return {a.x + x, a.y + y, a.z + z, a.w + w};
654 }
655
656 inline uint4 &uint4::operator+=(const uint4 &a) noexcept {
657 this->x += a.x;
658 this->y += a.y;
659 this->z += a.z;
660 this->w += a.w;
661 return *this;
662 }
663
664 inline uint4 &uint4::operator-=(const uint4 &a) noexcept {
665 this->x -= a.x;
666 this->y -= a.y;
667 this->z -= a.z;
668 this->w -= a.w;
669 return *this;
670 }
671
672 constexpr uint4 uint4::operator-(const uint4 &a) const noexcept {
673 return {x - a.x, y - a.y, z - a.z, w - a.w};
674 }
675
676 constexpr bool uint4::operator==(const uint4 &a) const noexcept {
677 return a.x == x && a.y == y && a.z == z && a.w == w;
678 }
679
680 constexpr bool uint4::operator!=(const uint4 &a) const noexcept {
681 return a.x != x || a.y != y || a.z != z || a.w != w;
682 }
683
684 constexpr uint4 uint4::operator-() const noexcept {
685 return {static_cast<unsigned int>(0u - x), static_cast<unsigned int>(0u - y), static_cast<unsigned int>(0u - z), static_cast<unsigned int>(0u - w)};
686 }
687
689
692 struct vec2 {
693
694
696 float x;
698 float y;
699
702 const float m2 = x * x + y * y;
703 if (m2 <= 0)
704 return *this;
705 const float inv = 1.0f / sqrtf(m2);
706 this->x *= inv;
707 this->y *= inv;
708 return *this;
709 }
710
712
715 [[nodiscard]] float magnitude() const {
716 return sqrtf(x * x + y * y);
717 }
718
720
723 constexpr vec2() : x(0), y(0) {
724 }
725
727 explicit vec2(const std::vector<float> &v) {
728 if (v.size() != 2) {
729 throw(std::runtime_error("ERROR: vector for initialization of vec2 must have length 2."));
730 }
731 x = v[0];
732 y = v[1];
733 }
735 explicit constexpr vec2(const float v[2]) : x(v[0]), y(v[1]) {
736 }
737
739 constexpr vec2(float v0, float v1) : x(v0), y(v1) {
740 }
741
743 constexpr float operator*(const vec2 &a) const noexcept;
745 constexpr vec2 operator+(const vec2 &a) const noexcept;
747 inline vec2 &operator+=(const vec2 &a) noexcept;
749 inline vec2 &operator-=(const vec2 &a) noexcept;
751 inline vec2 &operator*=(float a) noexcept;
753 inline vec2 &operator/=(float a) noexcept;
755 constexpr vec2 operator-(const vec2 &a) const noexcept;
757 constexpr vec2 operator*(float a) const noexcept;
759 inline vec2 operator/(float a) const noexcept;
761 constexpr vec2 operator+(float a) const noexcept;
763 constexpr vec2 operator-(float a) const noexcept;
765 constexpr bool operator==(const vec2 &a) const noexcept;
767 constexpr bool operator!=(const vec2 &a) const noexcept;
769 constexpr vec2 operator-() const noexcept;
770
772 friend std::ostream &operator<<(std::ostream &os, const helios::vec2 &vec) {
773 return os << "helios::vec2<" << vec.x << ", " << vec.y << ">";
774 }
775 };
776
778 constexpr vec2 operator*(float a, const vec2 &v) noexcept;
780 constexpr vec2 operator+(float a, const vec2 &v) noexcept;
782 constexpr vec2 operator-(float a, const vec2 &v) noexcept;
783
785
790 constexpr vec2 make_vec2(float x, float y) {
791 return {x, y};
792 }
793
794 inline vec2 normalize(const vec2 &v) {
795 const float m2 = v.x * v.x + v.y * v.y;
796 const float inv = 1.0f / sqrtf(m2);
797 return {v.x * inv, v.y * inv};
798 }
799
800 constexpr float vec2::operator*(const vec2 &a) const noexcept {
801 return a.x * x + a.y * y;
802 }
803
804 constexpr vec2 vec2::operator+(const vec2 &a) const noexcept {
805 return {a.x + x, a.y + y};
806 }
807
808 inline vec2 &vec2::operator+=(const vec2 &a) noexcept {
809 x += a.x;
810 y += a.y;
811 return *this;
812 }
813
814 inline vec2 &vec2::operator-=(const vec2 &a) noexcept {
815 x -= a.x;
816 y -= a.y;
817 return *this;
818 }
819
820 inline vec2 &vec2::operator*=(float a) noexcept {
821 x *= a;
822 y *= a;
823 return *this;
824 }
825
826 inline vec2 &vec2::operator/=(float a) noexcept {
827 x /= a;
828 y /= a;
829 return *this;
830 }
831
832 constexpr vec2 vec2::operator+(const float a) const noexcept {
833 return {a + x, a + y};
834 }
835
836 constexpr vec2 operator+(const float a, const vec2 &v) noexcept {
837 return {a + v.x, a + v.y};
838 }
839
840 constexpr vec2 vec2::operator-(const vec2 &a) const noexcept {
841 return {x - a.x, y - a.y};
842 }
843
844 constexpr vec2 vec2::operator-(const float a) const noexcept {
845 return {x - a, y - a};
846 }
847
848 constexpr vec2 operator-(const float a, const vec2 &v) noexcept {
849 return {a - v.x, a - v.y};
850 }
851
852 constexpr vec2 vec2::operator*(const float a) const noexcept {
853 return {x * a, y * a};
854 }
855
856 constexpr vec2 operator*(const float a, const vec2 &v) noexcept {
857 return {a * v.x, a * v.y};
858 }
859
860 inline vec2 vec2::operator/(const float a) const noexcept {
861 const float inv_a = (a != 0.f ? 1.f / a : std::copysign(std::numeric_limits<float>::infinity(), a));
862 return {x * inv_a, y * inv_a};
863 }
864
865 constexpr bool vec2::operator==(const vec2 &a) const noexcept {
866 return x == a.x && y == a.y;
867 }
868
869 constexpr bool vec2::operator!=(const vec2 &a) const noexcept {
870 return x != a.x || y != a.y;
871 }
872
873 constexpr vec2 vec2::operator-() const noexcept {
874 return {-x, -y};
875 }
876
878
881 struct vec3 {
882
884 float x;
886 float y;
888 float z;
889
892 const float m2 = x * x + y * y + z * z;
893 if (m2 <= 0)
894 return *this;
895 const float inv = 1.0f / sqrtf(m2);
896 this->x *= inv;
897 this->y *= inv;
898 this->z *= inv;
899 return *this;
900 }
901
903
906 [[nodiscard]] float magnitude() const {
907 return sqrtf(x * x + y * y + z * z);
908 }
909
911
914 constexpr vec3() : x(0), y(0), z(0) {
915 }
916
918 explicit vec3(const std::vector<float> &v) {
919 if (v.size() != 3) {
920 throw(std::runtime_error("ERROR: vector for initialization of vec3 must have length 3."));
921 }
922 x = v[0];
923 y = v[1];
924 z = v[2];
925 }
927 explicit constexpr vec3(const float v[3]) : x(v[0]), y(v[1]), z(v[2]) {
928 }
929
931 constexpr vec3(float v0, float v1, float v2) : x(v0), y(v1), z(v2) {
932 }
933
935 constexpr float operator*(const vec3 &a) const noexcept;
937 constexpr vec3 operator+(const vec3 &a) const noexcept;
939 inline vec3 &operator+=(const vec3 &a) noexcept;
941 inline vec3 &operator-=(const vec3 &a) noexcept;
943 inline vec3 &operator*=(float a) noexcept;
945 inline vec3 &operator/=(float a) noexcept;
947 constexpr vec3 operator-(const vec3 &a) const noexcept;
949 constexpr vec3 operator*(float a) const noexcept;
951 inline vec3 operator/(float a) const noexcept;
953 constexpr vec3 operator+(float a) const noexcept;
955 constexpr vec3 operator-(float a) const noexcept;
957 constexpr bool operator==(const vec3 &a) const noexcept;
959 constexpr bool operator!=(const vec3 &a) const noexcept;
961 constexpr vec3 operator-() const noexcept;
962
964 friend std::ostream &operator<<(std::ostream &os, const helios::vec3 &vec) {
965 return os << "helios::vec3<" << vec.x << ", " << vec.y << ", " << vec.z << ">";
966 }
967 };
968
970 constexpr vec3 operator*(float a, const vec3 &v) noexcept;
972 constexpr vec3 operator+(float a, const vec3 &v) noexcept;
974 constexpr vec3 operator-(float a, const vec3 &v) noexcept;
975
977 constexpr vec3 make_vec3(float x, float y, float z) {
978 return {x, y, z};
979 }
980
982 constexpr vec3 make_vec3(float X[3]) {
983 return {X[0], X[1], X[2]};
984 }
985
987 constexpr vec3 cross(const vec3 &a, const vec3 &b) {
988 return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x};
989 }
990
991 inline vec3 normalize(const vec3 &v) noexcept {
992 const float m2 = v.x * v.x + v.y * v.y + v.z * v.z;
993 const float inv = 1.0f / sqrtf(m2);
994 return {v.x * inv, v.y * inv, v.z * inv};
995 }
996
997 constexpr float vec3::operator*(const vec3 &a) const noexcept {
998 return a.x * x + a.y * y + a.z * z;
999 }
1000
1001 constexpr vec3 vec3::operator+(const vec3 &a) const noexcept {
1002 return {a.x + x, a.y + y, a.z + z};
1003 }
1004
1005 inline vec3 &vec3::operator+=(const vec3 &a) noexcept {
1006 this->x += a.x;
1007 this->y += a.y;
1008 this->z += a.z;
1009 return *this;
1010 }
1011
1012 inline vec3 &vec3::operator-=(const vec3 &a) noexcept {
1013 this->x -= a.x;
1014 this->y -= a.y;
1015 this->z -= a.z;
1016 return *this;
1017 }
1018
1019 inline vec3 &vec3::operator*=(float a) noexcept {
1020 x *= a;
1021 y *= a;
1022 z *= a;
1023 return *this;
1024 }
1025
1026 inline vec3 &vec3::operator/=(float a) noexcept {
1027 x /= a;
1028 y /= a;
1029 z /= a;
1030 return *this;
1031 }
1032
1033 constexpr vec3 vec3::operator+(float a) const noexcept {
1034 return {x + a, y + a, z + a};
1035 }
1036
1037 constexpr vec3 operator+(float a, const vec3 &v) noexcept {
1038 return {a + v.x, a + v.y, a + v.z};
1039 }
1040
1041 constexpr vec3 vec3::operator-(const vec3 &a) const noexcept {
1042 return {x - a.x, y - a.y, z - a.z};
1043 }
1044
1045 constexpr vec3 vec3::operator-(float a) const noexcept {
1046 return {x - a, y - a, z - a};
1047 }
1048
1049 constexpr vec3 operator-(float a, const vec3 &v) noexcept {
1050 return {a - v.x, a - v.y, a - v.z};
1051 }
1052
1053 constexpr vec3 vec3::operator*(float a) const noexcept {
1054 return {x * a, y * a, z * a};
1055 }
1056
1057 constexpr vec3 operator*(float a, const vec3 &v) noexcept {
1058 return {a * v.x, a * v.y, a * v.z};
1059 }
1060
1061 inline vec3 vec3::operator/(const float a) const noexcept {
1062 const float inv_a = (a != 0.f ? 1.f / a : std::copysign(std::numeric_limits<float>::infinity(), a));
1063 return {x * inv_a, y * inv_a, z * inv_a};
1064 }
1065
1066 constexpr bool vec3::operator==(const vec3 &a) const noexcept {
1067 return x == a.x && y == a.y && z == a.z;
1068 }
1069
1070 constexpr bool vec3::operator!=(const vec3 &a) const noexcept {
1071 return x != a.x || y != a.y || z != a.z;
1072 }
1073
1074 constexpr vec3 vec3::operator-() const noexcept {
1075 return {-x, -y, -z};
1076 }
1077
1079
1082 struct vec4 {
1083
1084
1086 float x;
1088 float y;
1090 float z;
1092 float w;
1093
1096 const float m2 = x * x + y * y + z * z + w * w;
1097 if (m2 <= 0)
1098 return *this;
1099 const float inv = 1.0f / sqrtf(m2);
1100 this->x *= inv;
1101 this->y *= inv;
1102 this->z *= inv;
1103 this->w *= inv;
1104 return *this;
1105 }
1106
1108
1111 [[nodiscard]] float magnitude() const {
1112 return sqrt(x * x + y * y + z * z + w * w);
1113 }
1114
1116
1119 constexpr vec4() : x(0), y(0), z(0), w(0) {
1120 }
1121
1123 explicit vec4(const std::vector<float> &v) {
1124 if (v.size() != 4) {
1125 throw(std::runtime_error("ERROR: vector for initialization of vec4 must have length 4."));
1126 }
1127 x = v[0];
1128 y = v[1];
1129 z = v[2];
1130 w = v[3];
1131 }
1133 explicit constexpr vec4(const float v[4]) : x(v[0]), y(v[1]), z(v[2]), w(v[3]) {
1134 }
1135
1137 constexpr vec4(float v0, float v1, float v2, float v3) : x(v0), y(v1), z(v2), w(v3) {
1138 }
1139
1141 constexpr float operator*(const vec4 &a) const noexcept;
1143 constexpr vec4 operator+(const vec4 &a) const noexcept;
1145 inline vec4 &operator+=(const vec4 &a) noexcept;
1147 inline vec4 &operator-=(const vec4 &a) noexcept;
1149 inline vec4 &operator*=(float a) noexcept;
1151 inline vec4 &operator/=(float a) noexcept;
1153 constexpr vec4 operator-(const vec4 &a) const noexcept;
1155 constexpr vec4 operator*(float a) const noexcept;
1157 inline vec4 operator/(float a) const noexcept;
1159 constexpr vec4 operator+(float a) const noexcept;
1161 constexpr vec4 operator-(float a) const noexcept;
1163 constexpr bool operator==(const vec4 &a) const noexcept;
1165 constexpr bool operator!=(const vec4 &a) const noexcept;
1167 constexpr vec4 operator-() const noexcept;
1168
1170 friend std::ostream &operator<<(std::ostream &os, const helios::vec4 &vec) {
1171 return os << "helios::vec4<" << vec.x << ", " << vec.y << ", " << vec.z << ", " << vec.w << ">";
1172 }
1173 };
1174
1176 constexpr vec4 operator*(float a, const vec4 &v) noexcept;
1178 constexpr vec4 operator+(float a, const vec4 &v) noexcept;
1180 constexpr vec4 operator-(float a, const vec4 &v) noexcept;
1181
1183 constexpr vec4 make_vec4(float x, float y, float z, float w) {
1184 return {x, y, z, w};
1185 }
1186
1188 constexpr vec4 make_vec4(float X[4]) {
1189 return {X[0], X[1], X[2], X[3]};
1190 }
1191
1192 inline vec4 normalize(const vec4 &v) {
1193 const float m2 = v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w;
1194 const float inv = 1.0f / sqrtf(m2);
1195 return {v.x * inv, v.y * inv, v.z * inv, v.w * inv};
1196 }
1197
1198 constexpr float vec4::operator*(const vec4 &a) const noexcept {
1199 return a.x * x + a.y * y + a.z * z + a.w * w;
1200 }
1201
1202 constexpr vec4 vec4::operator+(const vec4 &a) const noexcept {
1203 return {a.x + x, a.y + y, a.z + z, a.w + w};
1204 }
1205
1206 inline vec4 &vec4::operator+=(const vec4 &a) noexcept {
1207 this->x += a.x;
1208 this->y += a.y;
1209 this->z += a.z;
1210 this->w += a.w;
1211 return *this;
1212 }
1213
1214 inline vec4 &vec4::operator-=(const vec4 &a) noexcept {
1215 this->x -= a.x;
1216 this->y -= a.y;
1217 this->z -= a.z;
1218 this->w -= a.w;
1219 return *this;
1220 }
1221
1222 inline vec4 &vec4::operator*=(float a) noexcept {
1223 x *= a;
1224 y *= a;
1225 z *= a;
1226 w *= a;
1227 return *this;
1228 }
1229
1230 inline vec4 &vec4::operator/=(float a) noexcept {
1231 x /= a;
1232 y /= a;
1233 z /= a;
1234 w /= a;
1235 return *this;
1236 }
1237
1238 constexpr vec4 vec4::operator+(float a) const noexcept {
1239 return {x + a, y + a, z + a, w + a};
1240 }
1241
1242 constexpr vec4 operator+(float a, const vec4 &v) noexcept {
1243 return {a + v.x, a + v.y, a + v.z, a + v.w};
1244 }
1245
1246 constexpr vec4 vec4::operator-(const vec4 &a) const noexcept {
1247 return {x - a.x, y - a.y, z - a.z, w - a.w};
1248 }
1249
1250 constexpr vec4 vec4::operator-(float a) const noexcept {
1251 return {x - a, y - a, z - a, w - a};
1252 }
1253
1254 constexpr vec4 operator-(float a, const vec4 &v) noexcept {
1255 return {a - v.x, a - v.y, a - v.z, a - v.w};
1256 }
1257
1258 constexpr vec4 vec4::operator*(float a) const noexcept {
1259 return {x * a, y * a, z * a, w * a};
1260 }
1261
1262 constexpr vec4 operator*(float a, const vec4 &v) noexcept {
1263 return {a * v.x, a * v.y, a * v.z, a * v.w};
1264 }
1265
1266 inline vec4 vec4::operator/(const float a) const noexcept {
1267 const float inv_a = (a != 0.f ? 1.f / a : std::copysign(std::numeric_limits<float>::infinity(), a));
1268 return {x * inv_a, y * inv_a, z * inv_a, w * inv_a};
1269 }
1270
1271 constexpr bool vec4::operator==(const vec4 &a) const noexcept {
1272 return x == a.x && y == a.y && z == a.z && w == a.w;
1273 }
1274
1275 constexpr bool vec4::operator!=(const vec4 &a) const noexcept {
1276 return x != a.x || y != a.y || z != a.z || w != a.w;
1277 }
1278
1279 constexpr vec4 vec4::operator-() const noexcept {
1280 return {-x, -y, -z, -w};
1281 }
1282
1284
1287 struct RGBcolor {
1288
1289
1291
1292 float r;
1294
1295 float g;
1297
1298 float b;
1299
1301 constexpr RGBcolor() : r(0), g(0), b(0) {
1302 }
1303
1305
1311 constexpr RGBcolor(float red, float green, float blue) : r(RGBcolor::clamp(red)), g(RGBcolor::clamp(green)), b(RGBcolor::clamp(blue)) {
1312 }
1313
1315
1319 explicit constexpr RGBcolor(const float C[3]) : r(RGBcolor::clamp(C[0])), g(RGBcolor::clamp(C[1])), b(RGBcolor::clamp(C[2])) {
1320 }
1321
1323
1327 explicit RGBcolor(const std::vector<float> &C) {
1328 if (C.size() != 3) {
1329 throw(std::runtime_error("ERROR: cannot initialize RGBcolor using supplied vector - size should be 3."));
1330 }
1331 r = RGBcolor::clamp(C[0]);
1332 g = RGBcolor::clamp(C[1]);
1333 b = RGBcolor::clamp(C[2]);
1334 }
1336
1340 explicit constexpr RGBcolor(const vec3 &C) : r(RGBcolor::clamp(C.x)), g(RGBcolor::clamp(C.y)), b(RGBcolor::clamp(C.z)) {
1341 }
1342
1344
1347 void scale(float scale_factor) {
1348 if (scale_factor < 0) {
1349 throw(std::runtime_error("ERROR (RGBcolor::scale): cannot scale RGBcolor by negative factor."));
1350 }
1351 r *= scale_factor;
1352 g *= scale_factor;
1353 b *= scale_factor;
1354 }
1355
1357 friend std::ostream &operator<<(std::ostream &os, const helios::RGBcolor &c) {
1358 return os << "helios::RGBcolor<" << c.r << ", " << c.g << ", " << c.b << ">";
1359 }
1360
1362 constexpr RGBcolor operator+(const RGBcolor &c) const noexcept;
1364 constexpr RGBcolor operator-(const RGBcolor &c) const noexcept;
1366 constexpr bool operator==(const RGBcolor &c) const noexcept;
1368 constexpr bool operator!=(const RGBcolor &c) const noexcept;
1369
1370 private:
1372
1376 static constexpr float clamp(float value) {
1377 return (value < 0.f) ? 0.f : (value > 1.f) ? 1.f : value;
1378 }
1379 };
1380
1382
1388 inline RGBcolor make_RGBcolor(float red, float green, float blue) {
1389 return {red, green, blue};
1390 }
1391
1393
1398 RGBcolor blend(const RGBcolor &color0, const RGBcolor &color1, float weight);
1399
1400 constexpr RGBcolor RGBcolor::operator+(const RGBcolor &c) const noexcept {
1401 return {clamp(r + c.r), clamp(g + c.g), clamp(b + c.b)};
1402 }
1403
1404 constexpr RGBcolor RGBcolor::operator-(const RGBcolor &c) const noexcept {
1405 return {clamp(r - c.r), clamp(g - c.g), clamp(b - c.b)};
1406 }
1407
1408 constexpr bool RGBcolor::operator==(const RGBcolor &c) const noexcept {
1409 constexpr float epsilon = 1e-6f;
1410 auto constexpr_abs = [](float x) constexpr { return x < 0 ? -x : x; };
1411 return (constexpr_abs(r - c.r) < epsilon) && (constexpr_abs(g - c.g) < epsilon) && (constexpr_abs(b - c.b) < epsilon);
1412 }
1413
1414 constexpr bool RGBcolor::operator!=(const RGBcolor &c) const noexcept {
1415 return c.r != r || c.g != g || c.b != b;
1416 }
1417
1419 namespace RGB {
1420
1422 extern RGBcolor red;
1424 extern RGBcolor blue;
1426 extern RGBcolor green;
1428 extern RGBcolor cyan;
1430 extern RGBcolor magenta;
1432 extern RGBcolor yellow;
1434 extern RGBcolor orange;
1436 extern RGBcolor violet;
1438 extern RGBcolor black;
1440 extern RGBcolor white;
1442 extern RGBcolor lime;
1444 extern RGBcolor silver;
1446 extern RGBcolor gray;
1448 extern RGBcolor navy;
1450 extern RGBcolor brown;
1452 extern RGBcolor khaki;
1454 extern RGBcolor greenyellow;
1456 extern RGBcolor forestgreen;
1458 extern RGBcolor yellowgreen;
1460 extern RGBcolor goldenrod;
1461
1462 } // namespace RGB
1463
1465
1468 struct RGBAcolor {
1469
1471
1472 float r;
1474
1475 float g;
1477
1478 float b;
1480
1481 float a;
1482
1484 constexpr RGBAcolor() : r(0), g(0), b(0), a(1) {
1485 }
1486
1488
1495 constexpr RGBAcolor(float red, float green, float blue, float alpha) : r(RGBAcolor::clamp(red)), g(RGBAcolor::clamp(green)), b(RGBAcolor::clamp(blue)), a(RGBAcolor::clamp(alpha)) {
1496 }
1497
1499
1503 explicit constexpr RGBAcolor(const float C[4]) : r(RGBAcolor::clamp(C[0])), g(RGBAcolor::clamp(C[1])), b(RGBAcolor::clamp(C[2])), a(RGBAcolor::clamp(C[3])) {
1504 }
1505
1507
1511 explicit RGBAcolor(const std::vector<float> &C) {
1512 if (C.size() != 4) {
1513 throw(std::runtime_error("ERROR: cannot initialize RGBAcolor using supplied vector - size should be 4."));
1514 }
1515 r = RGBAcolor::clamp(C[0]);
1516 g = RGBAcolor::clamp(C[1]);
1517 b = RGBAcolor::clamp(C[2]);
1518 a = RGBAcolor::clamp(C[3]);
1519 }
1520
1522
1525 void scale(float scale_factor) {
1526 if (scale_factor < 0) {
1527 throw(std::runtime_error("ERROR (RGBAcolor::scale): cannot scale RGBAcolor by negative factor."));
1528 }
1529 r *= scale_factor;
1530 g *= scale_factor;
1531 b *= scale_factor;
1532 a *= scale_factor;
1533 }
1534
1536 friend std::ostream &operator<<(std::ostream &os, const helios::RGBAcolor &c) {
1537 return os << "helios::RGBAcolor<" << c.r << ", " << c.g << ", " << c.b << ", " << c.a << ">";
1538 }
1539
1541 constexpr RGBAcolor operator+(const RGBAcolor &c) const noexcept;
1543 constexpr RGBAcolor operator-(const RGBAcolor &c) const noexcept;
1545 constexpr bool operator==(const helios::RGBAcolor &c) const noexcept;
1547 constexpr bool operator!=(const helios::RGBAcolor &c) const noexcept;
1548
1549 private:
1551
1555 static constexpr float clamp(float value) {
1556 return (value < 0.f) ? 0.f : (value > 1.f) ? 1.f : value;
1557 }
1558 };
1559
1561
1568 inline RGBAcolor make_RGBAcolor(float r, float g, float b, float a) {
1569 return {r, g, b, a};
1570 }
1571
1573
1578 inline RGBAcolor make_RGBAcolor(RGBcolor color, float a) {
1579 return {color.r, color.g, color.b, a};
1580 }
1581
1583
1588 RGBAcolor blend(const helios::RGBAcolor &color0, const helios::RGBAcolor &color1, float weight);
1589
1590 constexpr bool RGBAcolor::operator==(const RGBAcolor &c) const noexcept {
1591 constexpr float epsilon = 1e-6f;
1592 auto constexpr_abs = [](float x) constexpr { return x < 0 ? -x : x; };
1593 return (constexpr_abs(r - c.r) < epsilon) && (constexpr_abs(g - c.g) < epsilon) && (constexpr_abs(b - c.b) < epsilon && (constexpr_abs(a - c.a) < epsilon));
1594 }
1595
1596 constexpr bool RGBAcolor::operator!=(const RGBAcolor &c) const noexcept {
1597 return c.r != r || c.g != g || c.b != b || c.a != a;
1598 }
1599
1600 constexpr RGBAcolor RGBAcolor::operator+(const RGBAcolor &c) const noexcept {
1601 return {clamp(r + c.r), clamp(g + c.g), clamp(b + c.b), clamp(a + c.a)};
1602 }
1603
1604 constexpr RGBAcolor RGBAcolor::operator-(const RGBAcolor &c) const noexcept {
1605 return {clamp(r - c.r), clamp(g - c.g), clamp(b - c.b), clamp(a - c.a)};
1606 }
1607
1609 namespace RGBA {
1610
1612 extern RGBAcolor red;
1614 extern RGBAcolor blue;
1616 extern RGBAcolor green;
1618 extern RGBAcolor cyan;
1620 extern RGBAcolor magenta;
1622 extern RGBAcolor yellow;
1624 extern RGBAcolor orange;
1626 extern RGBAcolor violet;
1628 extern RGBAcolor black;
1630 extern RGBAcolor white;
1632 extern RGBAcolor lime;
1634 extern RGBAcolor silver;
1636 extern RGBAcolor gray;
1638 extern RGBAcolor navy;
1640 extern RGBAcolor brown;
1642 extern RGBAcolor khaki;
1644 extern RGBAcolor greenyellow;
1646 extern RGBAcolor forestgreen;
1648 extern RGBAcolor yellowgreen;
1650 extern RGBAcolor goldenrod;
1651
1652 } // namespace RGBA
1653
1655
1659 struct Date {
1660
1661
1663 int day;
1667 int year;
1668
1670 constexpr Date() : day(1), month(1), year(2000) {
1671 }
1672
1674
1679 Date(int day, int month, int year) : day(day), month(month), year(year) {
1680
1681 if (day < 1 || day > 31) {
1682 throw(std::runtime_error("ERROR (Date constructor): Day of month is out of range (day of " + std::to_string(day) + " was given)."));
1683 } else if (month < 1 || month > 12) {
1684 throw(std::runtime_error("ERROR (Date constructor): Month of year is out of range (month of " + std::to_string(month) + " was given)."));
1685 } else if (year < 1000) {
1686 throw(std::runtime_error("ERROR (Date constructor): Year should be specified in YYYY format."));
1687 }
1688 }
1689
1691
1694 [[nodiscard]] int JulianDay() const;
1695
1697 void incrementDay();
1698
1700
1703 [[nodiscard]] bool isLeapYear() const;
1704
1706 constexpr bool operator==(const helios::Date &c) const noexcept;
1708 constexpr bool operator!=(const helios::Date &c) const noexcept;
1709
1711 friend std::ostream &operator<<(std::ostream &os, helios::Date const &d) {
1712 return os << d.year << "-" << std::setfill('0') << std::setw(2) << d.month << "-" << std::setfill('0') << std::setw(2) << d.day;
1713 }
1714 };
1715
1717
1723 inline Date make_Date(int day, int month, int year) {
1724 if (day < 1 || day > 31) {
1725 throw(std::runtime_error("ERROR (make_Date): Day of month is out of range (day of " + std::to_string(day) + " was given)."));
1726 } else if (month < 1 || month > 12) {
1727 throw(std::runtime_error("ERROR (make_Date): Month of year is out of range (month of " + std::to_string(month) + " was given)."));
1728 } else if (year < 1000) {
1729 throw(std::runtime_error("ERROR (make_Date): Year should be specified in YYYY format."));
1730 }
1731
1732 return {day, month, year};
1733 }
1734
1735 constexpr bool Date::operator==(const Date &c) const noexcept {
1736 return c.day == day && c.month == month && c.year == year;
1737 }
1738
1739 constexpr bool Date::operator!=(const Date &c) const noexcept {
1740 return c.day != day || c.month != month || c.year != year;
1741 }
1742
1744
1749 inline Date Julian2Calendar(int JulianDay, int year) {
1750
1751 int month = -1;
1752
1753 int skips_leap[] = {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335};
1754 int skips_nonleap[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
1755 const int *skips = nullptr;
1756
1757 if (JulianDay < 1 || JulianDay > 366) {
1758 throw(std::runtime_error("ERROR (Julian2Calendar): Julian day of " + std::to_string(JulianDay) + " is out of range (should be >0 and <367)."));
1759 }
1760
1761 if ((year - 2000) % 4 == 0) { // leap year
1762 skips = skips_leap;
1763 } else { // non-leap year
1764 skips = skips_nonleap;
1765 }
1766
1767 for (int i = 1; i <= 12; i++) {
1768 if (i == 12) {
1769 month = 12;
1770 } else if (JulianDay > skips[i - 1] && JulianDay <= skips[i]) {
1771 month = i;
1772 break;
1773 }
1774 }
1775 assert(month > 0 && month < 13);
1776
1777 int day = JulianDay - skips[month - 1];
1778
1779 assert(day > 0 && day < 32);
1780
1781 return {day, month, year};
1782 }
1783
1785
1789 inline int Calendar2Julian(Date date) {
1790
1791 int skips_leap[] = {0, 31, 60, 91, 121, 152, 182, 214, 244, 274, 305, 335};
1792 int skips_nonleap[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
1793 int *skips = nullptr;
1794
1795 if ((date.year - 2000) % 4 == 0) { // leap year
1796 skips = skips_leap;
1797 } else { // non-leap year
1798 skips = skips_nonleap;
1799 }
1800
1801 int JD = skips[date.month - 1] + date.day;
1802 if (JD <= 0 || JD > 366) {
1803 throw("ERROR (Calendar2Julian): Julian day of " + std::to_string(JD) + " is out of range (should be >0 and <=366).");
1804 }
1805
1806 return JD;
1807 }
1808
1810
1815 inline Date make_Date(int JulianDay, int year) {
1816 if (JulianDay < 1 || JulianDay > 366) {
1817 throw(std::runtime_error("ERROR (make_Date): Julian day is out of range (Julian day of " + std::to_string(JulianDay) + " was given)."));
1818 } else if (year < 1000) {
1819 throw(std::runtime_error("ERROR (make_Date): Year should be specified in YYYY format."));
1820 }
1821
1822 return Julian2Calendar(JulianDay, year);
1823 }
1824
1825
1827
1831 struct Time {
1832
1838 int hour;
1839
1841 constexpr Time() : second(0), minute(0), hour(0) {
1842 }
1843
1845
1850
1851 if (minute < 0 || minute > 59) {
1852 throw(std::runtime_error("ERROR (Time constructor): Minute out of range (0-59)."));
1853 } else if (hour < 0 || hour > 23) {
1854 throw(std::runtime_error("ERROR (Time constructor): Hour out of range (0-23)."));
1855 }
1856 }
1857
1859
1865
1866 if (second < 0 || second > 59) {
1867 throw(std::runtime_error("ERROR (Time constructor): Second out of range (0-59)."));
1868 } else if (minute < 0 || minute > 59) {
1869 throw(std::runtime_error("ERROR (Time constructor): Minute out of range (0-59)."));
1870 } else if (hour < 0 || hour > 23) {
1871 throw(std::runtime_error("ERROR (Time constructor): Hour out of range (0-23)."));
1872 }
1873 }
1874
1876 constexpr bool operator==(const helios::Time &c) const noexcept;
1878 constexpr bool operator!=(const helios::Time &c) const noexcept;
1879
1881 friend std::ostream &operator<<(std::ostream &os, helios::Time const &t) {
1882 return os << t.hour << ":" << std::setfill('0') << std::setw(2) << t.minute << ":" << std::setfill('0') << std::setw(2) << t.second;
1883 }
1884 };
1885
1887
1892 inline Time make_Time(int hour, int minute) {
1893 if (minute < 0 || minute > 59) {
1894 throw(std::runtime_error("ERROR (make_Time): Minute of " + std::to_string(minute) + " out of range (0-59)."));
1895 } else if (hour < 0 || hour > 23) {
1896 throw(std::runtime_error("ERROR (make_Time): Hour of " + std::to_string(hour) + " out of range (0-23)."));
1897 }
1898
1899 return {hour, minute, 0};
1900 }
1901
1903
1909 inline Time make_Time(int hour, int minute, int second) {
1910 if (second < 0 || second > 59) {
1911 throw(std::runtime_error("ERROR (make_Time): Second of " + std::to_string(second) + " out of range (0-59)."));
1912 } else if (minute < 0 || minute > 59) {
1913 throw(std::runtime_error("ERROR (make_Time): Minute of " + std::to_string(minute) + " out of range (0-59)."));
1914 } else if (hour < 0 || hour > 23) {
1915 throw(std::runtime_error("ERROR (make_Time): Hour of " + std::to_string(hour) + " out of range (0-23)."));
1916 }
1917
1918 return {hour, minute, second};
1919 }
1920
1921 constexpr bool Time::operator==(const Time &c) const noexcept {
1922 return c.hour == hour && c.minute == minute && c.second == second;
1923 }
1924
1925 constexpr bool Time::operator!=(const Time &c) const noexcept {
1926 return c.hour != hour || c.minute != minute || c.second != second;
1927 }
1928
1930
1933 struct Location {
1934
1941
1944 latitude_deg = 38.55f;
1945 longitude_deg = 121.76f;
1946 UTC_offset = 8;
1947 }
1948
1950
1956
1957 this->latitude_deg = latitude_deg;
1958 this->longitude_deg = longitude_deg;
1959 this->UTC_offset = UTC_offset;
1960 }
1961
1963 bool operator==(const helios::Location &c) const noexcept;
1965 bool operator!=(const helios::Location &c) const noexcept;
1966
1968 friend std::ostream &operator<<(std::ostream &os, helios::Location const &t) {
1969 return os << "<" << t.latitude_deg << "," << t.longitude_deg << "," << t.UTC_offset << ">";
1970 }
1971 };
1972
1974
1980 inline Location make_Location(float latitude_deg, float longitude_deg, float UTC_offset) {
1981 return {latitude_deg, longitude_deg, UTC_offset};
1982 }
1983
1984 inline bool Location::operator==(const Location &c) const noexcept {
1985 return c.latitude_deg == latitude_deg && c.longitude_deg == longitude_deg && c.UTC_offset == UTC_offset;
1986 }
1987
1988 inline bool Location::operator!=(const Location &c) const noexcept {
1989 return c.latitude_deg != latitude_deg || c.longitude_deg != longitude_deg || c.UTC_offset != UTC_offset;
1990 }
1991
1993
1997 private:
1998 float elevation_private;
1999 float zenith_private;
2000
2001 public:
2003 float radius;
2005
2008 const float &elevation;
2010
2013 const float &zenith;
2015 float azimuth;
2016
2018
2019 SphericalCoord() : elevation_private(0.5f * static_cast<float>(M_PI)), zenith_private(0.f), elevation(elevation_private), zenith(zenith_private) {
2020 radius = 1;
2021 azimuth = 0;
2022 }
2024
2029 SphericalCoord(float radius, float elevation_radians, float azimuth_radians) :
2030 elevation_private(elevation_radians), zenith_private(0.5f * static_cast<float>(M_PI) - elevation_radians), radius(radius), elevation(elevation_private), zenith(zenith_private), azimuth(azimuth_radians) {
2031 }
2032
2034 SphericalCoord(const SphericalCoord &c) : elevation_private(c.elevation_private), zenith_private(c.zenith_private), radius(c.radius), elevation(c.elevation_private), zenith(c.zenith_private), azimuth(c.azimuth) {
2035 }
2036
2039 if (this != &c) {
2040 elevation_private = c.elevation_private;
2041 zenith_private = c.zenith_private;
2042 radius = c.radius;
2043 azimuth = c.azimuth;
2044 }
2045 return *this;
2046 }
2047
2049 bool operator==(const helios::SphericalCoord &c) const noexcept;
2051 bool operator!=(const helios::SphericalCoord &c) const noexcept;
2052
2054 friend std::ostream &operator<<(std::ostream &os, helios::SphericalCoord const &coord) {
2055 return os << "helios::SphericalCoord<" << coord.radius << ", " << coord.elevation << ", " << coord.azimuth << ">";
2056 }
2057 };
2058
2060
2064 inline SphericalCoord make_SphericalCoord(float elevation_radians, float azimuth_radians) {
2065 return {1, elevation_radians, azimuth_radians};
2066 }
2067
2069
2074 inline SphericalCoord make_SphericalCoord(float radius, float elevation_radians, float azimuth_radians) {
2075#ifdef HELIOS_DEBUG
2076 if (radius <= 0.f) {
2077 throw("ERROR (helios::make_SphericalCoord): radius should be positive, but " + std::to_string(radius) + " was given.");
2078 }
2079#endif
2080 return {radius, elevation_radians, azimuth_radians};
2081 }
2082
2083 inline bool SphericalCoord::operator==(const SphericalCoord &c) const noexcept {
2084 return c.radius == radius && c.zenith == zenith && c.elevation == elevation && c.azimuth == azimuth;
2085 }
2086
2087 inline bool SphericalCoord::operator!=(const SphericalCoord &c) const noexcept {
2088 return c.radius != radius || c.zenith != zenith || c.elevation != elevation || c.azimuth != azimuth;
2089 }
2090
2091
2092} // namespace helios
2093
2094#endif