view include/Vector.h @ 7:378862555189

Refactored Vectors into templated classes. Much nicer now.
author Eris Caffee <discordia@eldalin.com>
date Wed, 28 Sep 2011 12:48:42 -0500
parents 11e216148d1c
children 5377337c7de0
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 ////////////////////////////////////////////////////////////////////////////////
14 // Vectors
15 //
16 // Templated classes for 2, 3, and 4 dimensional vectors of any type,
17 // although these types are really intended to be int, float, and double
18 // only. (i.e. if you roll your own base type, it had better act like
19 // a numeric scalar.)
20 //
21 // Supported operations on vectors
22 //
23 // Construction
24 // Vector v; // Default zero vector.
25 // Vector v2(v); // Construct from other vector.
26 // T a, b;
27 // Vector v(a, b) // Construct from values.
28 // []
29 // If you have a Vector named v you can access it's member elements as
30 // v[0], v[1], v[2], and v[3]. in addtion to v.x, v.y, v.z, and v.w
31 // == != + += - -=
32 // Defined for operations on two vectors of the same type.
33 // * *= / /=
34 // Defined for scalar multiplication/division with int, float, and double.
35 // *= and /= are defined as member functions, but * and / are defined
36 // as standalone template operators so that I can support v*a as well as
37 // a*v order of multiplication.
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 // getstring(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 vecor.
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 // Scalar multiplication and division are overloaded. Why?
84 // I'm not sure I need this. The idea is to support all likely scalar
85 // types without having to rely on implicit or explicity type conversion,
86 // especially not a conversion that might result in loss of precision.
87 // Multiplying a float Vector by a double scala, for example.
88 // Is there a better way to do this?
92 /////////////////////////////////////////////////////////////////////////////
93 template <class T> class Vector2
94 {
95 public:
96 T x, y;
98 // Constructors
99 Vector2() : x (0), y(0) {}
100 Vector2(T a) : x (a), y(a) {}
101 Vector2(T a, T b) : x (a), y(b) {}
103 // Array indexing
104 inline T& operator[](unsigned int i)
105 { assert (i<2); if (i==0) return x; return y; }
106 inline const T& operator[](unsigned int i) const
107 { assert (i<2); if (i==0) return x; return y; }
109 // Assignment
110 inline Vector2<T>& operator=(const Vector2<T>& v2)
111 { x = v2.x; y = v2.y; return *this; }
112 inline Vector2<T>& assign(const T a, const T b)
113 { x = a; y = b; return *this; }
115 // Comparison
116 inline bool operator==(Vector2<T>& v2) const
117 { return ((x == v2.x) && (y == v2.y)); }
118 inline bool operator!=(Vector2<T>& v2) const
119 { return ! ((x == v2.x) && (y == v2.y)); }
121 // Vector addition
122 inline Vector2<T> operator+(const Vector2<T>& v2) const
123 { Vector2<T> vres; vres.x = x + v2.x; vres.y = y + v2.y; return vres; }
124 inline Vector2<T>& operator+=(const Vector2<T>& v2)
125 { x += v2.x; y += v2.y; return *this; }
127 // Vector subtraction
128 inline Vector2<T> operator-(const Vector2<T>& v2) const
129 { Vector2<T> vres; vres.x = x - v2.x; vres.y = y - v2.y; return vres; }
130 inline Vector2<T>& operator-=(const Vector2<T>& v2)
131 { x -= v2.x; y -= v2.y; return *this; }
133 // Scalar multiplication
134 inline Vector2<T>& operator*=(const int a)
135 { x *= a; y *= a; return *this; }
136 inline Vector2<T>& operator*=(const float a)
137 { x *= a; y *= a; return *this; }
138 inline Vector2<T>& operator*=(const double a)
139 { x *= a; y *= a; return *this; }
141 // Scalar division
142 inline Vector2<T>& operator/=(const int a)
143 { assert(a!=0); x /= a; y /= a; return *this; }
144 inline Vector2<T>& operator/=(const float a)
145 { assert(a!=0); x /= a; y /= a; return *this; }
146 inline Vector2<T>& operator/=(const double a)
147 { assert(a!=0); x /= a; y /= a; return *this; }
150 // methods
152 inline T dot(const Vector2<T>& v2) const
153 { return x*v2.x + y*v2.y; }
155 inline double get_angle(Vector2<T>& v2)
156 {
157 double tmp = dot(v2);
158 return acos(sqrt(tmp*tmp/(dot(*this)*v2.dot(v2))));
159 }
161 inline double get_anglen(Vector2<T>& v2)
162 { return acos((double) dot(v2)); }
164 std::string & getstring(std::string & s) const;
166 inline double length(void) const
167 { return sqrt((dot(*this))); }
169 inline Vector2<T>& normalize()
170 { double l = length(); if (l == 0.0) return *this; x /= l; y /= l; return *this; }
172 inline Vector2<T> proj(Vector2<T>& v2)
173 { Vector2<T> vres; vres = v2 * dot(v2)/v2.dot(v2); return vres; }
174 inline Vector2<T>& proj(Vector2<T>& v2, Vector2<T>& vres)
175 { vres = v2 * dot(v2)/v2.dot(v2); return vres; }
176 };
178 // Scalar multiplication, continued
179 template <class T> inline Vector2<T> operator*(const Vector2<T>& v, const int a)
180 { return Vector2<T>(v) *= a;}
181 template <class T> inline Vector2<T> operator*(const int a, const Vector2<T>& v)
182 { return Vector2<T>(v) *= a;}
183 template <class T> inline Vector2<T> operator*(const Vector2<T> v, const float a)
184 { return Vector2<T>(v) *= a;}
185 template <class T> inline Vector2<T> operator*(const float a, const Vector2<T> v)
186 { return Vector2<T>(v) *= a;}
187 template <class T> inline Vector2<T> operator*(const Vector2<T>& v, const double a)
188 { return Vector2<T>(v) *= a;}
189 template <class T> inline Vector2<T> operator*(const double a, const Vector2<T>& v)
190 { return Vector2<T>(v) *= a;}
192 // Scalar division, continued
193 template <class T> inline Vector2<T> operator/(const Vector2<T>& v, const int a)
194 { return Vector2<T>(v) /= a;}
195 template <class T> inline Vector2<T> operator/(const int a, const Vector2<T>& v)
196 { return Vector2<T>(v) /= a;}
197 template <class T> inline Vector2<T> operator/(const Vector2<T>& v, const float a)
198 { return Vector2<T>(v) /= a;}
199 template <class T> inline Vector2<T> operator/(const float a, const Vector2<T>& v)
200 { return Vector2<T>(v) /= a;}
201 template <class T> inline Vector2<T> operator/(const Vector2<T>& v, const double a)
202 { return Vector2<T>(v) /= a;}
203 template <class T> inline Vector2<T> operator/(const double a, const Vector2<T>& v)
204 { return Vector2<T>(v) /= a;}
206 /////////////////////////////////////////////////////////////////////////////
207 template <class T> class Vector3
208 {
209 public:
210 T x, y, z;
212 // Constructors
213 Vector3() : x (0), y(0), z(0) {}
214 Vector3(T a) : x (a), y(a), z(a) {}
215 Vector3(T a, T b, T c) : x (a), y(b), z(c) {}
217 // Array indexing
218 inline T& operator[](unsigned int i)
219 { assert (i<3); if (i==0) return x; if (i==1) return y; return z; }
220 inline const T& operator[](unsigned int i) const
221 { assert (i<3); if (i==0) return x; if (i==1) return y; return z; }
223 // Assignment
224 inline Vector3<T>& operator=(const Vector3<T>& v2)
225 { x = v2.x; y = v2.y; z = v2.z; return *this; }
226 inline Vector3<T>& assign(const T a, const T b, const T c)
227 { x = a; y = b; z = c; return *this; }
229 // Comparison
230 inline bool operator==(Vector3<T>& v2) const
231 { return ((x == v2.x) && (y == v2.y) && (z == v2.z)); }
232 inline bool operator!=(Vector3<T>& v2) const
233 { return ! ((x == v2.x) && (y == v2.y) && (z == v2.z)); }
235 // Vector addition
236 inline Vector3<T> operator+(const Vector3<T>& v2) const
237 { Vector3<T> vres; vres.x = x + v2.x; vres.y = y + v2.y; vres.z = z + v2.z; return vres; }
238 inline Vector3<T>& operator+=(const Vector3<T>& v2)
239 { x += v2.x; y += v2.y; z += v2.z; return *this; }
241 // Vector subtraction
242 inline Vector3<T> operator-(const Vector3<T>& v2) const
243 { Vector3<T> vres; vres.x = x - v2.x; vres.y = y - v2.y; vres.z = z - v2.z; return vres; }
244 inline Vector3<T>& operator-=(const Vector3<T>& v2)
245 { x -= v2.x; y -= v2.y; z -= v2.z; return *this; }
247 // Scalar multiplication
248 inline Vector3<T>& operator*=(const int a)
249 { x *= a; y *= a; z *= a; return *this; }
250 inline Vector3<T>& operator*=(const float a)
251 { x *= a; y *= a; z *= a; return *this; }
252 inline Vector3<T>& operator*=(const double a)
253 { x *= a; y *= a; z *= a; return *this; }
255 // Scalar division
256 inline Vector3<T>& operator/=(const int a)
257 { assert(a!=0); x /= a; y /= a; z /= a; return *this; }
258 inline Vector3<T>& operator/=(const float a)
259 { assert(a!=0); x /= a; y /= a; z /= a; return *this; }
260 inline Vector3<T>& operator/=(const double a)
261 { assert(a!=0); x /= a; y /= a; z /= a; return *this; }
264 // methods
266 inline Vector3<T>& cross(Vector3<T>& v2, Vector3<T>& vres)
267 {
268 vres.x = y*v2.z - v2.y*z;
269 vres.y = -x*v2.z + v2.x*z;
270 vres.z = x*v2.y - v2.x*y;
271 return vres;
272 }
273 inline Vector3<T> cross(Vector3<T>& v2)
274 {
275 Vector3<T> vres;
276 vres.x = y*v2.z - v2.y*z;
277 vres.y = -x*v2.z + v2.x*z;
278 vres.z = x*v2.y - v2.x*y;
279 return vres;
280 }
282 inline T dot(const Vector3<T>& v2) const
283 { return x*v2.x + y*v2.y + z*v2.z; }
285 inline double get_angle(Vector3<T>& v2)
286 {
287 double tmp = dot(v2);
288 return acos(sqrt(tmp*tmp/(dot(*this)*v2.dot(v2))));
289 }
291 inline double get_anglen(Vector3<T>& v2)
292 { return acos((double) dot(v2)); }
294 std::string & getstring(std::string & s) const;
296 inline double length(void) const
297 { return sqrt((dot(*this))); }
299 inline Vector3<T>& normalize()
300 { double l = length(); if (l == 0.0) return *this; x /= l; y /= l; z /= l; return *this; }
302 inline Vector3<T> proj(Vector3<T>& v2)
303 { Vector3<T> vres; vres = v2 * dot(v2)/v2.dot(v2); return vres; }
304 inline Vector3<T>& proj(Vector3<T>& v2, Vector3<T>& vres)
305 { vres = v2 * dot(v2)/v2.dot(v2); return vres; }
306 };
308 // Scalar multiplication, continued
309 template <class T> inline Vector3<T> operator*(const Vector3<T>& v, const int a)
310 { return Vector3<T>(v) *= a;}
311 template <class T> inline Vector3<T> operator*(const int a, const Vector3<T>& v)
312 { return Vector3<T>(v) *= a;}
313 template <class T> inline Vector3<T> operator*(const Vector3<T> v, const float a)
314 { return Vector3<T>(v) *= a;}
315 template <class T> inline Vector3<T> operator*(const float a, const Vector3<T> v)
316 { return Vector3<T>(v) *= a;}
317 template <class T> inline Vector3<T> operator*(const Vector3<T>& v, const double a)
318 { return Vector3<T>(v) *= a;}
319 template <class T> inline Vector3<T> operator*(const double a, const Vector3<T>& v)
320 { return Vector3<T>(v) *= a;}
322 // Scalar division, continued
323 template <class T> inline Vector3<T> operator/(const Vector3<T>& v, const int a)
324 { return Vector3<T>(v) /= a;}
325 template <class T> inline Vector3<T> operator/(const int a, const Vector3<T>& v)
326 { return Vector3<T>(v) /= a;}
327 template <class T> inline Vector3<T> operator/(const Vector3<T>& v, const float a)
328 { return Vector3<T>(v) /= a;}
329 template <class T> inline Vector3<T> operator/(const float a, const Vector3<T>& v)
330 { return Vector3<T>(v) /= a;}
331 template <class T> inline Vector3<T> operator/(const Vector3<T>& v, const double a)
332 { return Vector3<T>(v) /= a;}
333 template <class T> inline Vector3<T> operator/(const double a, const Vector3<T>& v)
334 { return Vector3<T>(v) /= a;}
336 /////////////////////////////////////////////////////////////////////////////
337 template <class T> class Vector4
338 {
339 public:
340 T x, y, z, w;
342 // Constructors
343 Vector4() : x (0), y(0), z(0), w(0) {}
344 Vector4(T a) : x (a), y(a), z(a), w(a) {}
345 Vector4(T a, T b, T c, T d) : x (a), y(b), z(c), w(d) {}
347 // Array indexing
348 inline T& operator[](unsigned int i)
349 { assert (i<4); if (i==0) return x; if (i==1) return y; if (i==2) return z; return w; }
350 inline const T& operator[](unsigned int i) const
351 { assert (i<4); if (i==0) return x; if (i==1) return y; if (i==2) return z; return w; }
353 // Assignment
354 inline Vector4<T>& operator=(const Vector4<T>& v2)
355 { x = v2.x; y = v2.y; z = v2.z; w = v2.w; return *this; }
356 inline Vector4<T>& assign(const T a, const T b, const T c, const T d)
357 { x = a; y = b; z = c; w = d; return *this; }
359 // Comparison
360 inline bool operator==(Vector4<T>& v2) const
361 { return ((x == v2.x) && (y == v2.y) && (z == v2.z) && (w == v2.w)); }
362 inline bool operator!=(Vector4<T>& v2) const
363 { return ! ((x == v2.x) && (y == v2.y) && (z == v2.z) && (w == v2.w)); }
365 // Vector addition
366 inline Vector4<T> operator+(const Vector4<T>& v2) const
367 { Vector4<T> vres; vres.x = x + v2.x; vres.y = y + v2.y; vres.z = z + v2.z; vres.w = w + v2.w; return vres; }
368 inline Vector4<T>& operator+=(const Vector4<T>& v2)
369 { x += v2.x; y += v2.y; z += v2.z; w += v2.w; return *this; }
371 // Vector subtraction
372 inline Vector4<T> operator-(const Vector4<T>& v2) const
373 { Vector4<T> vres; vres.x = x - v2.x; vres.y = y - v2.y; vres.z = z - v2.z; vres.w = w - v2.w; return vres; }
374 inline Vector4<T>& operator-=(const Vector4<T>& v2)
375 { x -= v2.x; y -= v2.y; z -= v2.z; w -= v2.w; return *this; }
377 // Scalar multiplication
378 inline Vector4<T>& operator*=(const int a)
379 { x *= a; y *= a; z *= a; w *= a; return *this; }
380 inline Vector4<T>& operator*=(const float a)
381 { x *= a; y *= a; z *= a; w *= a; return *this; }
382 inline Vector4<T>& operator*=(const double a)
383 { x *= a; y *= a; z *= a; w *= a; return *this; }
385 // Scalar division
386 inline Vector4<T>& operator/=(const int a)
387 { assert(a!=0); x /= a; y /= a; z /= a; w /= a; return *this; }
388 inline Vector4<T>& operator/=(const float a)
389 { assert(a!=0); x /= a; y /= a; z /= a; w /= a; return *this; }
390 inline Vector4<T>& operator/=(const double a)
391 { assert(a!=0); x /= a; y /= a; z /= a; w /= a; return *this; }
394 // methods
396 inline T dot(const Vector4<T>& v2) const
397 { return x*v2.x + y*v2.y + z*v2.z + w*v2.w; }
399 inline double get_angle(Vector4<T>& v2)
400 {
401 double tmp = dot(v2);
402 return acos(sqrt(tmp*tmp/(dot(*this)*v2.dot(v2))));
403 }
405 inline double get_anglen(Vector4<T>& v2)
406 { return acos((double) dot(v2)); }
408 std::string & getstring(std::string & s) const;
410 inline double length(void) const
411 { return sqrt((dot(*this))); }
413 inline Vector4<T>& normalize()
414 { double l = length(); if (l == 0.0) return *this; x /= l; y /= l; z /= l; w /= l; return *this; }
416 inline Vector4<T> proj(Vector4<T>& v2)
417 { Vector4<T> vres; vres = v2 * dot(v2)/v2.dot(v2); return vres; }
418 inline Vector4<T>& proj(Vector4<T>& v2, Vector4<T>& vres)
419 { vres = v2 * dot(v2)/v2.dot(v2); return vres; }
420 };
422 // Scalar multiplication, continued
423 template <class T> inline Vector4<T> operator*(const Vector4<T>& v, const int a)
424 { return Vector4<T>(v) *= a;}
425 template <class T> inline Vector4<T> operator*(const int a, const Vector4<T>& v)
426 { return Vector4<T>(v) *= a;}
427 template <class T> inline Vector4<T> operator*(const Vector4<T> v, const float a)
428 { return Vector4<T>(v) *= a;}
429 template <class T> inline Vector4<T> operator*(const float a, const Vector4<T> v)
430 { return Vector4<T>(v) *= a;}
431 template <class T> inline Vector4<T> operator*(const Vector4<T>& v, const double a)
432 { return Vector4<T>(v) *= a;}
433 template <class T> inline Vector4<T> operator*(const double a, const Vector4<T>& v)
434 { return Vector4<T>(v) *= a;}
436 // Scalar division, continued
437 template <class T> inline Vector4<T> operator/(const Vector4<T>& v, const int a)
438 { return Vector4<T>(v) /= a;}
439 template <class T> inline Vector4<T> operator/(const int a, const Vector4<T>& v)
440 { return Vector4<T>(v) /= a;}
441 template <class T> inline Vector4<T> operator/(const Vector4<T>& v, const float a)
442 { return Vector4<T>(v) /= a;}
443 template <class T> inline Vector4<T> operator/(const float a, const Vector4<T>& v)
444 { return Vector4<T>(v) /= a;}
445 template <class T> inline Vector4<T> operator/(const Vector4<T>& v, const double a)
446 { return Vector4<T>(v) /= a;}
447 template <class T> inline Vector4<T> operator/(const double a, const Vector4<T>& v)
448 { return Vector4<T>(v) /= a;}
450 /////////////////////////////////////////////////////////////////////////////
452 typedef Vector2<int> Vector2i;
453 typedef Vector2<float> Vector2f;
454 typedef Vector2<double> Vector2d;
456 typedef Vector3<int> Vector3i;
457 typedef Vector3<float> Vector3f;
458 typedef Vector3<double> Vector3d;
460 typedef Vector4<int> Vector4i;
461 typedef Vector4<float> Vector4f;
462 typedef Vector4<double> Vector4d;
464 } // namespace arda
466 ////////////////////////////////////////////////////////////////////////////////
467 template <class T> std::string & arda::Vector2<T>::getstring(std::string & s) const
468 {
469 s.clear();
470 std::stringstream ss;
471 ss << "[ " << x << ", " << y << " ]";
472 s = ss.str();
473 return s;
474 }
476 ////////////////////////////////////////////////////////////////////////////////
477 template <class T> std::string & arda::Vector3<T>::getstring(std::string & s) const
478 {
479 s.clear();
480 std::stringstream ss;
481 ss << "[ " << x << ", " << y << ", " << z << " ]";
482 s = ss.str();
483 return s;
484 }
486 ////////////////////////////////////////////////////////////////////////////////
487 template <class T> std::string & arda::Vector4<T>::getstring(std::string & s) const
488 {
489 s.clear();
490 std::stringstream ss;
491 ss << "[ " << x << ", " << y << ", " << z << ", " << w << " ]";
492 s = ss.str();
493 return s;
494 }
497 #endif // VECTOR_H_