view include/Vector.h @ 15:ea32c94fc495

General minor improvements. - Spelling corrections. - Made the top level constants like PI static. - Changed instances of literal 1 and 0 to T(1) and T(0)
author Eris Caffee <discordia@eldalin.com>
date Sun, 19 May 2013 20:17:16 -0500
parents e00321d11fe1
children f9fb659509e1
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 // Vectors
17 //
18 // Templated classes for 2, 3, and 4 dimensional vectors of any type,
19 // although these types are really intended to be int, float, and double
20 // only. (i.e. if you roll your own base type, it had better act like
21 // a numeric scalar.)
22 //
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 // assign(T a, T b [, T b [, T d]])
43 // Directly assign values to the vector.
44 // cross(Vector3& v2)
45 // cross(Vector3& v2, Vector3& vres)
46 // Cross product of the vector with v2. Only defined for Vector3 types.
47 // The version that takes two arguments stores the result in the second
48 // argument. This may be faster since no temporary object is created
49 // during the operation.
50 // dot(Vector& v2)
51 // The dot product of the vector with v2.
52 // get_angle(Vector& v2)
53 // Returns the angle (in radians) between the vector and v2.
54 // Not meaningful for int vectors.
55 // get_anglen(Vector& v2)
56 // Like get_angle(), but the vectors must already be normalized.
57 // Not meaningful for int vectors.
58 // to_string(std::string & s)
59 // Returns a C string representation of the vector.
60 // This is one of the few non-inline Vector functions.
61 // length()
62 // Get the length of a vector.
63 // Returns a double for all vector types.
64 // normalize()
65 // Normalizes the vector.
66 // Not meaningful for int vectors.
67 // proj(Vector& v2, Vector& vres)
68 // Calculates the projection of the vector onto v2 and returns the result
69 // in vres.
70 // Not meaningful for int vectors.
71 // Returns vres.
72 //
73 //
74 // Note that the following typedefs are defined for convenience:
75 //
76 // typedef Vector2<int> Vector2i;
77 // typedef Vector2<float> Vector2f;
78 // typedef Vector2<double> Vector2d;
79 // typedef Vector3<int> Vector3i;
80 // typedef Vector3<float> Vector3f;
81 // typedef Vector3<double> Vector3d;
82 // typedef Vector4<int> Vector4i;
83 // typedef Vector4<float> Vector4f;
84 // typedef Vector4<double> Vector4d;
85 //
86 //
87 //
88 // Scalar multiplication and division are overloaded. Why?
89 // I'm not sure I need this. The idea is to support all likely scalar
90 // types without having to rely on implicit or explicit type conversion,
91 // especially not a conversion that might result in loss of precision.
92 // Multiplying a float Vector by a double scalar, for example.
93 //
94 // Is there a better way to do this? Am I worrying about nothing?
95 //
96 //
97 //
98 // I suppose I could make this into a single Vector template on two parameters
99 // template <typename T, unsigned int N> class Vector
100 // {
101 // T v[N];
102 //
103 // etc...
104 //
105 // This might buy perfect generality, but it would come at the expense of
106 // loops in all of the code, so I don't think it would really be worth it.
109 /////////////////////////////////////////////////////////////////////////////
110 template <typename T>
111 class Vector2
112 {
113 public:
114 T x, y;
116 // Constructors
117 Vector2() {}
118 explicit Vector2(T a) : x (a), y(a) {}
119 Vector2(T a, T b) : x (a), y(b) {}
121 // Array indexing
122 inline T& operator[](unsigned int const i)
123 { assert (i<2); if (i==0) return x; return y; }
124 inline T operator[](unsigned int const i) const
125 { assert (i<2); if (i==0) return x; return y; }
127 // Assignment
128 inline Vector2<T>& operator=(Vector2<T> const & v2)
129 { x = v2.x; y = v2.y; return *this; }
130 inline Vector2<T>& assign(T const a, T const b)
131 { x = a; y = b; return *this; }
133 // Comparison
134 inline bool operator==(Vector2<T> const & v2) const
135 { return ((x == v2.x) && (y == v2.y)); }
136 inline bool operator!=(Vector2<T> const & v2) const
137 { return ! (*this == v2); }
139 // Vector addition
140 inline Vector2<T>& operator+=(Vector2<T> const & v2)
141 { x += v2.x; y += v2.y; return *this; }
142 inline Vector2<T> operator+(Vector2<T> const & v2) const
143 { return Vector2<T>(*this) += v2; }
145 // Vector subtraction
146 inline Vector2<T>& operator-=(Vector2<T> const & v2)
147 { x -= v2.x; y -= v2.y; return *this; }
148 inline Vector2<T> operator-(Vector2<T> const & v2) const
149 { return Vector2<T>(*this) -= v2; }
151 // Scalar multiplication
152 inline Vector2<T>& operator*=(int const a)
153 { x *= a; y *= a; return *this; }
154 inline Vector2<T>& operator*=(float const a)
155 { x *= a; y *= a; return *this; }
156 inline Vector2<T>& operator*=(double const a)
157 { x *= a; y *= a; return *this; }
159 inline Vector2<T> operator*(int const a) const
160 { return Vector2<T>(*this) *= a;}
161 inline Vector2<T> operator*(float const a) const
162 { return Vector2<T>(*this) *= a;}
163 inline Vector2<T> operator*(double const a) const
164 { return Vector2<T>(*this) *= a;}
166 // Scalar division
167 inline Vector2<T>& operator/=(int const a)
168 { assert(a!=0); x /= a; y /= a; return *this; }
169 inline Vector2<T>& operator/=(float const a)
170 { assert(a!=0); x /= a; y /= a; return *this; }
171 inline Vector2<T>& operator/=(double const a)
172 { assert(a!=0); x /= a; y /= a; return *this; }
174 inline Vector2<T> operator/(int const a) const
175 { return Vector2<T>(*this) /= a;}
176 inline Vector2<T> operator/(float const a) const
177 { return Vector2<T>(*this) /= a;}
178 inline Vector2<T> operator/(double const a) const
179 { return Vector2<T>(*this) /= a;}
182 // methods
184 inline T dot(Vector2<T> const & v2) const
185 { return x*v2.x + y*v2.y; }
187 inline double get_angle(Vector2<T> const & v2)
188 {
189 double tmp = dot(v2);
190 return acos(sqrt(tmp*tmp/(dot(*this)*v2.dot(v2))));
191 }
193 inline double get_anglen(Vector2<T> const & v2)
194 { return acos((double) dot(v2)); }
196 std::string to_string(void) const;
198 inline double length(void) const
199 { return sqrt((dot(*this))); }
201 inline Vector2<T>& normalize()
202 {
203 double l = length();
204 if (l == 0.0) return *this;
205 x /= l; y /= l;
206 return *this; }
208 inline Vector2<T> proj(Vector2<T> const & v2)
209 { Vector2<T> vres; vres = v2 * (dot(v2)/v2.dot(v2)); return vres; }
210 inline Vector2<T>& proj(Vector2<T> const & v2, Vector2<T>& vres)
211 { vres = v2 * dot(v2)/v2.dot(v2); return vres; }
212 };
214 // Scalar multiplication, continued
215 template <typename T>
216 inline Vector2<T> operator*(int const a, Vector2<T> const & v)
217 { return Vector2<T>(v) *= a;}
219 template <typename T>
220 inline Vector2<T> operator*(float const a, Vector2<T> const & v)
221 { return Vector2<T>(v) *= a;}
223 template <typename T>
224 inline Vector2<T> operator*(double const a, Vector2<T> const & v)
225 { return Vector2<T>(v) *= a;}
228 /////////////////////////////////////////////////////////////////////////////
229 template <typename T>
230 class Vector3
231 {
232 public:
233 T x, y, z;
235 // Constructors
236 Vector3() {}
237 explicit Vector3(T a) : x (a), y(a), z(a) {}
238 Vector3(T a, T b, T c) : x (a), y(b), z(c) {}
239 Vector3(Vector2<T> v) : x (v.x), y (v.y), z (0) {}
241 // Array indexing
242 inline T& operator[](unsigned int const i)
243 { assert (i<3); if (i==0) return x; if (i==1) return y; return z; }
244 inline T operator[](unsigned int const i) const
245 { assert (i<3); if (i==0) return x; if (i==1) return y; return z; }
247 // Assignment
248 inline Vector3<T>& operator=(Vector2<T> const & v2)
249 { x = v2.x; y = v2.y; z = T(0); return *this; }
250 inline Vector3<T>& operator=(Vector3<T> const & v2)
251 { x = v2.x; y = v2.y; z = v2.z; return *this; }
253 inline Vector3<T>& assign(T const a, T const b, T const c)
254 { x = a; y = b; z = c; return *this; }
256 // Comparison
257 inline bool operator==(Vector3<T> const & v2) const
258 { return ((x == v2.x) && (y == v2.y) && (z == v2.z)); }
259 inline bool operator!=(Vector3<T> const & v2) const
260 { return ! (*this == v2); }
262 // Vector addition
263 inline Vector3<T>& operator+=(Vector3<T> const & v2)
264 { x += v2.x; y += v2.y; z += v2.z; return *this; }
265 inline Vector3<T> operator+(Vector3<T> const & v2) const
266 { return Vector3<T>(*this) += v2; }
268 // Vector subtraction
269 inline Vector3<T>& operator-=(Vector3<T> const & v2)
270 { x -= v2.x; y -= v2.y; z -= v2.z; return *this; }
271 inline Vector3<T> operator-(Vector3<T> const & v2) const
272 { return Vector3<T>(*this) -= v2; }
274 // Scalar multiplication
275 inline Vector3<T>& operator*=(int const a)
276 { x *= a; y *= a; z *= a; return *this; }
277 inline Vector3<T>& operator*=(float const a)
278 { x *= a; y *= a; z *= a; return *this; }
279 inline Vector3<T>& operator*=(double const a)
280 { x *= a; y *= a; z *= a; return *this; }
282 inline Vector3<T> operator*(int const a) const
283 { return Vector3<T>(*this) *= a;}
284 inline Vector3<T> operator*(float const a) const
285 { return Vector3<T>(*this) *= a;}
286 inline Vector3<T> operator*(double const a) const
287 { return Vector3<T>(*this) *= a;}
289 // Scalar division
290 inline Vector3<T>& operator/=(int const a)
291 { assert(a!=0); x /= a; y /= a; z /= a; return *this; }
292 inline Vector3<T>& operator/=(float const a)
293 { assert(a!=0); x /= a; y /= a; z /= a; return *this; }
294 inline Vector3<T>& operator/=(double const a)
295 { assert(a!=0); x /= a; y /= a; z /= a; return *this; }
297 inline Vector3<T> operator/(int const a) const
298 { return Vector3<T>(*this) /= a;}
299 inline Vector3<T> operator/(float const a) const
300 { return Vector3<T>(*this) /= a;}
301 inline Vector3<T> operator/(double const a) const
302 { return Vector3<T>(*this) /= a;}
305 // methods
307 inline Vector3<T>& cross(Vector3<T> const & v2, Vector3<T>& vres)
308 {
309 vres.x = y*v2.z - v2.y*z;
310 vres.y = -x*v2.z + v2.x*z;
311 vres.z = x*v2.y - v2.x*y;
312 return vres;
313 }
314 inline Vector3<T> cross(Vector3<T> const & v2)
315 {
316 Vector3<T> vres;
317 vres.x = y*v2.z - v2.y*z;
318 vres.y = -x*v2.z + v2.x*z;
319 vres.z = x*v2.y - v2.x*y;
320 return vres;
321 }
323 inline T dot(Vector3<T> const & v2) const
324 { return x*v2.x + y*v2.y + z*v2.z; }
326 inline double get_angle(Vector3<T> const & v2)
327 {
328 double tmp = dot(v2);
329 return acos(sqrt(tmp*tmp/(dot(*this)*v2.dot(v2))));
330 }
332 inline double get_anglen(Vector3<T> const & v2)
333 { return acos((double) dot(v2)); }
335 std::string to_string(void) const;
337 inline double length(void) const
338 { return sqrt((dot(*this))); }
340 inline Vector3<T>& normalize()
341 { double l = length(); if (l == 0.0) return *this; x /= l; y /= l; z /= l; return *this; }
343 inline Vector3<T> proj(Vector3<T> const & v2)
344 { Vector3<T> vres; vres = v2 * dot(v2)/v2.dot(v2); return vres; }
345 inline Vector3<T>& proj(Vector3<T> const & v2, Vector3<T>& vres)
346 { vres = v2 * dot(v2)/v2.dot(v2); return vres; }
347 };
349 // Scalar multiplication, continued
350 template <typename T>
351 inline Vector3<T> operator*(int const a, Vector3<T> const & v)
352 { return Vector3<T>(v) *= a;}
354 template <typename T>
355 inline Vector3<T> operator*(float const a, Vector3<T> const & v)
356 { return Vector3<T>(v) *= a;}
358 template <typename T>
359 inline Vector3<T> operator*(double const a, Vector3<T> const & v)
360 { return Vector3<T>(v) *= a;}
362 /////////////////////////////////////////////////////////////////////////////
363 template <typename T>
364 class Vector4
365 {
366 public:
367 T x, y, z, w;
369 // Constructors
370 Vector4() {}
371 explicit Vector4(T a) : x (a), y(a), z(a), w(a) {}
372 Vector4(T a, T b, T c, T d) : x (a), y(b), z(c), w(d) {}
373 Vector4(Vector2<T> v) : x (v.x), y (v.y), z (0), w (0) {}
374 Vector4(Vector3<T> v) : x (v.x), y (v.y), z (v.z), w (0) {}
376 // Array indexing
377 inline T& operator[](unsigned int const i)
378 { assert (i<4); if (i==0) return x; if (i==1) return y; if (i==2) return z; return w; }
379 inline T operator[](unsigned int const i) const
380 { assert (i<4); if (i==0) return x; if (i==1) return y; if (i==2) return z; return w; }
382 // Assignment
383 inline Vector4<T>& operator=(Vector2<T> const & v2)
384 { x = v2.x; y = v2.y; z = T(0); w = T(0); return *this; }
385 inline Vector4<T>& operator=(Vector3<T> const & v2)
386 { x = v2.x; y = v2.y; z = v2.z; w = T(0); return *this; }
387 inline Vector4<T>& operator=(Vector4<T> const & v2)
388 { x = v2.x; y = v2.y; z = v2.z; w = v2.w; return *this; }
390 inline Vector4<T>& assign(T const a, T const b, T const c, T const d)
391 { x = a; y = b; z = c; w = d; return *this; }
393 // Comparison
394 inline bool operator==(Vector4<T> const & v2) const
395 { return ((x == v2.x) && (y == v2.y) && (z == v2.z) && (w == v2.w)); }
396 inline bool operator!=(Vector4<T> const & v2) const
397 { return ! (*this == v2); }
399 // Vector addition
400 inline Vector4<T>& operator+=(Vector4<T> const & v2)
401 { x += v2.x; y += v2.y; z += v2.z; w += v2.w; return *this; }
402 inline Vector4<T> operator+(Vector4<T> const & v2) const
403 { return Vector4<T>(*this) += v2; }
405 // Vector subtraction
406 inline Vector4<T>& operator-=(Vector4<T> const & v2)
407 { x -= v2.x; y -= v2.y; z -= v2.z; w -= v2.w; return *this; }
408 inline Vector4<T> operator-(Vector4<T> const & v2) const
409 { return Vector4<T>(*this) -= v2; }
411 // Scalar multiplication
412 inline Vector4<T>& operator*=(int const a)
413 { x *= a; y *= a; z *= a; w *= a; return *this; }
414 inline Vector4<T>& operator*=(float const a)
415 { x *= a; y *= a; z *= a; w *= a; return *this; }
416 inline Vector4<T>& operator*=(double const a)
417 { x *= a; y *= a; z *= a; w *= a; return *this; }
419 inline Vector4<T> operator*(int const a) const
420 { return Vector4<T>(*this) *= a;}
421 inline Vector4<T> operator*(float const a) const
422 { return Vector4<T>(*this) *= a;}
423 inline Vector4<T> operator*(double const a) const
424 { return Vector4<T>(*this) *= a;}
426 // Scalar division
427 inline Vector4<T>& operator/=(int const a)
428 { assert(a!=0); x /= a; y /= a; z /= a; w /= a; return *this; }
429 inline Vector4<T>& operator/=(float const a)
430 { assert(a!=0); x /= a; y /= a; z /= a; w /= a; return *this; }
431 inline Vector4<T>& operator/=(double const a)
432 { assert(a!=0); x /= a; y /= a; z /= a; w /= a; return *this; }
434 inline Vector4<T> operator/(int const a) const
435 { return Vector4<T>(*this) /= a;}
436 inline Vector4<T> operator/(float const a) const
437 { return Vector4<T>(*this) /= a;}
438 inline Vector4<T> operator/(double const a) const
439 { return Vector4<T>(*this) /= a;}
442 // methods
444 inline T dot(Vector4<T> const & v2) const
445 { return x*v2.x + y*v2.y + z*v2.z + w*v2.w; }
447 inline double get_angle(Vector4<T> const & v2)
448 {
449 double tmp = dot(v2);
450 return acos(sqrt(tmp*tmp/(dot(*this)*v2.dot(v2))));
451 }
453 inline double get_anglen(Vector4<T> const & v2)
454 { return acos((double) dot(v2)); }
456 std::string to_string(void) const;
458 inline double length(void) const
459 { return sqrt((dot(*this))); }
461 inline Vector4<T>& normalize()
462 { double l = length(); if (l == 0.0) return *this; x /= l; y /= l; z /= l; w /= l; return *this; }
464 inline Vector4<T> proj(Vector4<T> const & v2)
465 { Vector4<T> vres; vres = v2 * dot(v2)/v2.dot(v2); return vres; }
466 inline Vector4<T>& proj(Vector4<T> const & v2, Vector4<T>& vres)
467 { vres = v2 * dot(v2)/v2.dot(v2); return vres; }
468 };
470 // Scalar multiplication, continued
471 template <typename T>
472 inline Vector4<T> operator*(int const a, Vector4<T> const & v)
473 { return Vector4<T>(v) *= a;}
475 template <typename T>
476 inline Vector4<T> operator*(float const a, Vector4<T> const & v)
477 { return Vector4<T>(v) *= a;}
479 template <typename T>
480 inline Vector4<T> operator*(double const a, Vector4<T> const & v)
481 { return Vector4<T>(v) *= a;}
483 /////////////////////////////////////////////////////////////////////////////
485 typedef Vector2<int> Vector2i;
486 typedef Vector2<float> Vector2f;
487 typedef Vector2<double> Vector2d;
489 typedef Vector3<int> Vector3i;
490 typedef Vector3<float> Vector3f;
491 typedef Vector3<double> Vector3d;
493 typedef Vector4<int> Vector4i;
494 typedef Vector4<float> Vector4f;
495 typedef Vector4<double> Vector4d;
497 } // namespace Math
499 } // namespace arda
501 ////////////////////////////////////////////////////////////////////////////////
502 template <typename T>
503 std::string arda::Math::Vector2<T>::to_string(void) const
504 {
505 std::stringstream ss;
506 ss << "[ " << x << ", " << y << " ]";
507 return ss.str();
508 }
510 ////////////////////////////////////////////////////////////////////////////////
511 template <typename T>
512 std::string arda::Math::Vector3<T>::to_string(void) const
513 {
514 std::stringstream ss;
515 ss << "[ " << x << ", " << y << ", " << z << " ]";
516 return ss.str();
517 }
519 ////////////////////////////////////////////////////////////////////////////////
520 template <typename T>
521 std::string arda::Math::Vector4<T>::to_string(void) const
522 {
523 std::stringstream ss;
524 ss << "[ " << x << ", " << y << ", " << z << ", " << w << " ]";
525 return ss.str();
526 }
529 #endif // VECTOR_H_