@@ -24,8 +24,23 @@ template <> struct LookupName<Quantity<std::ratio<0>, std::ratio<0>, std::ratio<
24
24
// -15_cDeg == 105_stDeg
25
25
// 15_cDeg == 75_stDeg
26
26
27
- // in order to do conversions properly between angles in standard position and compass angles, we need this helper class
28
- // it can only be constructed through string literals
27
+ /* *
28
+ * @brief DO NOT USE
29
+ *
30
+ * this class prevents conversion errors from compass angles to angles in standard position.
31
+ *
32
+ * consider the following:
33
+ * 0_cDeg gets converted to standard position angles internally, so it's converted to 90
34
+ * -0_cDeg is converted to standard position angles internally, and only afterwards is the
35
+ * negative applied, so now it equals -90 internally
36
+ *
37
+ * This class solves this problem by introducing the CAngle type. You can do things like
38
+ * negate it, multiply it, etc. without messing up the angle. However, this class can
39
+ * only be created through string literals, you can't do something like
40
+ * CAngle angle = 2_cDeg
41
+ * because the constructor is private. However, you can do
42
+ * Angle angle = 2_cDeg
43
+ */
29
44
class CAngle : public Quantity <std::ratio<0 >, std::ratio<0 >, std::ratio<0 >, std::ratio<0 >, std::ratio<1 >, std::ratio<0 >,
30
45
std::ratio<0 >, std::ratio<0 >> {
31
46
// make string literals friends, so they have access to the constructor
@@ -43,8 +58,12 @@ class CAngle : public Quantity<std::ratio<0>, std::ratio<0>, std::ratio<0>, std:
43
58
// make CAngle able to be implicitly converted to Angle
44
59
constexpr operator Angle () const { return Angle (M_PI_2 - this ->value ); }
45
60
61
+ constexpr Angle operator -(Angle other) const { return Angle (*this ) - other; }
62
+
46
63
constexpr CAngle operator -() const { return CAngle (-this ->value ); }
47
64
65
+ constexpr Angle operator +(Angle other) const { return Angle (*this ) + other; }
66
+
48
67
constexpr CAngle operator +() const { return CAngle (this ->value ); }
49
68
private:
50
69
// only allow construction through literals
@@ -64,12 +83,27 @@ inline std::ostream& operator<<(std::ostream& os, const Angle& quantity) {
64
83
return os;
65
84
}
66
85
86
+ constexpr Angle operator +(Angle lhs, CAngle rhs) { return lhs + Angle (rhs); }
87
+
88
+ constexpr Angle operator -(Angle lhs, CAngle rhs) { return lhs - Angle (rhs); }
89
+
67
90
constexpr CAngle operator *(double multiple, CAngle quantity) { return CAngle (multiple * quantity.internal ()); }
68
91
69
92
constexpr CAngle operator *(CAngle quantity, double multiple) { return CAngle (multiple * quantity.internal ()); }
70
93
71
94
constexpr CAngle operator /(CAngle quantity, double multiple) { return CAngle (quantity.internal () / multiple); }
72
95
96
+ namespace units {
97
+ template <typename T>
98
+ concept isAngle = std::same_as<T, CAngle> || std::same_as<T, Angle> ||
99
+ std::same_as<T, Quantity<std::ratio<0 >, std::ratio<0 >, std::ratio<0 >, std::ratio<0 >, std::ratio<1 >,
100
+ std::ratio<0 >, std::ratio<0 >, std::ratio<0 >>>;
101
+
102
+ template <isAngle Q, isAngle R, isAngle S> constexpr Angle clamp (Q lhs, R lo, S hi) {
103
+ return Angle (std::clamp (lhs.internal (), lo.internal (), hi.internal ()));
104
+ }
105
+ } // namespace units
106
+
73
107
constexpr Angle rad = Angle(1.0 );
74
108
constexpr Angle deg = Angle(M_PI / 180 );
75
109
constexpr Angle rot = Angle(M_TWOPI);
0 commit comments