view include/Vector.h @ 18:f9fb659509e1

Doxygen docs for Vector classes.
author Eris Caffee <discordia@eldalin.com>
date Mon, 27 May 2013 16:59:04 -0500
parents ea32c94fc495
children
line source
1 #ifndef VECTOR_H_
2 #define VECTOR_H_
4 #include <cassert>
5 #include <cmath>
6 #include <string>
7 #include <iostream>
8 #include <sstream>
11 namespace arda
12 {
13 namespace Math
14 {
15 ////////////////////////////////////////////////////////////////////////////////
16 /** \class arda::Math::Vector2
17 *
18 * \brief Templated classes for 2, 3, and 4 dimensional vectors.
19 *
20 * \tparam T Type is intended to be int, float, and double only. (i.e. if you roll your own base type, it had better act like a numeric scalar.)
21 *
22 * \verbatim
23 * Supported operations on vectors
24 *
25 * Construction
26 * Vector v; * Default zero vector.
27 * Vector v2(v); * Construct from other vector.
28 * T a, b;
29 * Vector v(a, b) * Construct from values.
30 * []
31 * If you have a Vector named v you can access it's member elements as
32 * v[0], v[1], v[2], and v[3]. in addtion to v.x, v.y, v.z, and v.w
33 * == != + += - -=
34 * Defined for operations on two vectors of the same type.
35 * TODO Is there a better way to do this? With integer types this is fine,
36 * but with floating point types this == and != are really worthless. Is it possible to
37 * create variant methods in a template class that vary by the type? Or do I just have
38 * to suck it up and create type specific external functions for comparing vectors?
39 * * *= / /=
40 * Defined for scalar multiplication/division with int, float, and double.
41 * * is defined as a standalone template operator for the scalar * Vector form.
42 *
43 * Note that the following typedefs are defined for convenience:
44 *
45 * typedef Vector2<int> Vector2i;
46 * typedef Vector2<float> Vector2f;
47 * typedef Vector2<double> Vector2d;
48 * typedef Vector3<int> Vector3i;
49 * typedef Vector3<float> Vector3f;
50 * typedef Vector3<double> Vector3d;
51 * typedef Vector4<int> Vector4i;
52 * typedef Vector4<float> Vector4f;
53 * typedef Vector4<double> Vector4d;
54 *
55 *
56 *
57 * Scalar multiplication and division are overloaded. Why?
58 * I'm not sure I need this. The idea is to support all likely scalar
59 * types without having to rely on implicit or explicit type conversion,
60 * especially not a conversion that might result in loss of precision.
61 * Multiplying a float Vector by a double scalar, for example.
62 *
63 * Is there a better way to do this? Am I worrying about nothing?
64 *
65 *
66 *
67 * I suppose I could make this into a single Vector template on two parameters
68 * template <typename T, unsigned int N> class Vector
69 * {
70 * T v[N];
71 *
72 * etc...
73 *
74 * This might buy perfect generality, but it would come at the expense of
75 * loops in all of the code, so I don't think it would really be worth it.
76 *
77 * \endverbatim
78 */
80 /////////////////////////////////////////////////////////////////////////////
81 template <typename T>
82 class Vector2
83 {
84 public:
85 T x, y;
87 // Constructors
88 Vector2() {}
89 explicit Vector2(T a) : x (a), y(a) {}
90 Vector2(T a, T b) : x (a), y(b) {}
92 // Array indexing
93 inline T& operator[](unsigned int const i)
94 { assert (i<2); if (i==0) return x; return y; }
95 inline T operator[](unsigned int const i) const
96 { assert (i<2); if (i==0) return x; return y; }
98 // Assignment
99 inline Vector2<T>& operator=(Vector2<T> const & v2)
100 { x = v2.x; y = v2.y; return *this; }
102 /** \brief Directly assign values to the vector.
103 *
104 * Takes 2, 3, or 4 arguments of template type T according to the size of the Vector.
105 */
107 inline Vector2<T>& assign(T const a, T const b)
108 { x = a; y = b; return *this; }
110 // Comparison
111 inline bool operator==(Vector2<T> const & v2) const
112 { return ((x == v2.x) && (y == v2.y)); }
113 inline bool operator!=(Vector2<T> const & v2) const
114 { return ! (*this == v2); }
116 // Vector addition
117 inline Vector2<T>& operator+=(Vector2<T> const & v2)
118 { x += v2.x; y += v2.y; return *this; }
119 inline Vector2<T> operator+(Vector2<T> const & v2) const
120 { return Vector2<T>(*this) += v2; }
122 // Vector subtraction
123 inline Vector2<T>& operator-=(Vector2<T> const & v2)
124 { x -= v2.x; y -= v2.y; return *this; }
125 inline Vector2<T> operator-(Vector2<T> const & v2) const
126 { return Vector2<T>(*this) -= v2; }
128 // Scalar multiplication
129 inline Vector2<T>& operator*=(int const a)
130 { x *= a; y *= a; return *this; }
131 inline Vector2<T>& operator*=(float const a)
132 { x *= a; y *= a; return *this; }
133 inline Vector2<T>& operator*=(double const a)
134 { x *= a; y *= a; return *this; }
136 inline Vector2<T> operator*(int const a) const
137 { return Vector2<T>(*this) *= a;}
138 inline Vector2<T> operator*(float const a) const
139 { return Vector2<T>(*this) *= a;}
140 inline Vector2<T> operator*(double const a) const
141 { return Vector2<T>(*this) *= a;}
143 // Scalar division
144 inline Vector2<T>& operator/=(int const a)
145 { assert(a!=0); x /= a; y /= a; return *this; }
146 inline Vector2<T>& operator/=(float const a)
147 { assert(a!=0); x /= a; y /= a; return *this; }
148 inline Vector2<T>& operator/=(double const a)
149 { assert(a!=0); x /= a; y /= a; return *this; }
151 inline Vector2<T> operator/(int const a) const
152 { return Vector2<T>(*this) /= a;}
153 inline Vector2<T> operator/(float const a) const
154 { return Vector2<T>(*this) /= a;}
155 inline Vector2<T> operator/(double const a) const
156 { return Vector2<T>(*this) /= a;}
159 // methods
161 /** \brief The dot product of the vector with v2.
162 */
163 inline T dot(Vector2<T> const & v2) const
164 { return x*v2.x + y*v2.y; }
167 /** \brief Returns the angle (in radians) between the vector and v2. Not meaningful for int vectors.
168 */
169 inline double get_angle(Vector2<T> const & v2)
170 {
171 double tmp = dot(v2);
172 return acos(sqrt(tmp*tmp/(dot(*this)*v2.dot(v2))));
173 }
176 /** \brief Like get_angle(), but the vectors must already be normalized. Not meaningful for int vectors.
177 */
178 inline double get_anglen(Vector2<T> const & v2)
179 { return acos((double) dot(v2)); }
182 /** \brief Returns a C string representation of the vector. This is one of the few non-inline Vector functions.
183 */
184 std::string to_string(void) const;
187 /** \brief Get the length of a vector. Returns a double for all vector types.
188 */
189 inline double length(void) const
190 { return sqrt((dot(*this))); }
193 /** \brief Normalizes the vector. Not meaningful for int vectors.
194 */
195 inline Vector2<T>& normalize()
196 {
197 double l = length();
198 if (l == 0.0) return *this;
199 x /= l; y /= l;
200 return *this; }
202 /** \brief Calculates the projection of the vector onto v2. Not meaningful for int vectors.
203 */
204 inline Vector2<T> proj(Vector2<T> const & v2)
205 { Vector2<T> vres; vres = v2 * (dot(v2)/v2.dot(v2)); return vres; }
206 /** \copybrief arda::Math::Vector2::proj
207 * Returns result in vres
208 */
209 inline Vector2<T>& proj(Vector2<T> const & v2, Vector2<T>& vres)
210 { vres = v2 * dot(v2)/v2.dot(v2); return vres; }
211 };
213 // Scalar multiplication, continued
214 template <typename T>
215 inline Vector2<T> operator*(int const a, Vector2<T> const & v)
216 { return Vector2<T>(v) *= a;}
218 template <typename T>
219 inline Vector2<T> operator*(float const a, Vector2<T> const & v)
220 { return Vector2<T>(v) *= a;}
222 template <typename T>
223 inline Vector2<T> operator*(double const a, Vector2<T> const & v)
224 { return Vector2<T>(v) *= a;}
227 /////////////////////////////////////////////////////////////////////////////
228 /** \class arda::Math::Vector3
229 * \copydoc arda::Math::Vector2
230 */
231 template <typename T>
232 class Vector3
233 {
234 public:
235 T x, y, z;
237 // Constructors
238 Vector3() {}
239 explicit Vector3(T a) : x (a), y(a), z(a) {}
240 Vector3(T a, T b, T c) : x (a), y(b), z(c) {}
241 Vector3(Vector2<T> v) : x (v.x), y (v.y), z (0) {}
243 // Array indexing
244 inline T& operator[](unsigned int const i)
245 { assert (i<3); if (i==0) return x; if (i==1) return y; return z; }
246 inline T operator[](unsigned int const i) const
247 { assert (i<3); if (i==0) return x; if (i==1) return y; return z; }
249 // Assignment
250 inline Vector3<T>& operator=(Vector2<T> const & v2)
251 { x = v2.x; y = v2.y; z = T(0); return *this; }
252 inline Vector3<T>& operator=(Vector3<T> const & v2)
253 { x = v2.x; y = v2.y; z = v2.z; return *this; }
255 /** \copydoc arda::Math::Vector2::assign */
256 inline Vector3<T>& assign(T const a, T const b, T const c)
257 { x = a; y = b; z = c; return *this; }
259 // Comparison
260 inline bool operator==(Vector3<T> const & v2) const
261 { return ((x == v2.x) && (y == v2.y) && (z == v2.z)); }
262 inline bool operator!=(Vector3<T> const & v2) const
263 { return ! (*this == v2); }
265 // Vector addition
266 inline Vector3<T>& operator+=(Vector3<T> const & v2)
267 { x += v2.x; y += v2.y; z += v2.z; return *this; }
268 inline Vector3<T> operator+(Vector3<T> const & v2) const
269 { return Vector3<T>(*this) += v2; }
271 // Vector subtraction
272 inline Vector3<T>& operator-=(Vector3<T> const & v2)
273 { x -= v2.x; y -= v2.y; z -= v2.z; return *this; }
274 inline Vector3<T> operator-(Vector3<T> const & v2) const
275 { return Vector3<T>(*this) -= v2; }
277 // Scalar multiplication
278 inline Vector3<T>& operator*=(int const a)
279 { x *= a; y *= a; z *= a; return *this; }
280 inline Vector3<T>& operator*=(float const a)
281 { x *= a; y *= a; z *= a; return *this; }
282 inline Vector3<T>& operator*=(double const a)
283 { x *= a; y *= a; z *= a; return *this; }
285 inline Vector3<T> operator*(int const a) const
286 { return Vector3<T>(*this) *= a;}
287 inline Vector3<T> operator*(float const a) const
288 { return Vector3<T>(*this) *= a;}
289 inline Vector3<T> operator*(double const a) const
290 { return Vector3<T>(*this) *= a;}
292 // Scalar division
293 inline Vector3<T>& operator/=(int const a)
294 { assert(a!=0); x /= a; y /= a; z /= a; return *this; }
295 inline Vector3<T>& operator/=(float const a)
296 { assert(a!=0); x /= a; y /= a; z /= a; return *this; }
297 inline Vector3<T>& operator/=(double const a)
298 { assert(a!=0); x /= a; y /= a; z /= a; return *this; }
300 inline Vector3<T> operator/(int const a) const
301 { return Vector3<T>(*this) /= a;}
302 inline Vector3<T> operator/(float const a) const
303 { return Vector3<T>(*this) /= a;}
304 inline Vector3<T> operator/(double const a) const
305 { return Vector3<T>(*this) /= a;}
308 // methods
310 /** \brief Cross product of the vector with another Vector. Result returned in vres.
311 *
312 * The version that takes two arguments stores the result in the second
313 * argument. This may be faster since no temporary object is created
314 * during the operation.
315 */
316 inline Vector3<T>& cross(Vector3<T> const & v2, Vector3<T>& vres)
317 {
318 vres.x = y*v2.z - v2.y*z;
319 vres.y = -x*v2.z + v2.x*z;
320 vres.z = x*v2.y - v2.x*y;
321 return vres;
322 }
323 /** \brief Cross product of the vector with another Vector.
324 * \copydetails arda::Math::Vector3::cross */
325 inline Vector3<T> cross(Vector3<T> const & v2)
326 {
327 Vector3<T> vres;
328 vres.x = y*v2.z - v2.y*z;
329 vres.y = -x*v2.z + v2.x*z;
330 vres.z = x*v2.y - v2.x*y;
331 return vres;
332 }
334 /** \copydoc arda::Math::Vector2::dot */
335 inline T dot(Vector3<T> const & v2) const
336 { return x*v2.x + y*v2.y + z*v2.z; }
338 /** \copydoc arda::Math::Vector2::get_angle */
339 inline double get_angle(Vector3<T> const & v2)
340 {
341 double tmp = dot(v2);
342 return acos(sqrt(tmp*tmp/(dot(*this)*v2.dot(v2))));
343 }
345 /** \copydoc arda::Math::Vector2::get_anglen */
346 inline double get_anglen(Vector3<T> const & v2)
347 { return acos((double) dot(v2)); }
349 /** \copydoc arda::Math::Vector2::to_string */
350 std::string to_string(void) const;
352 /** \copydoc arda::Math::Vector2::length */
353 inline double length(void) const
354 { return sqrt((dot(*this))); }
356 /** \copydoc arda::Math::Vector2::normalize */
357 inline Vector3<T>& normalize()
358 { double l = length(); if (l == 0.0) return *this; x /= l; y /= l; z /= l; return *this; }
360 /** \copydoc arda::Math::Vector2::proj */
361 inline Vector3<T> proj(Vector3<T> const & v2)
362 { Vector3<T> vres; vres = v2 * dot(v2)/v2.dot(v2); return vres; }
363 /** \copybrief arda::Math::Vector2::proj
364 * Returns result in vres
365 */
366 inline Vector3<T>& proj(Vector3<T> const & v2, Vector3<T>& vres)
367 { vres = v2 * dot(v2)/v2.dot(v2); return vres; }
368 };
370 // Scalar multiplication, continued
371 template <typename T>
372 inline Vector3<T> operator*(int const a, Vector3<T> const & v)
373 { return Vector3<T>(v) *= a;}
375 template <typename T>
376 inline Vector3<T> operator*(float const a, Vector3<T> const & v)
377 { return Vector3<T>(v) *= a;}
379 template <typename T>
380 inline Vector3<T> operator*(double const a, Vector3<T> const & v)
381 { return Vector3<T>(v) *= a;}
383 /////////////////////////////////////////////////////////////////////////////
384 /** \class arda::Math::Vector4
385 * \copydoc arda::Math::Vector2
386 */
387 template <typename T>
388 class Vector4
389 {
390 public:
391 T x, y, z, w;
393 // Constructors
394 Vector4() {}
395 explicit Vector4(T a) : x (a), y(a), z(a), w(a) {}
396 Vector4(T a, T b, T c, T d) : x (a), y(b), z(c), w(d) {}
397 Vector4(Vector2<T> v) : x (v.x), y (v.y), z (0), w (0) {}
398 Vector4(Vector3<T> v) : x (v.x), y (v.y), z (v.z), w (0) {}
400 // Array indexing
401 inline T& operator[](unsigned int const i)
402 { assert (i<4); if (i==0) return x; if (i==1) return y; if (i==2) return z; return w; }
403 inline T operator[](unsigned int const i) const
404 { assert (i<4); if (i==0) return x; if (i==1) return y; if (i==2) return z; return w; }
406 // Assignment
407 inline Vector4<T>& operator=(Vector2<T> const & v2)
408 { x = v2.x; y = v2.y; z = T(0); w = T(0); return *this; }
409 inline Vector4<T>& operator=(Vector3<T> const & v2)
410 { x = v2.x; y = v2.y; z = v2.z; w = T(0); return *this; }
411 inline Vector4<T>& operator=(Vector4<T> const & v2)
412 { x = v2.x; y = v2.y; z = v2.z; w = v2.w; return *this; }
414 /** \copydoc arda::Math::Vector2::assign */
415 inline Vector4<T>& assign(T const a, T const b, T const c, T const d)
416 { x = a; y = b; z = c; w = d; return *this; }
418 // Comparison
419 inline bool operator==(Vector4<T> const & v2) const
420 { return ((x == v2.x) && (y == v2.y) && (z == v2.z) && (w == v2.w)); }
421 inline bool operator!=(Vector4<T> const & v2) const
422 { return ! (*this == v2); }
424 // Vector addition
425 inline Vector4<T>& operator+=(Vector4<T> const & v2)
426 { x += v2.x; y += v2.y; z += v2.z; w += v2.w; return *this; }
427 inline Vector4<T> operator+(Vector4<T> const & v2) const
428 { return Vector4<T>(*this) += v2; }
430 // Vector subtraction
431 inline Vector4<T>& operator-=(Vector4<T> const & v2)
432 { x -= v2.x; y -= v2.y; z -= v2.z; w -= v2.w; return *this; }
433 inline Vector4<T> operator-(Vector4<T> const & v2) const
434 { return Vector4<T>(*this) -= v2; }
436 // Scalar multiplication
437 inline Vector4<T>& operator*=(int const a)
438 { x *= a; y *= a; z *= a; w *= a; return *this; }
439 inline Vector4<T>& operator*=(float const a)
440 { x *= a; y *= a; z *= a; w *= a; return *this; }
441 inline Vector4<T>& operator*=(double const a)
442 { x *= a; y *= a; z *= a; w *= a; return *this; }
444 inline Vector4<T> operator*(int const a) const
445 { return Vector4<T>(*this) *= a;}
446 inline Vector4<T> operator*(float const a) const
447 { return Vector4<T>(*this) *= a;}
448 inline Vector4<T> operator*(double const a) const
449 { return Vector4<T>(*this) *= a;}
451 // Scalar division
452 inline Vector4<T>& operator/=(int const a)
453 { assert(a!=0); x /= a; y /= a; z /= a; w /= a; return *this; }
454 inline Vector4<T>& operator/=(float const a)
455 { assert(a!=0); x /= a; y /= a; z /= a; w /= a; return *this; }
456 inline Vector4<T>& operator/=(double const a)
457 { assert(a!=0); x /= a; y /= a; z /= a; w /= a; return *this; }
459 inline Vector4<T> operator/(int const a) const
460 { return Vector4<T>(*this) /= a;}
461 inline Vector4<T> operator/(float const a) const
462 { return Vector4<T>(*this) /= a;}
463 inline Vector4<T> operator/(double const a) const
464 { return Vector4<T>(*this) /= a;}
467 // methods
469 /** \copydoc arda::Math::Vector2::dot */
470 inline T dot(Vector4<T> const & v2) const
471 { return x*v2.x + y*v2.y + z*v2.z + w*v2.w; }
473 /** \copydoc arda::Math::Vector2::get_angle */
474 inline double get_angle(Vector4<T> const & v2)
475 {
476 double tmp = dot(v2);
477 return acos(sqrt(tmp*tmp/(dot(*this)*v2.dot(v2))));
478 }
480 /** \copydoc arda::Math::Vector2::get_anglen */
481 inline double get_anglen(Vector4<T> const & v2)
482 { return acos((double) dot(v2)); }
484 /** \copydoc arda::Math::Vector2::to_string */
485 std::string to_string(void) const;
487 /** \copydoc arda::Math::Vector2::length */
488 inline double length(void) const
489 { return sqrt((dot(*this))); }
491 /** \copydoc arda::Math::Vector2::normalize */
492 inline Vector4<T>& normalize()
493 { double l = length(); if (l == 0.0) return *this; x /= l; y /= l; z /= l; w /= l; return *this; }
495 /** \copydoc arda::Math::Vector2::proj */
496 inline Vector4<T> proj(Vector4<T> const & v2)
497 { Vector4<T> vres; vres = v2 * dot(v2)/v2.dot(v2); return vres; }
498 /** \copybrief arda::Math::Vector2::proj
499 * Returns result in vres
500 */
501 inline Vector4<T>& proj(Vector4<T> const & v2, Vector4<T>& vres)
502 { vres = v2 * dot(v2)/v2.dot(v2); return vres; }
503 };
505 // Scalar multiplication, continued
506 template <typename T>
507 inline Vector4<T> operator*(int const a, Vector4<T> const & v)
508 { return Vector4<T>(v) *= a;}
510 template <typename T>
511 inline Vector4<T> operator*(float const a, Vector4<T> const & v)
512 { return Vector4<T>(v) *= a;}
514 template <typename T>
515 inline Vector4<T> operator*(double const a, Vector4<T> const & v)
516 { return Vector4<T>(v) *= a;}
518 /////////////////////////////////////////////////////////////////////////////
520 typedef Vector2<int> Vector2i;
521 typedef Vector2<float> Vector2f;
522 typedef Vector2<double> Vector2d;
524 typedef Vector3<int> Vector3i;
525 typedef Vector3<float> Vector3f;
526 typedef Vector3<double> Vector3d;
528 typedef Vector4<int> Vector4i;
529 typedef Vector4<float> Vector4f;
530 typedef Vector4<double> Vector4d;
532 } // namespace Math
534 } // namespace arda
536 ////////////////////////////////////////////////////////////////////////////////
537 template <typename T>
538 std::string arda::Math::Vector2<T>::to_string(void) const
539 {
540 std::stringstream ss;
541 ss << "[ " << x << ", " << y << " ]";
542 return ss.str();
543 }
545 ////////////////////////////////////////////////////////////////////////////////
546 template <typename T>
547 std::string arda::Math::Vector3<T>::to_string(void) const
548 {
549 std::stringstream ss;
550 ss << "[ " << x << ", " << y << ", " << z << " ]";
551 return ss.str();
552 }
554 ////////////////////////////////////////////////////////////////////////////////
555 template <typename T>
556 std::string arda::Math::Vector4<T>::to_string(void) const
557 {
558 std::stringstream ss;
559 ss << "[ " << x << ", " << y << ", " << z << ", " << w << " ]";
560 return ss.str();
561 }
564 #endif // VECTOR_H_