C plus plus:Tutorials:Vectors

From GPWiki
Jump to: navigation, search

A general-purpose templated two-dimensional vector in C++. Supports most operations you'd expect in a vector. The internal array representation is meant to make passing it to OpenGL easier. Just do for example glVertex2iv(my_vector_var).

There is also an alternate version of a math vector.

#ifndef VECTOR2_HPP
#define VECTOR2_HPP
 
#include <cmath>
#include <iosfwd>
 
template<class T>
class Vector2
{
 public:
  Vector2()
  {
    set(T(), T());
  }
  Vector2(T new_x, T new_y)
  {
    set(new_x, new_y);
  }
  explicit Vector2(T value)
  {
    set(value, value);
  }
 
  void set(T new_x, T new_y)
  {
    x() = new_x;
    y() = new_y;
  }
 
  T& x(){return _c[0];}
  T& y(){return _c[1];}
  T x() const{return _c[0];}
  T y() const{return _c[1];}
 
  void operator=(T value)
  {
    set(value, value);
  }
 
  void operator+=(const Vector2& other)
  {
    set(x() + other.x(), y() + other.y());
  }
  void operator-=(const Vector2& other)
  {
    set(x() - other.x(), y() - other.y());
  }
  void operator*=(T factor)
  {
    set(x() * factor, y() * factor);
  }
  void operator/=(T factor)
  {
    set(x() / factor, y() / factor);
  }
 
  T lengthSquared() const
  {
    return x()*x() + y()*y();
  }
  T length() const
  {
    return std::sqrt(lengthSquared());
  }
  void normalize()
  {
    operator/=(length());
  }
  void invert()
  {
    x() = -x();
    y() = -y();
  }
 
  operator const T*() const
  {
    return _c;
  }
 
  template <class U>
  Vector2<U> convert() const
  {
    return Vector2<U>(static_cast<U>(x()), static_cast<U>(y()));
  }
 
 private:
  T _c[2];
};
 
template<class T>
inline const Vector2<T> operator+(const Vector2<T>& one, const Vector2<T>& two)
{
  return Vector2<T>(one.x() + two.x(), one.y() + two.y());
}
template<class T>
inline const Vector2<T> operator-(const Vector2<T>& one, const Vector2<T>& two)
{
  return Vector2<T>(one.x() - two.x(), one.y() - two.y());
}
template<class T>
inline const Vector2<T> operator-(const Vector2<T>& one)
{
  return Vector2<T>(-one.x(), -one.y());
}
template<class T>
inline const Vector2<T> operator*(const Vector2<T>& one, T factor)
{
  return Vector2<T>(one.x() * factor, one.y() * factor);
}
template<class T>
inline const Vector2<T> operator*(T factor, const Vector2<T>& one)
{
  return Vector2<T>(one.x() * factor, one.y() * factor);
}
template<class T>
inline const Vector2<T> operator/(const Vector2<T>& one, T factor)
{
  return Vector2<T>(one.x() / factor, one.y() / factor);
}
 
template<class T>
inline T operator*(const Vector2<T>& one, const Vector2<T>& two){ //dotproduct
  return one.x() * two.x() + one.y() * two.y();
}
 
template<class T>
inline bool operator==(const Vector2<T>& one, const Vector2<T>& two)
{
  return one.x() == two.x() and one.y() == two.y();
}
template<class T>
inline bool operator!=(const Vector2<T>& one, const Vector2<T>& two)
{
  return !(one == two);
}
 
template<class T>
std::ostream& operator<<(std::ostream& os, const Vector2<T>& vec)
{
  os << '(' << vec.x() << ',' << ' ' << vec.y() << ')';
  return os;
}
 
typedef Vector2<float> Vector2f;
typedef Vector2<int> Vector2i;
typedef Vector2<size_t> Vector2u;
 
#endif //VECTOR2_HPP

And it's three-dimensional brother.

#ifndef VECTOR3_HPP
#define VECTOR3_HPP
 
#include <iosfwd>
#include <cmath>
 
template <class T>
class Vector3
{
 public:
  Vector3()
  {
    set(T(), T(), T());
  }
  Vector3(T new_x, T new_y, T new_z)
  {
    set(new_x, new_y, new_z);
  }
  explicit Vector3(T value)
  {
    set(value, value, value);
  }
 
