Cafu Engine
Vector2.hpp
1 /*
2 Cafu Engine, http://www.cafu.de/
3 Copyright (c) Carsten Fuchs and other contributors.
4 This project is licensed under the terms of the MIT license.
5 */
6 
7 #ifndef CAFU_MATH_VECTOR2_HPP_INCLUDED
8 #define CAFU_MATH_VECTOR2_HPP_INCLUDED
9 
10 #include "Errors.hpp"
11 
12 #include <cassert>
13 #include <cmath>
14 #include <iomanip>
15 #include <limits>
16 #include <sstream>
17 
18 
19 /// This class represents a 2-dimensional vector.
20 template<class T>
21 class Vector2T
22 {
23  public:
24 
25  T x; ///< The x-component of this vector.
26  T y; ///< The y-component of this vector.
27 
28 
29 
30  /// The default constructor. It initializes all components to zero.
31  Vector2T() : x(0), y(0) { }
32 
33  /// This constructor initializes the components from x_ and y_ respectively.
34  Vector2T(T x_, T y_) : x(x_), y(y_) { }
35 
36  /// This constructor initializes the components from an array of (at least) two Ts.
37  template<class C> explicit Vector2T(const C Values[]) : x(T(Values[0])), y(T(Values[1])) { }
38 
39 
40 
41  /// Returns true if the vector is valid, that is, all components are non-NANs.
42  bool IsValid() const
43  {
44  return true;
45  }
46 
47  /// Component access by index number (0 to 1) rather than by name.
48  /// @param Index Index of the component to access. Can only be 0 or 1 (for x or y).
49  /// @throws InvalidOperationE if Index is not 0 or 1.
50  T& operator [] (unsigned int Index)
51  {
52  switch (Index)
53  {
54  case 0: return x;
55  case 1: return y;
56  default: throw InvalidOperationE();
57  }
58  }
59 
60  /// Component access by index number (0 to 1) rather than by name.
61  /// @param Index Index of the component to access. Can only be 0 or 1 (for x or y).
62  /// @throws InvalidOperationE if Index is not 0 or 1.
63  const T& operator [] (unsigned int Index) const
64  {
65  switch (Index)
66  {
67  case 0: return x;
68  case 1: return y;
69  default: throw InvalidOperationE();
70  }
71  }
72 
73 
74 
75  /// Gets this Vector2T<T> as a Vector2T<float>, so that the cast is explicitly visible in user code.
77  {
78 #ifdef _WIN32
79  assert(typeid(T)!=typeid(float));
80 #endif
81 
82  return Vector2T<float>(float(x), float(y));
83  }
84 
85  /// Gets this Vector2T<T> as a Vector2T<double>, so that the cast is explicitly visible in user code.
87  {
88 #ifdef _WIN32
89  assert(typeid(T)!=typeid(double));
90 #endif
91 
92  return Vector2T<double>(double(x), double(y));
93  }
94 
95 
96 
97  /// @name Group of const inspector methods. They are all const and thus do not modify this object.
98  //@{
99 
100  /// Returns the square of the length of this vector.
101  T GetLengthSqr() const { return x*x + y*y; }
102 
103  /// Returns whether this vector is equal to B within tolerance Epsilon, that is, whether it is geometrically closer to B than Epsilon.
104  /// @param B Vector to compare to.
105  /// @param Epsilon Tolerance value.
106  /// @see operator ==
107  bool IsEqual(const Vector2T<T>& B, const T Epsilon) const
108  {
109  return (*this-B).GetLengthSqr() <= Epsilon*Epsilon;
110  }
111 
112  /// Returns a copy of this vector scaled by s, that is, the scalar product (Skalarmultiplikation) of this vector and s.
113  /// @param s Scale factor to scale this vector by.
114  /// @see Also see the operator *, which does exactly the same.
115  Vector2T<T> GetScaled(const T s) const
116  {
117  return Vector2T<T>(x*s, y*s);
118  }
119 
120  /// Returns a copy of this vector non-uniformely scaled by S.
122  {
123  return Vector2T<T>(x*S.x, y*S.y);
124  }
125 
126  //@}
127 
128 
129 
130  /// @name Group of (constructive) binary operators that do not modify their operands.
131  //@{
132 
133  /// Returns whether this vector and B are truly (bit-wise) identical.
134  /// Use this operator with care, as it comes *without* any epsilon threshold for taking rounding errors into account.
135  /// @param B Vector to compare to.
136  /// @see IsEqual()
137  bool operator == (const Vector2T<T>& B) const
138  {
139  return x==B.x &&
140  y==B.y;
141  }
142 
143  /// Returns whether this vector and B are not equal (bit-wise).
144  /// Use this operator with care, as it comes *without* any epsilon threshold for taking rounding errors into account.
145  /// @param B Vector to compare to.
146  /// @see IsEqual()
147  bool operator != (const Vector2T<T>& B) const
148  {
149  return x!=B.x ||
150  y!=B.y;
151  }
152 
153  /// Returns the sum of this Vector2T<T> and B.
155  {
156  return Vector2T<T>(x+B.x, y+B.y);
157  }
158 
159  /// Returns the difference between this Vector2T<T> and B.
161  {
162  return Vector2T<T>(x-B.x, y-B.y);
163  }
164 
165  /// The unary minus operator. B=-A is quasi identical with B=A.GetScaled(-1).
167  {
168  return Vector2T<T>(-x, -y);
169  }
170 
171  /// Returns a copy of this vector scaled by s, that is, the scalar product (Skalarmultiplikation) of this vector and s.
172  /// @param s Factor to multiply this vector with.
173  /// @see GetScaled(), which does exactly the same.
174  Vector2T<T> operator * (const T s) const
175  {
176  return GetScaled(s);
177  }
178 
179  /// Returns a copy of this vector divided by s, that is, the scalar product (Skalarmultiplikation) of this vector and 1/s.
180  Vector2T<T> operator / (const T s) const
181  {
182  // Cannot multiply by the reciprocal, because that won't work with integers.
183  return Vector2T<T>(x/s, y/s);
184  }
185 
186  /// Returns the dot product (Skalarprodukt) of this vector and B.
187  T dot(const Vector2T<T>& B) const
188  {
189  return x*B.x + y*B.y;
190  }
191 
192  //@}
193 
194 
195 
196  /// @name Group of operators that modify this vector.
197  //@{
198 
199  /// Adds B to this vector.
201  {
202  x+=B.x;
203  y+=B.y;
204 
205  return *this;
206  }
207 
208  /// Subtracts B from this vector.
210  {
211  x-=B.x;
212  y-=B.y;
213 
214  return *this;
215  }
216 
217  /// Scales this vector by s.
219  {
220  x*=s;
221  y*=s;
222 
223  return *this;
224  }
225 
226  /// Divides this vector by s. Assumes that s is not 0.
228  {
229  // Cannot multiply by the reciprocal, because that won't work with integers.
230  x/=s;
231  y/=s;
232 
233  return *this;
234  }
235 
236  //@}
237 };
238 
239 
240 /// Returns A scaled by r, that is, the scalar product (Skalarmultiplikation) of A and r.
241 template<class T> inline Vector2T<T> scale(const Vector2T<T>& A, const T r)
242 {
243  return Vector2T<T>(A.x*r, A.y*r);
244 }
245 
246 /// Returns A, non-uniformely scaled by R.
247 template<class T> inline Vector2T<T> scale(const Vector2T<T>& A, const Vector2T<T>& R)
248 {
249  return Vector2T<T>(A.x*R.x, A.y*R.y);
250 }
251 
252 /// Returns the dot product (Skalarprodukt) of A and B.
253 template<class T> inline T dot(const Vector2T<T>& A, const Vector2T<T>& B)
254 {
255  return A.x*B.x + A.y*B.y;
256 }
257 
258 /// Returns the length of A.
259 template<class T> inline T length(const Vector2T<T>& A)
260 {
261  return sqrt(dot(A, A));
262 }
263 
264 /// Returns the length of A. This is a specialized version of the generic length<T> function for floats.
265 template<> inline float length(const Vector2T<float>& A)
266 {
267  return sqrtf(dot(A, A));
268 }
269 
270 /// Returns the normalized (unit length) version of A.
271 /// @throws DivisionByZeroE if length(A)<=Epsilon.
272 template<class T> inline Vector2T<T> normalize(const Vector2T<T>& A, const T Epsilon)
273 {
274  const T Length=length(A);
275 
276  // I'm using <= here rather than only <, so that Epsilon==0 yields a meaningful test (e.g. if T==int).
277  if (Length<=Epsilon) throw DivisionByZeroE();
278 
279  return A/Length;
280 }
281 
282 /// Returns the normalized (unit length) version of A if length(A)>Epsilon, or the (0, 0, 0) vector otherwise.
283 template<class T> inline Vector2T<T> normalizeOr0(const Vector2T<T>& A, const T Epsilon=0)
284 {
285  const T Length=length(A);
286 
287  return (Length>Epsilon) ? scale(A, T(1.0)/Length) : Vector2T<T>(0, 0, 0);
288 }
289 
290 template<class T> inline std::string convertToString(const Vector2T<T>& A)
291 {
292  // From MSDN documentation: "digits10 returns the number of decimal digits that the type can represent without loss of precision."
293  // For floats, that's usually 6, for doubles, that's usually 15. However, we want to use the number of *significant* decimal digits here,
294  // see http://www.open-std.org/JTC1/sc22/wg21/docs/papers/2006/n2005.pdf for details.
295  const int sigdigits=std::numeric_limits<T>::digits10 + 3;
296 
297  std::ostringstream out;
298 
299  out << std::setprecision(sigdigits) << "(" << A.x << ", " << A.y << ")";
300 
301  return out.str();
302 }
303 
304 
305 template<class T> inline std::ostream& operator << (std::ostream& os, const Vector2T<T>& A)
306 {
307  return os << "(" << A.x << ", " << A.y << ")";
308 }
309 
310 
311 typedef Vector2T<float> Vector2fT;
313 
314 #endif
Vector2T< T > GetScaled(const T s) const
Returns a copy of this vector scaled by s, that is, the scalar product (Skalarmultiplikation) of this...
Definition: Vector2.hpp:115
Vector2T(const C Values[])
This constructor initializes the components from an array of (at least) two Ts.
Definition: Vector2.hpp:37
T dot(const Vector2T< T > &B) const
Returns the dot product (Skalarprodukt) of this vector and B.
Definition: Vector2.hpp:187
Vector2T< T > operator*(const T s) const
Returns a copy of this vector scaled by s, that is, the scalar product (Skalarmultiplikation) of this...
Definition: Vector2.hpp:174
Vector2T< T > & operator-=(const Vector2T< T > &B)
Subtracts B from this vector.
Definition: Vector2.hpp:209
Vector2T< T > operator/(const T s) const
Returns a copy of this vector divided by s, that is, the scalar product (Skalarmultiplikation) of thi...
Definition: Vector2.hpp:180
Vector2T< T > operator-() const
The unary minus operator. B=-A is quasi identical with B=A.GetScaled(-1).
Definition: Vector2.hpp:166
Vector2T< T > operator+(const Vector2T< T > &B) const
Returns the sum of this Vector2T<T> and B.
Definition: Vector2.hpp:154
This class represents a 2-dimensional vector.
Definition: Vector2.hpp:21
Vector2T(T x_, T y_)
This constructor initializes the components from x_ and y_ respectively.
Definition: Vector2.hpp:34
Vector2T< double > AsVectorOfDouble() const
Gets this Vector2T<T> as a Vector2T<double>, so that the cast is explicitly visible in user code...
Definition: Vector2.hpp:86
Vector2T< float > AsVectorOfFloat() const
Gets this Vector2T<T> as a Vector2T<float>, so that the cast is explicitly visible in user code...
Definition: Vector2.hpp:76
bool IsEqual(const Vector2T< T > &B, const T Epsilon) const
Returns whether this vector is equal to B within tolerance Epsilon, that is, whether it is geometrica...
Definition: Vector2.hpp:107
Invalid operation (invalid use of method, etc.).
Definition: Errors.hpp:33
bool IsValid() const
Returns true if the vector is valid, that is, all components are non-NANs.
Definition: Vector2.hpp:42
Vector2T< T > & operator*=(const T s)
Scales this vector by s.
Definition: Vector2.hpp:218
Vector2T< T > & operator+=(const Vector2T< T > &B)
Adds B to this vector.
Definition: Vector2.hpp:200
T GetLengthSqr() const
Returns the square of the length of this vector.
Definition: Vector2.hpp:101
bool operator==(const Vector2T< T > &B) const
Returns whether this vector and B are truly (bit-wise) identical.
Definition: Vector2.hpp:137
T & operator[](unsigned int Index)
Component access by index number (0 to 1) rather than by name.
Definition: Vector2.hpp:50
T y
The y-component of this vector.
Definition: Vector2.hpp:26
Vector2T< T > & operator/=(const T s)
Divides this vector by s. Assumes that s is not 0.
Definition: Vector2.hpp:227
T x
The x-component of this vector.
Definition: Vector2.hpp:25
bool operator!=(const Vector2T< T > &B) const
Returns whether this vector and B are not equal (bit-wise).
Definition: Vector2.hpp:147
Vector2T()
The default constructor. It initializes all components to zero.
Definition: Vector2.hpp:31
Division by zero error.
Definition: Errors.hpp:24
Vector2T< T > GetScaled(const Vector2T< T > &S) const
Returns a copy of this vector non-uniformely scaled by S.
Definition: Vector2.hpp:121