]> git.tdb.fi Git - libs/math.git/blob - source/geometry/angle.h
Some more member mis-use fixes
[libs/math.git] / source / geometry / angle.h
1 #ifndef MSP_GEOMETRY_ANGLE_H_
2 #define MSP_GEOMETRY_ANGLE_H_
3
4 #include <cmath>
5
6 namespace Msp {
7 namespace Geometry {
8
9 /**
10 A planar angle.  Creating an Angle from a raw value or extracting it requires
11 specifying the units used.  This eliminates a common source of errors.
12 */
13 template<typename T>
14 class Angle
15 {
16 private:
17         T value;
18
19         explicit Angle(T v): value(v) { }
20 public:
21         Angle(): value(0) { }
22         template<typename U>
23         Angle(const Angle<U> &other): value(other.radians()) { }
24
25         static Angle from_degrees(T);
26         static Angle from_radians(T);
27         static Angle from_turns(T);
28
29         static Angle zero() { return from_radians(0); }
30         static Angle right() { return from_radians(M_PI/2); }
31         static Angle quarter_turn() { return right(); }
32         static Angle straight() { return from_radians(M_PI); }
33         static Angle half_turn() { return straight(); }
34         static Angle full_turn() { return from_radians(2*M_PI); }
35
36         T degrees() const { return value*180/M_PI; }
37         T radians() const { return value; }
38         T turns() const { return value/(2*M_PI); }
39
40         Angle &operator+=(const Angle &);
41         Angle &operator-=(const Angle &);
42         Angle &operator*=(T);
43         Angle &operator/=(T);
44
45         bool operator==(const Angle &other) const { return value==other.value; }
46         bool operator!=(const Angle &other) const { return value!=other.value; }
47         bool operator<(const Angle &other) const { return value<other.value; }
48         bool operator<=(const Angle &other) const { return value<=other.value; }
49         bool operator>(const Angle &other) const { return value>other.value; }
50         bool operator>=(const Angle &other) const { return value>=other.value; }
51
52         Angle &wrap_with_base(const Angle &);
53         Angle &wrap_positive();
54         Angle &wrap_balanced();
55 };
56
57 template<typename T>
58 inline Angle<T> Angle<T>::from_degrees(T d)
59 {
60         return Angle<T>(d*M_PI/180);
61 }
62
63 template<typename T>
64 inline Angle<T> Angle<T>::from_radians(T r)
65 {
66         return Angle<T>(r);
67 }
68
69 template<typename T>
70 inline Angle<T> Angle<T>::from_turns(T t)
71 {
72         return Angle<T>(t*2*M_PI);
73 }
74
75 template<typename T>
76 inline Angle<T> &Angle<T>::operator+=(const Angle &a)
77 {
78         value += a.value;
79         return *this;
80 }
81
82 template<typename T>
83 inline Angle<T> operator+(const Angle<T> &a1, const Angle<T> &a2)
84 {
85         Angle<T> r(a1);
86         return r += a2;
87 }
88
89 template<typename T>
90 inline Angle<T> &Angle<T>::operator-=(const Angle &a)
91 {
92         value -= a.value;
93         return *this;
94 }
95
96 template<typename T>
97 inline Angle<T> operator-(const Angle<T> &a1, const Angle<T> &a2)
98 {
99         Angle<T> r(a1);
100         return r -= a2;
101 }
102
103 template<typename T>
104 inline Angle<T> operator-(const Angle<T> &a)
105 {
106         return Angle<T>::zero()-a;
107 }
108
109 template<typename T>
110 inline Angle<T> &Angle<T>::operator*=(T s)
111 {
112         value *= s;
113         return *this;
114 }
115
116 template<typename T>
117 inline Angle<T> operator*(const Angle<T> &a, T s)
118 {
119         Angle<T> r(a);
120         return r *= s;
121 }
122
123 template<typename T>
124 inline Angle<T> operator*(T s, const Angle<T> &a)
125 {
126         return a*s;
127 }
128
129 template<typename T>
130 inline Angle<T> &Angle<T>::operator/=(T s)
131 {
132         value /= s;
133         return *this;
134 }
135
136 template<typename T>
137 inline Angle<T> operator/(const Angle<T> &a, T s)
138 {
139         Angle<T> r(a);
140         return r /= s;
141 }
142
143 template<typename T>
144 inline Angle<T> operator/(T s, const Angle<T> &a)
145 {
146         return a/s;
147 }
148
149 template<typename T>
150 inline T operator/(const Angle<T> &a1, const Angle<T> &a2)
151 {
152         return a1.radians()/a2.radians();
153 }
154
155 template<typename T>
156 inline Angle<T> &Angle<T>::wrap_with_base(const Angle<T> &b)
157 {
158         while(value<b.value)
159                 value += 2*M_PI;
160         while(value>=b.value+2*M_PI)
161                 value -= 2*M_PI;
162         return *this;
163 }
164
165 template<typename T>
166 inline Angle<T> &Angle<T>::wrap_positive()
167 {
168         return wrap_with_base(zero());
169 }
170
171 template<typename T>
172 inline Angle<T> &Angle<T>::wrap_balanced()
173 {
174         return wrap_with_base(-half_turn());
175 }
176
177 template<typename T>
178 inline Angle<T> wrap_with_base(const Angle<T> &a, const Angle<T> &b)
179 {
180         Angle<T> r = a;
181         return r.wrap_with_base(b);
182 }
183
184 template<typename T>
185 inline Angle<T> wrap_positive(const Angle<T> &a)
186 {
187         Angle<T> r = a;
188         return r.wrap_positive();
189 }
190
191 template<typename T>
192 inline Angle<T> wrap_balanced(const Angle<T> &a)
193 {
194         Angle<T> r = a;
195         return r.wrap_balanced();
196 }
197
198 template<typename T>
199 inline Angle<T> abs(const Angle<T> &angle)
200 {
201         using std::abs;
202         return Angle<T>::from_radians(abs(angle.radians()));
203 }
204
205 template<typename T>
206 inline T sin(const Angle<T> &angle)
207 {
208         using std::sin;
209         return sin(angle.radians());
210 }
211
212 template<typename T>
213 inline Angle<T> asin(T s)
214 {
215         using std::asin;
216         return Angle<T>::from_radians(asin(s));
217 }
218
219 template<typename T>
220 inline T cos(const Angle<T> &angle)
221 {
222         using std::cos;
223         return cos(angle.radians());
224 }
225
226 template<typename T>
227 inline Angle<T> acos(T s)
228 {
229         using std::acos;
230         return Angle<T>::from_radians(acos(s));
231 }
232
233 template<typename T>
234 inline T tan(const Angle<T> &angle)
235 {
236         using std::tan;
237         return tan(angle.radians());
238 }
239
240 template<typename T>
241 inline Angle<T> atan(T s)
242 {
243         using std::atan;
244         return Angle<T>::from_radians(atan(s));
245 }
246
247 template<typename T>
248 inline Angle<T> atan2(T y, T x)
249 {
250         using std::atan2;
251         return Angle<T>::from_radians(atan2(y, x));
252 }
253
254 } // namespace Geometry
255 } // namespace Msp
256
257 #endif