  void set(T new_x, T new_y, T new_z)
  {
    x() = new_x;
    y() = new_y;
    z() = new_z;
  }
 
  T& x(){return _c[0];}
  T& y(){return _c[1];}
  T& z(){return _c[2];}
  T x() const{return _c[0];}
  T y() const{return _c[1];}
  T z() const{return _c[2];}
 
  void operator=(T value)
  {
    set(value, value, value);
  }
 
  void operator+=(const Vector3& other)
  {
    set(x() + other.x(), y() + other.y(), z() + other.z());
  }
  void operator-=(const Vector3& other)
  {
    set(x() - other.x(), y() - other.y(), z() - other.z());
  }
  void operator*=(T factor)
  {
    set(x() * factor, y() * factor, z() * factor);
  }
  void operator/=(T factor)
  {
    set(x() / factor, y() / factor, z() / factor);
  }
 
  T lengthSquared() const
  {
    return x()*x() + y()*y() + z()*z();
  }
  T length() const
  {
    return std::sqrt(lengthSquared());
  }
  void normalize()
  {
    operator/=(length());
  }
  void invert()
  {
    x() = -x();
    y() = -y();
    z() = -z();
  }
 
  operator const T*() const
  {
    return _c;
  }
 
  template <class U>
  Vector3<U> convert() const
  {
    return Vector3<U>(static_cast<U>(x()), static_cast<U>(y()), static_cast<U>(z()));
  }
 
 private:
  T _c[3];
};
 
template <class T>
inline const Vector3<T> operator+(const Vector3<T>& one, const Vector3<T>& two)
{
  return Vector3<T>(one.x() + two.x(), one.y() + two.y(), one.z() + two.z());
}
template <class T>
inline const Vector3<T> operator-(const Vector3<T>& one, const Vector3<T>& two)
{
  return Vector3<T>(one.x() - two.x(), one.y() - two.y(), one.z() - two.z());
}
template <class T>
inline const Vector3<T> operator-(const Vector3<T>& one)
{
  return Vector3<T>(-one.x(), -one.y(), -one.z());
}
template <class T>
inline const Vector3<T> operator*(const Vector3<T>& one, T factor)
{
  return Vector3<T>(one.x() * factor, one.y() * factor, one.z() * factor);
}
template <class T>
inline const Vector3<T> operator*(T factor, const Vector3<T>& one)
{
  return Vector3<T>(one.x() * factor, one.y() * factor, one.z() * factor);
}
template <class T>
inline const Vector3<T> operator/(const Vector3<T>& one, T factor)
{
  return Vector3<T>(one.x() / factor, one.y() / factor, one.z() / factor);
}
 
template <class T>
inline T operator*(const Vector3<T>& one, const Vector3<T>& two){ //dotproduct
  return one.x()*two.x() + one.y()*two.y() + one.z()*two.z();
}
template <class T>
inline T boundedDot(const Vector3<T>& one, const Vector3<T>& two)
{
  T dot = one * two;
  if (dot < 0)
    return 0;
  if (dot > 1)
    return 1;
  return dot;
}
template <class T>
inline Vector3<T> operator%(const Vector3<T>& one, const Vector3<T> two){ //crossproduct
  return Vector3<T>(one.y()*two.z() - one.z()*two.y(), one.z()*two.x() - one.x()*two.z(), 
		    one.x()*two.y() - one.y()*two.x());
}
 
template <class T>
inline Vector3<T> normalize(const Vector3<T>& vec){return vec / vec.length();}
 
template <class T>
inline bool operator==(const Vector3<T>& one, const Vector3<T>& two)
{
  return one.x() == two.x() and one.y() == two.y() and one.z() == two.z();
}
template <class T>
inline bool operator!=(const Vector3<T>& one, const Vector3<T>& two)
{
  return !(one == two);
}
 
template<class T>
std::ostream& operator<<(std::ostream& os, const Vector3<T>& vec)
{
  os << '(' << vec.x() << ',' << ' ' << vec.y() << ',' << ' ' << vec.z() << ')';
  return os;
}
 
typedef Vector3<float> Vector3f;
typedef Vector3<int> Vector3i;
typedef Vector3<size_t> Vector3u;
 
#endif //VECTOR3_HPP