view include/Vector.h @ 9:81d2aa42a860

Matrix22 working, but a few methods not yet written. I started thinking about refactoring again t omake things even cleaner in design, with less repetition.
author Eris Caffee <discordia@eldalin.com>
date Fri, 07 Oct 2011 11:08:38 -0500
parents 5377337c7de0
children 398894c52b69
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 // * is defined as a standalone template operator for the scalar * Vector form.
36 // assign(T a, T b [, T b [, T d]])
37 // Directly assign values to the vector.
38 // cross(Vector3& v2)
39 // cross(Vector3& v2, Vector3& vres)
40 // Cross product of the vector with v2. Only defined for Vector3 types.
41 // The version that takes two arguments stores the result in the second
42 // argument. This may be faster since no temporary object is created
43 // during the operation.
44 // dot(Vector& v2)
45 // The dot product of the vector with v2.
46 // get_angle(Vector& v2)
47 // Returns the angle (in radians) between the vector and v2.
48 // Not meaningful for int vectors.
49 // get_anglen(Vector& v2)
50 // Like get_angle(), but the vectors must already be normalized.
51 // Not meaningful for int vectors.
52 // getstring(std::string & s)
53 // Returns a C string representation of the vector.
54 // This is one of the few non-inline Vector functions.
55 // length()
56 // Get the length of a vector.
57 // Returns a double for all vector types.
58 // normalize()
59 // Normalizes the vecor.
60 // Not meaningful for int vectors.
61 // proj(Vector& v2, Vector& vres)
62 // Calculates the projection of the vector onto v2 and returns the result
63 // in vres.
64 // Not meaningful for int vectors.
65 // Returns vres.
66 //
67 //
68 // Note that the following typedefs are defined for convenience:
69 //
70 // typedef Vector2<int> Vector2i;
71 // typedef Vector2<float> Vector2f;
72 // typedef Vector2<double> Vector2d;
73 // typedef Vector3<int> Vector3i;
74 // typedef Vector3<float> Vector3f;
75 // typedef Vector3<double> Vector3d;
76 // typedef Vector4<int> Vector4i;
77 // typedef Vector4<float> Vector4f;
78 // typedef Vector4<double> Vector4d;
79 //
80 //
81 //
82 // Scalar multiplication and division are overloaded. Why?
83 // I'm not sure I need this. The idea is to support all likely scalar
84 // types without having to rely on implicit or explicit type conversion,
85 // especially not a conversion that might result in loss of precision.
86 // Multiplying a float Vector by a double scalar, for example.
87 //
88 // Is there a better way to do this? Am I worrying about nothing?
89 //
90 //
91 //
92 // I suppose I could make this into a single Vector template on two parameters
93 // template <typename T, unsigned int N> class Vector
94 // {
95 // T v[N];
96 //
97 // etc...
98 //
99 // This might buy perfect generality, but it would come at the expense of
100 // loops in all of the code, so I don't think it would really be worth it.
103 /////////////////////////////////////////////////////////////////////////////
104 template <typename T> class Vector2
105 {
106 public:
107 T x, y;
109 // Constructors
110 Vector2() {}
111 Vector2(T a) : x (a), y(a) {}
112 Vector2(T a, T b) : x (a), y(b) {}
114 // Array indexing
115 inline T& operator[](unsigned int i)
116 { assert (i<2); if (i==0) return x; return y; }
117 inline const T& operator[](unsigned int i) const
118 { assert (i<2); if (i==0) return x; return y; }
120 // Assignment
121 inline Vector2<T>& operator=(const Vector2<T>& v2)
122 { x = v2.x; y = v2.y; return *this; }
123 inline Vector2<T>& assign(const T a, const T b)
124 { x = a; y = b; return *this; }
126 // Comparison
127 inline bool operator==(Vector2<T>& v2) const
128 { return ((x == v2.x) && (y == v2.y)); }
129 inline bool operator!=(Vector2<T>& v2) const
130 { return ! (*this == v2); }
132 // Vector addition
133 inline Vector2<T>& operator+=(const Vector2<T>& v2)
134 { x += v2.x; y += v2.y; return *this; }
135 inline Vector2<T> operator+(const Vector2<T>& v2) const
136 { return Vector2<T>(*this) += v2; }
138 // Vector subtraction
139 inline Vector2<T>& operator-=(const Vector2<T>& v2)
140 { x -= v2.x; y -= v2.y; return *this; }
141 inline Vector2<T> operator-(const Vector2<T>& v2) const
142 { return Vector2<T>(*this) -= v2; }
144 // Scalar multiplication
145 inline Vector2<T>& operator*=(const int a)
146 { x *= a; y *= a; return *this; }
147 inline Vector2<T>& operator*=(const float a)
148 { x *= a; y *= a; return *this; }
149 inline Vector2<T>& operator*=(const double a)
150 { x *= a; y *= a; return *this; }
151 inline Vector2<T> operator*(const int a)
152 { return Vector2<T>(*this) *= a;}
153 inline Vector2<T> operator*(const float a)
154 { return Vector2<T>(*this) *= a;}
155 inline Vector2<T> operator*(const double a)
156 { return Vector2<T>(*this) *= a;}
158 // Scalar division
159 inline Vector2<T>& operator/=(const int a)
160 { assert(a!=0); x /= a; y /= a; return *this; }
161 inline Vector2<T>& operator/=(const float a)
162 { assert(a!=0); x /= a; y /= a; return *this; }
163 inline Vector2<T>& operator/=(const double a)
164 { assert(a!=0); x /= a; y /= a; return *this; }
165 inline Vector2<T> operator/(const int a)
166 { return Vector2<T>(*this) /= a;}
167 inline Vector2<T> operator/(const float a)
168 { return Vector2<T>(*this) /= a;}
169 inline Vector2<T> operator/(const double a)
170 { return Vector2<T>(*this) /= a;}
173 // methods
175 inline T dot(const Vector2<T>& v2) const
176 { return x*v2.x + y*v2.y; }
178 inline double get_angle(Vector2<T>& v2)
179 {
180 double tmp = dot(v2);
181 return acos(sqrt(tmp*tmp/(dot(*this)*v2.dot(v2))));
182 }
184 inline double get_anglen(Vector2<T>& v2)
185 { return acos((double) dot(v2)); }
187 std::string & getstring(std::string & s) const;
189 inline double length(void) const
190 { return sqrt((dot(*this))); }
192 inline Vector2<T>& normalize()
193 { double l = length(); if (l == 0.0) return *this; x /= l; y /= l; return *this; }
195 inline Vector2<T> proj(Vector2<T>& v2)
196 { Vector2<T> vres; vres = v2 * dot(v2)/v2.dot(v2); return vres; }
197 inline Vector2<T>& proj(Vector2<T>& v2, Vector2<T>& vres)
198 { vres = v2 * dot(v2)/v2.dot(v2); return vres; }
199 };
201 // Scalar multiplication, continued
202 template <typename T> inline Vector2<T> operator*(const int a, const Vector2<T>& v)
203 { return Vector2<T>(v) *= a;}
204 template <typename T> inline Vector2<T> operator*(const float a, const Vector2<T> v)
205 { return Vector2<T>(v) *= a;}
206 template <typename T> inline Vector2<T> operator*(const double a, const Vector2<T>& v)
207 { return Vector2<T>(v) *= a;}
210 /////////////////////////////////////////////////////////////////////////////
211 template <typename T> class Vector3
212 {
213 public:
214 T x, y, z;
216 // Constructors
217 Vector3() {}
218 Vector3(T a) : x (a), y(a), z(a) {}
219 Vector3(T a, T b, T c) : x (a), y(b), z(c) {}
221 // Array indexing
222 inline T& operator[](unsigned int i)
223 { assert (i<3); if (i==0) return x; if (i==1) return y; return z; }
224 inline const T& operator[](unsigned int i) const
225 { assert (i<3); if (i==0) return x; if (i==1) return y; return z; }
227 // Assignment
228 inline Vector3<T>& operator=(const Vector3<T>& v2)
229 { x = v2.x; y = v2.y; z = v2.z; return *this; }
230 inline Vector3<T>& assign(const T a, const T b, const T c)
231 { x = a; y = b; z = c; return *this; }
233 // Comparison
234 inline bool operator==(Vector3<T>& v2) const
235 { return ((x == v2.x) && (y == v2.y) && (z == v2.z)); }
236 inline bool operator!=(Vector3<T>& v2) const
237 { return ! (*this == v2); }
239 // Vector addition
240 inline Vector3<T>& operator+=(const Vector3<T>& v2)
241 { x += v2.x; y += v2.y; z += v2.z; return *this; }
242 inline Vector3<T> operator+(const Vector3<T>& v2) const
243 { return Vector3<T>(*this) += v2; }
245 // Vector subtraction
246 inline Vector3<T>& operator-=(const Vector3<T>& v2)
247 { x -= v2.x; y -= v2.y; z -= v2.z; return *this; }
248 inline Vector3<T> operator-(const Vector3<T>& v2) const
249 { return Vector3<T>(*this) -= v2; }
251 // Scalar multiplication
252 inline Vector3<T>& operator*=(const int a)
253 { x *= a; y *= a; z *= a; return *this; }
254 inline Vector3<T>& operator*=(const float a)
255 { x *= a; y *= a; z *= a; return *this; }
256 inline Vector3<T>& operator*=(const double a)
257 { x *= a; y *= a; z *= a; return *this; }
258 inline Vector3<T> operator*(const int a)
259 { return Vector3<T>(*this) *= a;}
260 inline Vector3<T> operator*(const float a)
261 { return Vector3<T>(*this) *= a;}
262 inline Vector3<T> operator*(const double a)
263 { return Vector3<T>(*this) *= a;}
265 // Scalar division
266 inline Vector3<T>& operator/=(const int a)
267 { assert(a!=0); x /= a; y /= a; z /= a; return *this; }
268 inline Vector3<T>& operator/=(const float a)
269 { assert(a!=0); x /= a; y /= a; z /= a; return *this; }
270 inline Vector3<T>& operator/=(const double a)
271 { assert(a!=0); x /= a; y /= a; z /= a; return *this; }
272 inline Vector3<T> operator/(const int a)
273 { return Vector3<T>(*this) /= a;}
274 inline Vector3<T> operator/(const float a)
275 { return Vector3<T>(*this) /= a;}
276 inline Vector3<T> operator/(const double a)
277 { return Vector3<T>(*this) /= a;}
280 // methods
282 inline Vector3<T>& cross(Vector3<T>& v2, Vector3<T>& vres)
283 {
284 vres.x = y*v2.z - v2.y*z;
285 vres.y = -x*v2.z + v2.x*z;
286 vres.z = x*v2.y - v2.x*y;
287 return vres;
288 }
289 inline Vector3<T> cross(Vector3<T>& v2)
290 {
291 Vector3<T> vres;
292 vres.x = y*v2.z - v2.y*z;
293 vres.y = -x*v2.z + v2.x*z;
294 vres.z = x*v2.y - v2.x*y;
295 return vres;
296 }
298 inline T dot(const Vector3<T>& v2) const
299 { return x*v2.x + y*v2.y + z*v2.z; }
301 inline double get_angle(Vector3<T>& v2)
302 {
303 double tmp = dot(v2);
304 return acos(sqrt(tmp*tmp/(dot(*this)*v2.dot(v2))));
305 }
307 inline double get_anglen(Vector3<T>& v2)
308 { return acos((double) dot(v2)); }
310 std::string & getstring(std::string & s) const;
312 inline double length(void) const
313 { return sqrt((dot(*this))); }
315 inline Vector3<T>& normalize()
316 { double l = length(); if (l == 0.0) return *this; x /= l; y /= l; z /= l; return *this; }
318 inline Vector3<T> proj(Vector3<T>& v2)
319 { Vector3<T> vres; vres = v2 * dot(v2)/v2.dot(v2); return vres; }
320 inline Vector3<T>& proj(Vector3<T>& v2, Vector3<T>& vres)
321 { vres = v2 * dot(v2)/v2.dot(v2); return vres; }
322 };
324 // Scalar multiplication, continued
325 template <typename T> inline Vector3<T> operator*(const int a, const Vector3<T>& v)
326 { return Vector3<T>(v) *= a;}
327 template <typename T> inline Vector3<T> operator*(const float a, const Vector3<T> v)
328 { return Vector3<T>(v) *= a;}
329 template <typename T> inline Vector3<T> operator*(const double a, const Vector3<T>& v)
330 { return Vector3<T>(v) *= a;}
332 /////////////////////////////////////////////////////////////////////////////
333 template <typename T> class Vector4
334 {
335 public:
336 T x, y, z, w;
338 // Constructors
339 Vector4() {}
340 Vector4(T a) : x (a), y(a), z(a), w(a) {}
341 Vector4(T a, T b, T c, T d) : x (a), y(b), z(c), w(d) {}
343 // Array indexing
344 inline T& operator[](unsigned int i)
345 { assert (i<4); if (i==0) return x; if (i==1) return y; if (i==2) return z; return w; }
346 inline const T& operator[](unsigned int i) const
347 { assert (i<4); if (i==0) return x; if (i==1) return y; if (i==2) return z; return w; }
349 // Assignment
350 inline Vector4<T>& operator=(const Vector4<T>& v2)
351 { x = v2.x; y = v2.y; z = v2.z; w = v2.w; return *this; }
352 inline Vector4<T>& assign(const T a, const T b, const T c, const T d)
353 { x = a; y = b; z = c; w = d; return *this; }
355 // Comparison
356 inline bool operator==(Vector4<T>& v2) const
357 { return ((x == v2.x) && (y == v2.y) && (z == v2.z) && (w == v2.w)); }
358 inline bool operator!=(Vector4<T>& v2) const
359 { return ! (*this == v2); }
361 // Vector addition
362 inline Vector4<T>& operator+=(const Vector4<T>& v2)
363 { x += v2.x; y += v2.y; z += v2.z; w += v2.w; return *this; }
364 inline Vector4<T> operator+(const Vector4<T>& v2) const
365 { return Vector4<T>(*this) += v2; }
367 // Vector subtraction
368 inline Vector4<T>& operator-=(const Vector4<T>& v2)
369 { x -= v2.x; y -= v2.y; z -= v2.z; w -= v2.w; return *this; }
370 inline Vector4<T> operator-(const Vector4<T>& v2) const
371 { return Vector4<T>(*this) -= v2; }
373 // Scalar multiplication
374 inline Vector4<T>& operator*=(const int a)
375 { x *= a; y *= a; z *= a; w *= a; return *this; }
376 inline Vector4<T>& operator*=(const float a)
377 { x *= a; y *= a; z *= a; w *= a; return *this; }
378 inline Vector4<T>& operator*=(const double a)
379 { x *= a; y *= a; z *= a; w *= a; return *this; }
380 inline Vector4<T> operator*(const int a)
381 { return Vector4<T>(*this) *= a;}
382 inline Vector4<T> operator*(const float a)
383 { return Vector4<T>(*this) *= a;}
384 inline Vector4<T> operator*(const double a)
385 { return Vector4<T>(*this) *= a;}
387 // Scalar division
388 inline Vector4<T>& operator/=(const int a)
389 { assert(a!=0); x /= a; y /= a; z /= a; w /= a; return *this; }
390 inline Vector4<T>& operator/=(const float a)
391 { assert(a!=0); x /= a; y /= a; z /= a; w /= a; return *this; }
392 inline Vector4<T>& operator/=(const double a)
393 { assert(a!=0); x /= a; y /= a; z /= a; w /= a; return *this; }
394 inline Vector4<T> operator/(const int a)
395 { return Vector4<T>(*this) /= a;}
396 inline Vector4<T> operator/(const float a)
397 { return Vector4<T>(*this) /= a;}
398 inline Vector4<T> operator/(const double a)
399 { return Vector4<T>(*this) /= a;}
402 // methods
404 inline T dot(const Vector4<T>& v2) const
405 { return x*v2.x + y*v2.y + z*v2.z + w*v2.w; }
407 inline double get_angle(Vector4<T>& v2)
408 {
409 double tmp = dot(v2);
410 return acos(sqrt(tmp*tmp/(dot(*this)*v2.dot(v2))));
411 }
413 inline double get_anglen(Vector4<T>& v2)
414 { return acos((double) dot(v2)); }
416 std::string & getstring(std::string & s) const;
418 inline double length(void) const
419 { return sqrt((dot(*this))); }
421 inline Vector4<T>& normalize()
422 { double l = length(); if (l == 0.0) return *this; x /= l; y /= l; z /= l; w /= l; return *this; }
424 inline Vector4<T> proj(Vector4<T>& v2)
425 { Vector4<T> vres; vres = v2 * dot(v2)/v2.dot(v2); return vres; }
426 inline Vector4<T>& proj(Vector4<T>& v2, Vector4<T>& vres)
427 { vres = v2 * dot(v2)/v2.dot(v2); return vres; }
428 };
430 // Scalar multiplication, continued
431 template <typename T> inline Vector4<T> operator*(const int a, const Vector4<T>& v)
432 { return Vector4<T>(v) *= a;}
433 template <typename T> inline Vector4<T> operator*(const float a, const Vector4<T> v)
434 { return Vector4<T>(v) *= a;}
435 template <typename T> inline Vector4<T> operator*(const double a, const Vector4<T>& v)
436 { return Vector4<T>(v) *= a;}
438 /////////////////////////////////////////////////////////////////////////////
440 typedef Vector2<int> Vector2i;
441 typedef Vector2<float> Vector2f;
442 typedef Vector2<double> Vector2d;
444 typedef Vector3<int> Vector3i;
445 typedef Vector3<float> Vector3f;
446 typedef Vector3<double> Vector3d;
448 typedef Vector4<int> Vector4i;
449 typedef Vector4<float> Vector4f;
450 typedef Vector4<double> Vector4d;
452 } // namespace arda
454 ////////////////////////////////////////////////////////////////////////////////
455 template <typename T> std::string & arda::Vector2<T>::getstring(std::string & s) const
456 {
457 s.clear();
458 std::stringstream ss;
459 ss << "[ " << x << ", " << y << " ]";
460 s = ss.str();
461 return s;
462 }
464 ////////////////////////////////////////////////////////////////////////////////
465 template <typename T> std::string & arda::Vector3<T>::getstring(std::string & s) const
466 {
467 s.clear();
468 std::stringstream ss;
469 ss << "[ " << x << ", " << y << ", " << z << " ]";
470 s = ss.str();
471 return s;
472 }
474 ////////////////////////////////////////////////////////////////////////////////
475 template <typename T> std::string & arda::Vector4<T>::getstring(std::string & s) const
476 {
477 s.clear();
478 std::stringstream ss;
479 ss << "[ " << x << ", " << y << ", " << z << ", " << w << " ]";
480 s = ss.str();
481 return s;
482 }
485 #endif // VECTOR_H_