Skip to content

Commit 2a20ff5

Browse files
committed
add + and - operators for Angle
1 parent 0acf513 commit 2a20ff5

File tree

2 files changed

+47
-6
lines changed

2 files changed

+47
-6
lines changed

include/units/Angle.hpp

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,23 @@ template <> struct LookupName<Quantity<std::ratio<0>, std::ratio<0>, std::ratio<
2424
// -15_cDeg == 105_stDeg
2525
// 15_cDeg == 75_stDeg
2626

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+
*/
2944
class CAngle : public Quantity<std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>, std::ratio<0>,
3045
std::ratio<0>, std::ratio<0>> {
3146
// 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:
4358
// make CAngle able to be implicitly converted to Angle
4459
constexpr operator Angle() const { return Angle(M_PI_2 - this->value); }
4560

61+
constexpr Angle operator-(Angle other) const { return Angle(*this) - other; }
62+
4663
constexpr CAngle operator-() const { return CAngle(-this->value); }
4764

65+
constexpr Angle operator+(Angle other) const { return Angle(*this) + other; }
66+
4867
constexpr CAngle operator+() const { return CAngle(this->value); }
4968
private:
5069
// only allow construction through literals
@@ -64,12 +83,27 @@ inline std::ostream& operator<<(std::ostream& os, const Angle& quantity) {
6483
return os;
6584
}
6685

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+
6790
constexpr CAngle operator*(double multiple, CAngle quantity) { return CAngle(multiple * quantity.internal()); }
6891

6992
constexpr CAngle operator*(CAngle quantity, double multiple) { return CAngle(multiple * quantity.internal()); }
7093

7194
constexpr CAngle operator/(CAngle quantity, double multiple) { return CAngle(quantity.internal() / multiple); }
7295

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+
73107
constexpr Angle rad = Angle(1.0);
74108
constexpr Angle deg = Angle(M_PI / 180);
75109
constexpr Angle rot = Angle(M_TWOPI);

src/main.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,9 @@ void initialize() {
2121
std::ratio<0>, std::ratio<0>>(1.0);
2222
a.orientation += 2_rpm2;
2323
2_rpm2 -= a.orientation;
24-
/*
2524
to_cDeg(Quantity<std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>, std::ratio<0>,
2625
std::ratio<0>, std::ratio<0>>(5.0) -
2726
a.theta() + 5_cDeg);
28-
*/
2927
Quantity<std::ratio<0>, std::ratio<0>, std::ratio<1>, std::ratio<0>, std::ratio<1>, std::ratio<0>, std::ratio<0>,
3028
std::ratio<0>>
3129
c = Multiplied<Angle, Time>();
@@ -34,11 +32,9 @@ void initialize() {
3432
Length z = toLinear<Angle>(y, 2_cm);
3533
static_assert(Angle(5.1) >= Quantity<std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>,
3634
std::ratio<0>, std::ratio<0>, std::ratio<0>>(5.0));
37-
/*
3835
units::clamp(2_cDeg, a.theta(),
3936
Quantity<std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>, std::ratio<0>,
4037
std::ratio<0>, std::ratio<0>>(5.0));
41-
*/
4238
units::max(10_celsius, Quantity<std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>,
4339
std::ratio<1>, std::ratio<0>, std::ratio<0>>(1.0));
4440
// check Vector3D overloads
@@ -61,4 +57,15 @@ void angleTests() {
6157
static_assert(r2i(to_stDeg(2 * 15_cDeg)) == r2i(to_stDeg(60_stDeg)));
6258
static_assert(r2i(to_stDeg(+0_cDeg)) == r2i(to_stDeg(90_stDeg)));
6359
static_assert(90_stDeg == +0_cDeg);
60+
Angle a = 2_cDeg;
61+
Angle b = 2_cDeg + 2_stDeg;
62+
Angle c = 2_stDeg - 2_cDeg;
63+
Angle d = 2_cDeg + Quantity<std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>,
64+
std::ratio<0>, std::ratio<0>, std::ratio<0>>(5.0);
65+
Angle e = Quantity<std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>, std::ratio<0>,
66+
std::ratio<0>, std::ratio<0>>(5.0) +
67+
2_cDeg;
68+
units::clamp(2_cDeg, 2_stDeg,
69+
Quantity<std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<0>, std::ratio<1>, std::ratio<0>,
70+
std::ratio<0>, std::ratio<0>>(5.0));
6471
}

0 commit comments

Comments
 (0)