view include/Vector.h @ 13:e00321d11fe1

to_string simplified. Added Vector constructors from smaller vectors. Added rotation and transform matrix calculation functions.
author Eris Caffee <discordia@eldalin.com>
date Wed, 08 May 2013 22:50:09 -0500
parents 1d2b25d4517f
children ea32c94fc495
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 // * *= / /=
36 // Defined for scalar multiplication/division with int, float, and double.
37 // * is defined as a standalone template operator for the scalar * Vector form.
38 // assign(T a, T b [, T b [, T d]])
39 // Directly assign values to the vector.
40 // cross(Vector3& v2)
41 // cross(Vector3& v2, Vector3& vres)
42 // Cross product of the vector with v2. Only defined for Vector3 types.
43 // The version that takes two arguments stores the result in the second
44 // argument. This may be faster since no temporary object is created
45 // during the operation.
46 // dot(Vector& v2)
47 // The dot product of the vector with v2.
48 // get_angle(Vector& v2)
49 // Returns the angle (in radians) between the vector and v2.
50 // Not meaningful for int vectors.
51 // get_anglen(Vector& v2)
52 // Like get_angle(), but the vectors must already be normalized.
53 // Not meaningful for int vectors.
54 // to_string(std::string & s)
55 // Returns a C string representation of the vector.
56 // This is one of the few non-inline Vector functions.
57 // length()
58 // Get the length of a vector.
59 // Returns a double for all vector types.
60 // normalize()
61 // Normalizes the vector.
62 // Not meaningful for int vectors.
63 // proj(Vector& v2, Vector& vres)
64 // Calculates the projection of the vector onto v2 and returns the result
65 // in vres.
66 // Not meaningful for int vectors.
67 // Returns vres.
68 //
69 //
70 // Note that the following typedefs are defined for convenience:
71 //
72 // typedef Vector2<int> Vector2i;
73 // typedef Vector2<float> Vector2f;
74 // typedef Vector2<double> Vector2d;
75 // typedef Vector3<int> Vector3i;
76 // typedef Vector3<float> Vector3f;
77 // typedef Vector3<double> Vector3d;
78 // typedef Vector4<int> Vector4i;
79 // typedef Vector4<float> Vector4f;
80 // typedef Vector4<double> Vector4d;
81 //
82 //
83 //
84 // Scalar multiplication and division are overloaded. Why?
85 // I'm not sure I need this. The idea is to support all likely scalar
86 // types without having to rely on implicit or explicit type conversion,
87 // especially not a conversion that might result in loss of precision.
88 // Multiplying a float Vector by a double scalar, for example.
89 //
90 // Is there a better way to do this? Am I worrying about nothing?
91 //
92 //
93 //
94 // I suppose I could make this into a single Vector template on two parameters
95 // template <typename T, unsigned int N> class Vector
96 // {
97 // T v[N];
98 //
99 // etc...
100 //
101 // This might buy perfect generality, but it would come at the expense of
102 // loops in all of the code, so I don't think it would really be worth it.
105 /////////////////////////////////////////////////////////////////////////////
106 template <typename T>
107 class Vector2
108 {
109 public:
110 T x, y;
112 // Constructors
113 Vector2() {}
114 explicit Vector2(T a) : x (a), y(a) {}
115 Vector2(T a, T b) : x (a), y(b) {}
117 // Array indexing
118 inline T& operator[](unsigned int const i)
119 { assert (i<2); if (i==0) return x; return y; }
120 inline T operator[](unsigned int const i) const
121 { assert (i<2); if (i==0) return x; return y; }
123 // Assignment
124 inline Vector2<T>& operator=(Vector2<T> const & v2)
125 { x = v2.x; y = v2.y; return *this; }
126 inline Vector2<T>& assign(T const a, T const b)
127 { x = a; y = b; return *this; }
129 // Comparison
130 inline bool operator==(Vector2<T> const & v2) const
131 { return ((x == v2.x) && (y == v2.y)); }
132 inline bool operator!=(Vector2<T> const & v2) const
133 { return ! (*this == v2); }
135 // Vector addition
136 inline Vector2<T>& operator+=(Vector2<T> const & v2)
137 { x += v2.x; y += v2.y; return *this; }
138 inline Vector2<T> operator+(Vector2<T> const & v2) const
139 { return Vector2<T>(*this) += v2; }
141 // Vector subtraction
142 inline Vector2<T>& operator-=(Vector2<T> const & v2)
143 { x -= v2.x; y -= v2.y; return *this; }
144 inline Vector2<T> operator-(Vector2<T> const & v2) const
145 { return Vector2<T>(*this) -= v2; }
147 // Scalar multiplication
148 inline Vector2<T>& operator*=(int const a)
149 { x *= a; y *= a; return *this; }
150 inline Vector2<T>& operator*=(float const a)
151 { x *= a; y *= a; return *this; }
152 inline Vector2<T>& operator*=(double const a)
153 { x *= a; y *= a; return *this; }
155 inline Vector2<T> operator*(int const a) const
156 { return Vector2<T>(*this) *= a;}
157 inline Vector2<T> operator*(float const a) const
158 { return Vector2<T>(*this) *= a;}
159 inline Vector2<T> operator*(double const a) const
160 { return Vector2<T>(*this) *= a;}
162 // Scalar division
163 inline Vector2<T>& operator/=(int const a)
164 { assert(a!=0); x /= a; y /= a; return *this; }
165 inline Vector2<T>& operator/=(float const a)
166 { assert(a!=0); x /= a; y /= a; return *this; }
167 inline Vector2<T>& operator/=(double const a)
168 { assert(a!=0); x /= a; y /= a; return *this; }
170 inline Vector2<T> operator/(int const a) const
171 { return Vector2<T>(*this) /= a;}
172 inline Vector2<T> operator/(float const a) const
173 { return Vector2<T>(*this) /= a;}
174 inline Vector2<T> operator/(double const a) const
175 { return Vector2<T>(*this) /= a;}
178 // methods
180 inline T dot(Vector2<T> const & v2) const
181 { return x*v2.x + y*v2.y; }
183 inline double get_angle(Vector2<T> const & v2)
184 {
185 double tmp = dot(v2);
186 return acos(sqrt(tmp*tmp/(dot(*this)*v2.dot(v2))));
187 }
189 inline double get_anglen(Vector2<T> const & v2)
190 { return acos((double) dot(v2)); }
192 std::string to_string(void) const;
194 inline double length(void) const
195 { return sqrt((dot(*this))); }
197 inline Vector2<T>& normalize()
198 {
199 double l = length();
200 if (l == 0.0) return *this;
201 x /= l; y /= l;
202 return *this; }
204 inline Vector2<T> proj(Vector2<T> const & v2)
205 { Vector2<T> vres; vres = v2 * (dot(v2)/v2.dot(v2)); return vres; }
206 inline Vector2<T>& proj(Vector2<T> const & v2, Vector2<T>& vres)
207 { vres = v2 * dot(v2)/v2.dot(v2); return vres; }
208 };
210 // Scalar multiplication, continued
211 template <typename T>
212 inline Vector2<T> operator*(int const a, Vector2<T> const & v)
213 { return Vector2<T>(v) *= a;}
215 template <typename T>
216 inline Vector2<T> operator*(float const a, Vector2<T> const & v)
217 { return Vector2<T>(v) *= a;}
219 template <typename T>
220 inline Vector2<T> operator*(double const a, Vector2<T> const & v)
221 { return Vector2<T>(v) *= a;}
224 /////////////////////////////////////////////////////////////////////////////
225 template <typename T>
226 class Vector3
227 {
228 public:
229 T x, y, z;
231 // Constructors
232 Vector3() {}
233 explicit Vector3(T a) : x (a), y(a), z(a) {}
234 Vector3(T a, T b, T c) : x (a), y(b), z(c) {}
235 Vector3(Vector2<T> v) : x (v.x), y (v.y), z (0) {}
237 // Array indexing
238 inline T& operator[](unsigned int const i)
239 { assert (i<3); if (i==0) return x; if (i==1) return y; return z; }
240 inline T operator[](unsigned int const i) const
241 { assert (i<3); if (i==0) return x; if (i==1) return y; return z; }
243 // Assignment
244 inline Vector3<T>& operator=(Vector2<T> const & v2)
245 { x = v2.x; y = v2.y; z = 0; return *this; }
246 inline Vector3<T>& operator=(Vector3<T> const & v2)
247 { x = v2.x; y = v2.y; z = v2.z; return *this; }
249 inline Vector3<T>& assign(T const a, T const b, T const c)
250 { x = a; y = b; z = c; return *this; }
252 // Comparison
253 inline bool operator==(Vector3<T> const & v2) const
254 { return ((x == v2.x) && (y == v2.y) && (z == v2.z)); }
255 inline bool operator!=(Vector3<T> const & v2) const
256 { return ! (*this == v2); }
258 // Vector addition
259 inline Vector3<T>& operator+=(Vector3<T> const & v2)
260 { x += v2.x; y += v2.y; z += v2.z; return *this; }
261 inline Vector3<T> operator+(Vector3<T> const & v2) const
262 { return Vector3<T>(*this) += v2; }
264 // Vector subtraction
265 inline Vector3<T>& operator-=(Vector3<T> const & v2)
266 { x -= v2.x; y -= v2.y; z -= v2.z; return *this; }
267 inline Vector3<T> operator-(Vector3<T> const & v2) const
268 { return Vector3<T>(*this) -= v2; }
270 // Scalar multiplication
271 inline Vector3<T>& operator*=(int const a)
272 { x *= a; y *= a; z *= a; return *this; }
273 inline Vector3<T>& operator*=(float const a)
274 { x *= a; y *= a; z *= a; return *this; }
275 inline Vector3<T>& operator*=(double const a)
276 { x *= a; y *= a; z *= a; return *this; }
278 inline Vector3<T> operator*(int const a) const
279 { return Vector3<T>(*this) *= a;}
280 inline Vector3<T> operator*(float const a) const
281 { return Vector3<T>(*this) *= a;}
282 inline Vector3<T> operator*(double const a) const
283 { return Vector3<T>(*this) *= a;}
285 // Scalar division
286 inline Vector3<T>& operator/=(int const a)
287 { assert(a!=0); x /= a; y /= a; z /= a; return *this; }
288 inline Vector3<T>& operator/=(float const a)
289 { assert(a!=0); x /= a; y /= a; z /= a; return *this; }
290 inline Vector3<T>& operator/=(double const a)
291 { assert(a!=0); x /= a; y /= a; z /= a; return *this; }
293 inline Vector3<T> operator/(int const a) const
294 { return Vector3<T>(*this) /= a;}
295 inline Vector3<T> operator/(float const a) const
296 { return Vector3<T>(*this) /= a;}
297 inline Vector3<T> operator/(double const a) const
298 { return Vector3<T>(*this) /= a;}
301 // methods
303 inline Vector3<T>& cross(Vector3<T> const & v2, Vector3<T>& vres)
304 {
305 vres.x = y*v2.z - v2.y*z;
306 vres.y = -x*v2.z + v2.x*z;
307 vres.z = x*v2.y - v2.x*y;
308 return vres;
309 }
310 inline Vector3<T> cross(Vector3<T> const & v2)
311 {
312 Vector3<T> vres;
313 vres.x = y*v2.z - v2.y*z;
314 vres.y = -x*v2.z + v2.x*z;
315 vres.z = x*v2.y - v2.x*y;
316 return vres;
317 }
319 inline T dot(Vector3<T> const & v2) const
320 { return x*v2.x + y*v2.y + z*v2.z; }
322 inline double get_angle(Vector3<T> const & v2)
323 {
324 double tmp = dot(v2);
325 return acos(sqrt(tmp*tmp/(dot(*this)*v2.dot(v2))));
326 }
328 inline double get_anglen(Vector3<T> const & v2)
329 { return acos((double) dot(v2)); }
331 std::string to_string(void) const;
333 inline double length(void) const
334 { return sqrt((dot(*this))); }
336 inline Vector3<T>& normalize()
337 { double l = length(); if (l == 0.0) return *this; x /= l; y /= l; z /= l; return *this; }
339 inline Vector3<T> proj(Vector3<T> const & v2)
340 { Vector3<T> vres; vres = v2 * dot(v2)/v2.dot(v2); return vres; }
341 inline Vector3<T>& proj(Vector3<T> const & v2, Vector3<T>& vres)
342 { vres = v2 * dot(v2)/v2.dot(v2); return vres; }
343 };
345 // Scalar multiplication, continued
346 template <typename T>
347 inline Vector3<T> operator*(int const a, Vector3<T> const & v)
348 { return Vector3<T>(v) *= a;}
350 template <typename T>
351 inline Vector3<T> operator*(float const a, Vector3<T> const & v)
352 { return Vector3<T>(v) *= a;}
354 template <typename T>
355 inline Vector3<T> operator*(double const a, Vector3<T> const & v)
356 { return Vector3<T>(v) *= a;}
358 /////////////////////////////////////////////////////////////////////////////
359 template <typename T>
360 class Vector4
361 {
362 public:
363 T x, y, z, w;
365 // Constructors
366 Vector4() {}
367 explicit Vector4(T a) : x (a), y(a), z(a), w(a) {}
368 Vector4(T a, T b, T c, T d) : x (a), y(b), z(c), w(d) {}
369 Vector4(Vector2<T> v) : x (v.x), y (v.y), z (0), w (0) {}
370 Vector4(Vector3<T> v) : x (v.x), y (v.y), z (v.z), w (0) {}
372 // Array indexing
373 inline T& operator[](unsigned int const i)
374 { assert (i<4); if (i==0) return x; if (i==1) return y; if (i==2) return z; return w; }
375 inline T operator[](unsigned int const i) const
376 { assert (i<4); if (i==0) return x; if (i==1) return y; if (i==2) return z; return w; }
378 // Assignment
379 inline Vector4<T>& operator=(Vector2<T> const & v2)
380 { x = v2.x; y = v2.y; z = 0; w = 0; return *this; }
381 inline Vector4<T>& operator=(Vector3<T> const & v2)
382 { x = v2.x; y = v2.y; z = v2.z; w = 0; return *this; }
383 inline Vector4<T>& operator=(Vector4<T> const & v2)
384 { x = v2.x; y = v2.y; z = v2.z; w = v2.w; return *this; }
386 inline Vector4<T>& assign(T const a, T const b, T const c, T const d)
387 { x = a; y = b; z = c; w = d; return *this; }
389 // Comparison
390 inline bool operator==(Vector4<T> const & v2) const
391 { return ((x == v2.x) && (y == v2.y) && (z == v2.z) && (w == v2.w)); }
392 inline bool operator!=(Vector4<T> const & v2) const
393 { return ! (*this == v2); }
395 // Vector addition
396 inline Vector4<T>& operator+=(Vector4<T> const & v2)
397 { x += v2.x; y += v2.y; z += v2.z; w += v2.w; return *this; }
398 inline Vector4<T> operator+(Vector4<T> const & v2) const
399 { return Vector4<T>(*this) += v2; }
401 // Vector subtraction
402 inline Vector4<T>& operator-=(Vector4<T> const & v2)
403 { x -= v2.x; y -= v2.y; z -= v2.z; w -= v2.w; return *this; }
404 inline Vector4<T> operator-(Vector4<T> const & v2) const
405 { return Vector4<T>(*this) -= v2; }
407 // Scalar multiplication
408 inline Vector4<T>& operator*=(int const a)
409 { x *= a; y *= a; z *= a; w *= a; return *this; }
410 inline Vector4<T>& operator*=(float const a)
411 { x *= a; y *= a; z *= a; w *= a; return *this; }
412 inline Vector4<T>& operator*=(double const a)
413 { x *= a; y *= a; z *= a; w *= a; return *this; }
415 inline Vector4<T> operator*(int const a) const
416 { return Vector4<T>(*this) *= a;}
417 inline Vector4<T> operator*(float const a) const
418 { return Vector4<T>(*this) *= a;}
419 inline Vector4<T> operator*(double const a) const
420 { return Vector4<T>(*this) *= a;}
422 // Scalar division
423 inline Vector4<T>& operator/=(int const a)
424 { assert(a!=0); x /= a; y /= a; z /= a; w /= a; return *this; }
425 inline Vector4<T>& operator/=(float const a)
426 { assert(a!=0); x /= a; y /= a; z /= a; w /= a; return *this; }
427 inline Vector4<T>& operator/=(double const a)
428 { assert(a!=0); x /= a; y /= a; z /= a; w /= a; return *this; }
430 inline Vector4<T> operator/(int const a) const
431 { return Vector4<T>(*this) /= a;}
432 inline Vector4<T> operator/(float const a) const
433 { return Vector4<T>(*this) /= a;}
434 inline Vector4<T> operator/(double const a) const
435 { return Vector4<T>(*this) /= a;}
438 // methods
440 inline T dot(Vector4<T> const & v2) const
441 { return x*v2.x + y*v2.y + z*v2.z + w*v2.w; }
443 inline double get_angle(Vector4<T> const & v2)
444 {
445 double tmp = dot(v2);
446 return acos(sqrt(tmp*tmp/(dot(*this)*v2.dot(v2))));
447 }
449 inline double get_anglen(Vector4<T> const & v2)
450 { return acos((double) dot(v2)); }
452 std::string to_string(void) const;
454 inline double length(void) const
455 { return sqrt((dot(*this))); }
457 inline Vector4<T>& normalize()
458 { double l = length(); if (l == 0.0) return *this; x /= l; y /= l; z /= l; w /= l; return *this; }
460 inline Vector4<T> proj(Vector4<T> const & v2)
461 { Vector4<T> vres; vres = v2 * dot(v2)/v2.dot(v2); return vres; }
462 inline Vector4<T>& proj(Vector4<T> const & v2, Vector4<T>& vres)
463 { vres = v2 * dot(v2)/v2.dot(v2); return vres; }
464 };
466 // Scalar multiplication, continued
467 template <typename T>
468 inline Vector4<T> operator*(int const a, Vector4<T> const & v)
469 { return Vector4<T>(v) *= a;}
471 template <typename T>
472 inline Vector4<T> operator*(float const a, Vector4<T> const & v)
473 { return Vector4<T>(v) *= a;}
475 template <typename T>
476 inline Vector4<T> operator*(double const a, Vector4<T> const & v)
477 { return Vector4<T>(v) *= a;}
479 /////////////////////////////////////////////////////////////////////////////
481 typedef Vector2<int> Vector2i;
482 typedef Vector2<float> Vector2f;
483 typedef Vector2<double> Vector2d;
485 typedef Vector3<int> Vector3i;
486 typedef Vector3<float> Vector3f;
487 typedef Vector3<double> Vector3d;
489 typedef Vector4<int> Vector4i;
490 typedef Vector4<float> Vector4f;
491 typedef Vector4<double> Vector4d;
493 } // namespace Math
495 } // namespace arda
497 ////////////////////////////////////////////////////////////////////////////////
498 template <typename T>
499 std::string arda::Math::Vector2<T>::to_string(void) const
500 {
501 std::stringstream ss;
502 ss << "[ " << x << ", " << y << " ]";
503 return ss.str();
504 }
506 ////////////////////////////////////////////////////////////////////////////////
507 template <typename T>
508 std::string arda::Math::Vector3<T>::to_string(void) const
509 {
510 std::stringstream ss;
511 ss << "[ " << x << ", " << y << ", " << z << " ]";
512 return ss.str();
513 }
515 ////////////////////////////////////////////////////////////////////////////////
516 template <typename T>
517 std::string arda::Math::Vector4<T>::to_string(void) const
518 {
519 std::stringstream ss;
520 ss << "[ " << x << ", " << y << ", " << z << ", " << w << " ]";
521 return ss.str();
522 }
525 #endif // VECTOR_H_