view include/Vector.h @ 8:5377337c7de0

Updated comments.
author Eris Caffee <discordia@eldalin.com>
date Wed, 28 Sep 2011 12:53:57 -0500
parents 378862555189
children 81d2aa42a860
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 //
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 explicity type conversion,
87 // especially not a conversion that might result in loss of precision.
88 // Multiplying a float Vector by a double scala, for example.
89 // Is there a better way to do this?
90 //
91 //
92 //
93 // I suppose I could make this into a single Vector template on two parameters
94 // template <class T, unsigned int N> class Vector
95 // {
96 // T v[N];
97 //
98 // etc...
99 //
100 // This might buy perfect generality, but it would come at the expense of
101 // loops in all of the code, so I don't think it would really be worth it.
104 /////////////////////////////////////////////////////////////////////////////
105 template <class T> class Vector2
106 {
107 public:
108 T x, y;
110 // Constructors
111 Vector2() : x (0), y(0) {}
112 Vector2(T a) : x (a), y(a) {}
113 Vector2(T a, T b) : x (a), y(b) {}
115 // Array indexing
116 inline T& operator[](unsigned int i)
117 { assert (i<2); if (i==0) return x; return y; }
118 inline const T& operator[](unsigned int i) const
119 { assert (i<2); if (i==0) return x; return y; }
121 // Assignment
122 inline Vector2<T>& operator=(const Vector2<T>& v2)
123 { x = v2.x; y = v2.y; return *this; }
124 inline Vector2<T>& assign(const T a, const T b)
125 { x = a; y = b; return *this; }
127 // Comparison
128 inline bool operator==(Vector2<T>& v2) const
129 { return ((x == v2.x) && (y == v2.y)); }
130 inline bool operator!=(Vector2<T>& v2) const
131 { return ! ((x == v2.x) && (y == v2.y)); }
133 // Vector addition
134 inline Vector2<T> operator+(const Vector2<T>& v2) const
135 { Vector2<T> vres; vres.x = x + v2.x; vres.y = y + v2.y; return vres; }
136 inline Vector2<T>& operator+=(const Vector2<T>& v2)
137 { x += v2.x; y += v2.y; return *this; }
139 // Vector subtraction
140 inline Vector2<T> operator-(const Vector2<T>& v2) const
141 { Vector2<T> vres; vres.x = x - v2.x; vres.y = y - v2.y; return vres; }
142 inline Vector2<T>& operator-=(const Vector2<T>& v2)
143 { x -= v2.x; y -= v2.y; return *this; }
145 // Scalar multiplication
146 inline Vector2<T>& operator*=(const int a)
147 { x *= a; y *= a; return *this; }
148 inline Vector2<T>& operator*=(const float a)
149 { x *= a; y *= a; return *this; }
150 inline Vector2<T>& operator*=(const double a)
151 { x *= a; y *= a; return *this; }
153 // Scalar division
154 inline Vector2<T>& operator/=(const int a)
155 { assert(a!=0); x /= a; y /= a; return *this; }
156 inline Vector2<T>& operator/=(const float a)
157 { assert(a!=0); x /= a; y /= a; return *this; }
158 inline Vector2<T>& operator/=(const double a)
159 { assert(a!=0); x /= a; y /= a; return *this; }
162 // methods
164 inline T dot(const Vector2<T>& v2) const
165 { return x*v2.x + y*v2.y; }
167 inline double get_angle(Vector2<T>& v2)
168 {
169 double tmp = dot(v2);
170 return acos(sqrt(tmp*tmp/(dot(*this)*v2.dot(v2))));
171 }
173 inline double get_anglen(Vector2<T>& v2)
174 { return acos((double) dot(v2)); }
176 std::string & getstring(std::string & s) const;
178 inline double length(void) const
179 { return sqrt((dot(*this))); }
181 inline Vector2<T>& normalize()
182 { double l = length(); if (l == 0.0) return *this; x /= l; y /= l; return *this; }
184 inline Vector2<T> proj(Vector2<T>& v2)
185 { Vector2<T> vres; vres = v2 * dot(v2)/v2.dot(v2); return vres; }
186 inline Vector2<T>& proj(Vector2<T>& v2, Vector2<T>& vres)
187 { vres = v2 * dot(v2)/v2.dot(v2); return vres; }
188 };
190 // Scalar multiplication, continued
191 template <class T> inline Vector2<T> operator*(const Vector2<T>& v, const int a)
192 { return Vector2<T>(v) *= a;}
193 template <class T> inline Vector2<T> operator*(const int a, const Vector2<T>& v)
194 { return Vector2<T>(v) *= a;}
195 template <class T> inline Vector2<T> operator*(const Vector2<T> v, const float a)
196 { return Vector2<T>(v) *= a;}
197 template <class T> inline Vector2<T> operator*(const float a, const Vector2<T> v)
198 { return Vector2<T>(v) *= a;}
199 template <class T> inline Vector2<T> operator*(const Vector2<T>& v, const double a)
200 { return Vector2<T>(v) *= a;}
201 template <class T> inline Vector2<T> operator*(const double a, const Vector2<T>& v)
202 { return Vector2<T>(v) *= a;}
204 // Scalar division, continued
205 template <class T> inline Vector2<T> operator/(const Vector2<T>& v, const int a)
206 { return Vector2<T>(v) /= a;}
207 template <class T> inline Vector2<T> operator/(const int a, const Vector2<T>& v)
208 { return Vector2<T>(v) /= a;}
209 template <class T> inline Vector2<T> operator/(const Vector2<T>& v, const float a)
210 { return Vector2<T>(v) /= a;}
211 template <class T> inline Vector2<T> operator/(const float a, const Vector2<T>& v)
212 { return Vector2<T>(v) /= a;}
213 template <class T> inline Vector2<T> operator/(const Vector2<T>& v, const double a)
214 { return Vector2<T>(v) /= a;}
215 template <class T> inline Vector2<T> operator/(const double a, const Vector2<T>& v)
216 { return Vector2<T>(v) /= a;}
218 /////////////////////////////////////////////////////////////////////////////
219 template <class T> class Vector3
220 {
221 public:
222 T x, y, z;
224 // Constructors
225 Vector3() : x (0), y(0), z(0) {}
226 Vector3(T a) : x (a), y(a), z(a) {}
227 Vector3(T a, T b, T c) : x (a), y(b), z(c) {}
229 // Array indexing
230 inline T& operator[](unsigned int i)
231 { assert (i<3); if (i==0) return x; if (i==1) return y; return z; }
232 inline const T& operator[](unsigned int i) const
233 { assert (i<3); if (i==0) return x; if (i==1) return y; return z; }
235 // Assignment
236 inline Vector3<T>& operator=(const Vector3<T>& v2)
237 { x = v2.x; y = v2.y; z = v2.z; return *this; }
238 inline Vector3<T>& assign(const T a, const T b, const T c)
239 { x = a; y = b; z = c; return *this; }
241 // Comparison
242 inline bool operator==(Vector3<T>& v2) const
243 { return ((x == v2.x) && (y == v2.y) && (z == v2.z)); }
244 inline bool operator!=(Vector3<T>& v2) const
245 { return ! ((x == v2.x) && (y == v2.y) && (z == v2.z)); }
247 // Vector addition
248 inline Vector3<T> operator+(const Vector3<T>& v2) const
249 { Vector3<T> vres; vres.x = x + v2.x; vres.y = y + v2.y; vres.z = z + v2.z; return vres; }
250 inline Vector3<T>& operator+=(const Vector3<T>& v2)
251 { x += v2.x; y += v2.y; z += v2.z; return *this; }
253 // Vector subtraction
254 inline Vector3<T> operator-(const Vector3<T>& v2) const
255 { Vector3<T> vres; vres.x = x - v2.x; vres.y = y - v2.y; vres.z = z - v2.z; return vres; }
256 inline Vector3<T>& operator-=(const Vector3<T>& v2)
257 { x -= v2.x; y -= v2.y; z -= v2.z; return *this; }
259 // Scalar multiplication
260 inline Vector3<T>& operator*=(const int a)
261 { x *= a; y *= a; z *= a; return *this; }
262 inline Vector3<T>& operator*=(const float a)
263 { x *= a; y *= a; z *= a; return *this; }
264 inline Vector3<T>& operator*=(const double a)
265 { x *= a; y *= a; z *= a; return *this; }
267 // Scalar division
268 inline Vector3<T>& operator/=(const int a)
269 { assert(a!=0); x /= a; y /= a; z /= a; return *this; }
270 inline Vector3<T>& operator/=(const float a)
271 { assert(a!=0); x /= a; y /= a; z /= a; return *this; }
272 inline Vector3<T>& operator/=(const double a)
273 { assert(a!=0); x /= a; y /= a; z /= a; return *this; }
276 // methods
278 inline Vector3<T>& cross(Vector3<T>& v2, Vector3<T>& vres)
279 {
280 vres.x = y*v2.z - v2.y*z;
281 vres.y = -x*v2.z + v2.x*z;
282 vres.z = x*v2.y - v2.x*y;
283 return vres;
284 }
285 inline Vector3<T> cross(Vector3<T>& v2)
286 {
287 Vector3<T> vres;
288 vres.x = y*v2.z - v2.y*z;
289 vres.y = -x*v2.z + v2.x*z;
290 vres.z = x*v2.y - v2.x*y;
291 return vres;
292 }
294 inline T dot(const Vector3<T>& v2) const
295 { return x*v2.x + y*v2.y + z*v2.z; }
297 inline double get_angle(Vector3<T>& v2)
298 {
299 double tmp = dot(v2);
300 return acos(sqrt(tmp*tmp/(dot(*this)*v2.dot(v2))));
301 }
303 inline double get_anglen(Vector3<T>& v2)
304 { return acos((double) dot(v2)); }
306 std::string & getstring(std::string & s) const;
308 inline double length(void) const
309 { return sqrt((dot(*this))); }
311 inline Vector3<T>& normalize()
312 { double l = length(); if (l == 0.0) return *this; x /= l; y /= l; z /= l; return *this; }
314 inline Vector3<T> proj(Vector3<T>& v2)
315 { Vector3<T> vres; vres = v2 * dot(v2)/v2.dot(v2); return vres; }
316 inline Vector3<T>& proj(Vector3<T>& v2, Vector3<T>& vres)
317 { vres = v2 * dot(v2)/v2.dot(v2); return vres; }
318 };
320 // Scalar multiplication, continued
321 template <class T> inline Vector3<T> operator*(const Vector3<T>& v, const int a)
322 { return Vector3<T>(v) *= a;}
323 template <class T> inline Vector3<T> operator*(const int a, const Vector3<T>& v)
324 { return Vector3<T>(v) *= a;}
325 template <class T> inline Vector3<T> operator*(const Vector3<T> v, const float a)
326 { return Vector3<T>(v) *= a;}
327 template <class T> inline Vector3<T> operator*(const float a, const Vector3<T> v)
328 { return Vector3<T>(v) *= a;}
329 template <class T> inline Vector3<T> operator*(const Vector3<T>& v, const double a)
330 { return Vector3<T>(v) *= a;}
331 template <class T> inline Vector3<T> operator*(const double a, const Vector3<T>& v)
332 { return Vector3<T>(v) *= a;}
334 // Scalar division, continued
335 template <class T> inline Vector3<T> operator/(const Vector3<T>& v, const int a)
336 { return Vector3<T>(v) /= a;}
337 template <class T> inline Vector3<T> operator/(const int a, const Vector3<T>& v)
338 { return Vector3<T>(v) /= a;}
339 template <class T> inline Vector3<T> operator/(const Vector3<T>& v, const float a)
340 { return Vector3<T>(v) /= a;}
341 template <class T> inline Vector3<T> operator/(const float a, const Vector3<T>& v)
342 { return Vector3<T>(v) /= a;}
343 template <class T> inline Vector3<T> operator/(const Vector3<T>& v, const double a)
344 { return Vector3<T>(v) /= a;}
345 template <class T> inline Vector3<T> operator/(const double a, const Vector3<T>& v)
346 { return Vector3<T>(v) /= a;}
348 /////////////////////////////////////////////////////////////////////////////
349 template <class T> class Vector4
350 {
351 public:
352 T x, y, z, w;
354 // Constructors
355 Vector4() : x (0), y(0), z(0), w(0) {}
356 Vector4(T a) : x (a), y(a), z(a), w(a) {}
357 Vector4(T a, T b, T c, T d) : x (a), y(b), z(c), w(d) {}
359 // Array indexing
360 inline T& operator[](unsigned int i)
361 { assert (i<4); if (i==0) return x; if (i==1) return y; if (i==2) return z; return w; }
362 inline const T& operator[](unsigned int i) const
363 { assert (i<4); if (i==0) return x; if (i==1) return y; if (i==2) return z; return w; }
365 // Assignment
366 inline Vector4<T>& operator=(const Vector4<T>& v2)
367 { x = v2.x; y = v2.y; z = v2.z; w = v2.w; return *this; }
368 inline Vector4<T>& assign(const T a, const T b, const T c, const T d)
369 { x = a; y = b; z = c; w = d; return *this; }
371 // Comparison
372 inline bool operator==(Vector4<T>& v2) const
373 { return ((x == v2.x) && (y == v2.y) && (z == v2.z) && (w == v2.w)); }
374 inline bool operator!=(Vector4<T>& v2) const
375 { return ! ((x == v2.x) && (y == v2.y) && (z == v2.z) && (w == v2.w)); }
377 // Vector addition
378 inline Vector4<T> operator+(const Vector4<T>& v2) const
379 { 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; }
380 inline Vector4<T>& operator+=(const Vector4<T>& v2)
381 { x += v2.x; y += v2.y; z += v2.z; w += v2.w; return *this; }
383 // Vector subtraction
384 inline Vector4<T> operator-(const Vector4<T>& v2) const
385 { 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; }
386 inline Vector4<T>& operator-=(const Vector4<T>& v2)
387 { x -= v2.x; y -= v2.y; z -= v2.z; w -= v2.w; return *this; }
389 // Scalar multiplication
390 inline Vector4<T>& operator*=(const int a)
391 { x *= a; y *= a; z *= a; w *= a; return *this; }
392 inline Vector4<T>& operator*=(const float a)
393 { x *= a; y *= a; z *= a; w *= a; return *this; }
394 inline Vector4<T>& operator*=(const double a)
395 { x *= a; y *= a; z *= a; w *= a; return *this; }
397 // Scalar division
398 inline Vector4<T>& operator/=(const int a)
399 { assert(a!=0); x /= a; y /= a; z /= a; w /= a; return *this; }
400 inline Vector4<T>& operator/=(const float a)
401 { assert(a!=0); x /= a; y /= a; z /= a; w /= a; return *this; }
402 inline Vector4<T>& operator/=(const double a)
403 { assert(a!=0); x /= a; y /= a; z /= a; w /= a; return *this; }
406 // methods
408 inline T dot(const Vector4<T>& v2) const
409 { return x*v2.x + y*v2.y + z*v2.z + w*v2.w; }
411 inline double get_angle(Vector4<T>& v2)
412 {
413 double tmp = dot(v2);
414 return acos(sqrt(tmp*tmp/(dot(*this)*v2.dot(v2))));
415 }
417 inline double get_anglen(Vector4<T>& v2)
418 { return acos((double) dot(v2)); }
420 std::string & getstring(std::string & s) const;
422 inline double length(void) const
423 { return sqrt((dot(*this))); }
425 inline Vector4<T>& normalize()
426 { double l = length(); if (l == 0.0) return *this; x /= l; y /= l; z /= l; w /= l; return *this; }
428 inline Vector4<T> proj(Vector4<T>& v2)
429 { Vector4<T> vres; vres = v2 * dot(v2)/v2.dot(v2); return vres; }
430 inline Vector4<T>& proj(Vector4<T>& v2, Vector4<T>& vres)
431 { vres = v2 * dot(v2)/v2.dot(v2); return vres; }
432 };
434 // Scalar multiplication, continued
435 template <class T> inline Vector4<T> operator*(const Vector4<T>& v, const int a)
436 { return Vector4<T>(v) *= a;}
437 template <class T> inline Vector4<T> operator*(const int a, const Vector4<T>& v)
438 { return Vector4<T>(v) *= a;}
439 template <class T> inline Vector4<T> operator*(const Vector4<T> v, const float a)
440 { return Vector4<T>(v) *= a;}
441 template <class T> inline Vector4<T> operator*(const float a, const Vector4<T> v)
442 { return Vector4<T>(v) *= a;}
443 template <class T> inline Vector4<T> operator*(const Vector4<T>& v, const double a)
444 { return Vector4<T>(v) *= a;}
445 template <class T> inline Vector4<T> operator*(const double a, const Vector4<T>& v)
446 { return Vector4<T>(v) *= a;}
448 // Scalar division, continued
449 template <class T> inline Vector4<T> operator/(const Vector4<T>& v, const int a)
450 { return Vector4<T>(v) /= a;}
451 template <class T> inline Vector4<T> operator/(const int a, const Vector4<T>& v)
452 { return Vector4<T>(v) /= a;}
453 template <class T> inline Vector4<T> operator/(const Vector4<T>& v, const float a)
454 { return Vector4<T>(v) /= a;}
455 template <class T> inline Vector4<T> operator/(const float a, const Vector4<T>& v)
456 { return Vector4<T>(v) /= a;}
457 template <class T> inline Vector4<T> operator/(const Vector4<T>& v, const double a)
458 { return Vector4<T>(v) /= a;}
459 template <class T> inline Vector4<T> operator/(const double a, const Vector4<T>& v)
460 { return Vector4<T>(v) /= a;}
462 /////////////////////////////////////////////////////////////////////////////
464 typedef Vector2<int> Vector2i;
465 typedef Vector2<float> Vector2f;
466 typedef Vector2<double> Vector2d;
468 typedef Vector3<int> Vector3i;
469 typedef Vector3<float> Vector3f;
470 typedef Vector3<double> Vector3d;
472 typedef Vector4<int> Vector4i;
473 typedef Vector4<float> Vector4f;
474 typedef Vector4<double> Vector4d;
476 } // namespace arda
478 ////////////////////////////////////////////////////////////////////////////////
479 template <class T> std::string & arda::Vector2<T>::getstring(std::string & s) const
480 {
481 s.clear();
482 std::stringstream ss;
483 ss << "[ " << x << ", " << y << " ]";
484 s = ss.str();
485 return s;
486 }
488 ////////////////////////////////////////////////////////////////////////////////
489 template <class T> std::string & arda::Vector3<T>::getstring(std::string & s) const
490 {
491 s.clear();
492 std::stringstream ss;
493 ss << "[ " << x << ", " << y << ", " << z << " ]";
494 s = ss.str();
495 return s;
496 }
498 ////////////////////////////////////////////////////////////////////////////////
499 template <class T> std::string & arda::Vector4<T>::getstring(std::string & s) const
500 {
501 s.clear();
502 std::stringstream ss;
503 ss << "[ " << x << ", " << y << ", " << z << ", " << w << " ]";
504 s = ss.str();
505 return s;
506 }
509 #endif // VECTOR_H_