Added replacement vector class.

This commit is contained in:
David Williams 2008-02-09 17:50:10 +00:00
parent 38b266d261
commit 9138ae51da
2 changed files with 604 additions and 0 deletions

117
include/Vector.hpp Normal file
View File

@ -0,0 +1,117 @@
#ifndef VECTOR_HEADER_INCLUDED
#define VECTOR_HEADER_INCLUDED
#include <boost\operators.hpp>
//#include "..\Base\Typedef.hpp"
#include "boost/cstdint.hpp"
namespace Ogre
{
//template <boost::uint32_t Size, typename Type> class Matrix; //Forward declaration
///Represents a vector in space.
template <boost::uint32_t Size, typename Type>
class Vector
: boost::addable< Vector<Size,Type> // Vector + Vector
, boost::subtractable< Vector<Size,Type> // Vector - Vector
, boost::dividable2< Vector<Size,Type>, Type // Vector / Type
, boost::multipliable2< Vector<Size,Type>, Type // Vector * Type, Type * Vector
, boost::equality_comparable1< Vector<Size,Type> // Vector != Vector
> > > > >
{
public:
///Constructor.
Vector(Type x, Type y) throw();
///Constructor.
Vector(Type x, Type y, Type z) throw();
///Constructor.
Vector(Type x, Type y, Type z, Type w) throw();
///Constructor
Vector(void) throw();
///Copy Constructor.
Vector(const Vector<Size,Type>& vector) throw();
///Copy Constructor which performs casting.
template <typename CastType> explicit Vector(const Vector<Size,CastType>& vector) throw();
///Destructor.
~Vector(void) throw();
///Assignment Operator.
Vector<Size,Type>& operator=(const Vector<Size,Type>& rhs) throw();
///Equality Operator.
bool operator==(const Vector<Size,Type>& rhs) const throw();
///Addition and Assignment Operator.
Vector<Size,Type>& operator+=(const Vector<Size,Type> &rhs) throw();
///Subtraction and Assignment Operator.
Vector<Size,Type>& operator-=(const Vector<Size,Type> &rhs) throw();
///Multiplication and Assignment Operator.
Vector<Size,Type>& operator*=(const Type& rhs) throw();
///Division and Assignment Operator.
Vector<Size,Type>& operator/=(const Type& rhs) throw();
///Element Access
Type operator()(boost::uint32_t index) const throw();
///Get the x component of the vector.
Type x(void) const throw();
///Get the y component of the vector.
Type y(void) const throw();
///Get the z component of the vector.
Type z(void) const throw();
///Get the w component of the vector.
Type w(void) const throw();
///Element Access
void set(boost::uint32_t index, Type tValue) throw();
///Set the x component of the vector.
void setX(Type tX) throw();
///Set the y component of the vector.
void setY(Type tY) throw();
///Set the z component of the vector.
void setZ(Type tZ) throw();
///Set the w component of the vector.
void setW(Type tW) throw();
///Get the length of the vector.
double length(void) const throw();
///Get the squared length of the vector.
double lengthSquared(void) const throw();
///Find the angle between this vector and that which is passed as a parameter.
double angleTo(const Vector<Size,Type>& vector) const throw();
///Find the cross product between this vector and the vector passed as a parameter.
Vector<Size,Type> cross(const Vector<Size,Type>& vector) const throw();
///Find the dot product between this vector and the vector passed as a parameter.
Type dot(const Vector<Size,Type>& rhs) const throw();
///Normalise the vector.
void normalise(void) throw();
private:
//Values for the vector
Type m_tElements[Size];
};
//Non-member overloaded operators.
//!Multiplication operator.
//template <boost::uint32_t Size,typename Type>
//Vector<Size,Type> operator*(const Vector<Size,Type>& lhs, const Matrix<Size,Type>& rhs) throw();
//!Multiplication operator.
//template <boost::uint32_t Size,typename Type>
//Vector<Size,Type> operator*(const Matrix<Size,Type>& lhs, const Vector<Size,Type>& rhs) throw();
///Stream insertion operator.
template <boost::uint32_t Size, typename Type>
std::ostream& operator<<(std::ostream& os, const Vector<Size,Type>& vector) throw();
//Some handy typedefs
typedef Vector<2,float> Vector2DFloat;
typedef Vector<2,double> Vector2DDouble;
typedef Vector<2,boost::int32_t> Vector2DInt32;
typedef Vector<2,boost::uint32_t> Vector2DUint32;
typedef Vector<3,float> Vector3DFloat;
typedef Vector<3,double> Vector3DDouble;
typedef Vector<3,boost::int32_t> Vector3DInt32;
typedef Vector<3,boost::uint32_t> Vector3DUint32;
}//namespace Thermite
#include "Vector.inl"
#endif

487
include/Vector.inl Normal file
View File

@ -0,0 +1,487 @@
#include <cassert>
#include <cmath>
#include <string>
namespace Ogre
{
/**
This Vector class is templated on both size and data type. It is designed to be
generic but so far had only been tested with vectors of size 2 and 3. Also note
that some of the operations do not make sense with integer types, for example it
does not make conceptual sense to try and normalise an integer Vector.
The elements of the Vector are accessed via the overloaded () operator which takes
an index indicating the element to fetch. They are set using the set() function which
takes an index indicating the element to set and a new value for that element. For
convienience, the functions x(), setX(), y(), setY(), z(), setZ, w() and setW()
do the same thing for the first 4 elements of the Vector.
A variety of overloaded operators are also provided for comparison and arithmetic
operations. For most of these arithmetic operators only the unary versions are
documented below - however often binary versions are also generated by boost::operators.
Lastly, note that for convienience a set of typedefs are included for 2 and 3 dimentionsal
vectors with type float, double, boost::int32_t, and boost::uint32_t. They are used as follows:
Vector2DInt4 test(1,2); //Declares a 2 dimensional Vector of type int4.
*/
//-------------------------- Constructors, etc ---------------------------------
/**
Creates a Vector object and initialises it with given values.
\param x x component to set.
\param y y component to set.
*/
template <boost::uint32_t Size,typename Type>
Vector<Size,Type>::Vector(Type x, Type y) throw()
{
m_tElements[0] = x;
m_tElements[1] = y;
}
/**
Creates a Vector3D object and initialises it with given values.
\param x x component to set.
\param y y component to set.
\param z z component to set.
*/
template <boost::uint32_t Size,typename Type>
Vector<Size,Type>::Vector(Type x, Type y, Type z) throw()
{
m_tElements[0] = x;
m_tElements[1] = y;
m_tElements[2] = z;
}
/**
Creates a Vector3D object and initialises it with given values.
\param x x component to set.
\param y y component to set.
\param z z component to set.
\param w w component to set.
*/
template <boost::uint32_t Size,typename Type>
Vector<Size,Type>::Vector(Type x, Type y, Type z, Type w) throw()
{
m_tElements[0] = x;
m_tElements[1] = y;
m_tElements[2] = z;
m_tElements[3] = w;
}
/**
Creates a Vector object but does not initialise it.
*/
template <boost::uint32_t Size, typename Type>
Vector<Size, Type>::Vector(void) throw()
{
}
/**
Copy constructor builds object based on object passed as parameter.
\param vector A reference to the Vector to be copied.
*/
template <boost::uint32_t Size, typename Type>
Vector<Size, Type>::Vector(const Vector<Size, Type>& vector) throw()
{
std::memcpy(m_tElements, vector.m_tElements, sizeof(Type) * Size);
}
/**
This copy constructor allows casting between vectors with different data types.
It is now possible to use code such as:
Vector3DDouble v3dDouble(1.0,2.0,3.0);
Vector3DFloat v3dFloat = static_cast<Vector3DFloat>(v3dDouble); //Casting
\param vector A reference to the Vector to be copied.
*/
template <boost::uint32_t Size, typename Type>
template <typename CastType>
Vector<Size, Type>::Vector(const Vector<Size, CastType>& vector) throw()
{
for(boost::uint32_t ct = 0; ct < Size; ++ct)
{
m_tElements[ct] = static_cast<CastType>(vector(ct));
}
}
/**
Destroys the Vector.
*/
template <boost::uint32_t Size, typename Type>
Vector<Size, Type>::~Vector(void) throw()
{
}
//------------------------------- Overloaded Operators -------------------------
/**
Assignment operator copies each element of first Vector to the second.
\param rhs Vector to assign to.
\return A reference to the result to allow chaining.
*/
template <boost::uint32_t Size, typename Type>
Vector<Size, Type>& Vector<Size, Type>::operator=(const Vector<Size, Type>& rhs) throw()
{
if(this == &rhs)
{
return *this;
}
std::memcpy(m_tElements, rhs.m_tElements, sizeof(Type) * Size);
return *this;
}
/**
Checks whether two Vectors are equal.
\param rhs The Vector to compare to.
\return true if the Vectors match.
\see operator!=
*/
template <boost::uint32_t Size, typename Type>
inline bool Vector<Size, Type>::operator==(const Vector<Size, Type> &rhs) const throw()
{
bool equal = true;
for(boost::uint32_t ct = 0; ct < Size; ++ct)
{
if(m_tElements[ct] != rhs(ct))
{
equal = false;
break;
}
}
return equal;
}
/**
Subtraction operator subtracts corresponding elements of one Vector from the other.
\param rhs Vector to subtract
\return The resulting Vector.
*/
template <boost::uint32_t Size, typename Type>
inline Vector<Size, Type>& Vector<Size, Type>::operator-=(const Vector<Size, Type>& rhs) throw()
{
for(boost::uint32_t ct = 0; ct < Size; ++ct)
{
m_tElements[ct] -= rhs.m_tElements[ct];
}
return *this;
}
/**
Addition operator adds corresponding elements of the two Vectors.
\param rhs Vector to add
\return The resulting Vector.
*/
template <boost::uint32_t Size, typename Type>
inline Vector<Size, Type>& Vector<Size, Type>::operator+=(const Vector<Size, Type>& rhs) throw()
{
for(boost::uint32_t ct = 0; ct < Size; ++ct)
{
m_tElements[ct] += rhs.m_tElements[ct];
}
return *this;
}
/**
Multiplication operator multiplies each element of the Vector by a number.
\param rhs the number the Vector is multiplied by.
\return The resulting Vector.
*/
template <boost::uint32_t Size, typename Type>
inline Vector<Size, Type>& Vector<Size, Type>::operator*=(const Type& rhs) throw()
{
for(boost::uint32_t ct = 0; ct < Size; ++ct)
{
m_tElements[ct] *= rhs;
}
return *this;
}
/**
Division operator divides each element of the Vector by a number.
\param rhs the number the Vector is divided by.
\return The resulting Vector.
*/
template <boost::uint32_t Size, typename Type>
inline Vector<Size, Type>& Vector<Size, Type>::operator/=(const Type& rhs) throw()
{
for(boost::uint32_t ct = 0; ct < Size; ++ct)
{
m_tElements[ct] /= rhs;
}
return *this;
}
/**
Multiplies a Vector and a Matrix.
NOTE: Although the Vector class does not distinguish between row and column vectors, the Vector
must <i>conceptually</i> be in <i>row</i> form for this operation to make sense.
\param lhs The Vector to be multiplied
\param rhs The Matrix to multiply by.
\return The resulting Vector
*/
/*template <boost::uint32_t Size,typename Type>
Vector<Size,Type> operator*(const Vector<Size,Type>& lhs, const Matrix<Size,Type>& rhs) throw()
{
Type tZero = static_cast<Type>(0);
Vector<Size,Type> result(tZero,tZero,tZero);
for(boost::uint32_t colCt = 0; colCt < Size; ++colCt)
{
for(boost::uint32_t rowCt = 0; rowCt < Size; ++rowCt)
{
//result(colCt) += lhs(rowCt) * rhs(rowCt, colCt);
result.set(colCt, result(colCt) + (lhs(rowCt) * rhs(rowCt, colCt)));
}
}
return result;
}*/
/**
Multiplies a Matrix and a Vector.
NOTE: Although the Vector class does not distinguish between row and column vectors, the Vector
must <i>conceptually</i> be in <i>column</i> form for this operation to make sense.
\param lhs The Matrix to be multiplied
\param rhs The Vector to multiply by.
\return The resulting Vector
*/
/*template <boost::uint32_t Size,typename Type>
Vector<Size,Type> operator*(const Matrix<Size,Type>& lhs, const Vector<Size,Type>& rhs) throw()
{
Type tZero = static_cast<Type>(0);
Vector<Size,Type> result(tZero,tZero,tZero);
for(boost::uint32_t rowCt = 0; rowCt < Size; ++rowCt)
{
for(boost::uint32_t colCt = 0; colCt < Size; ++colCt)
{
//result(rowCt) += lhs(rowCt,colCt) * rhs(colCt);
result.set(rowCt, result(rowCt) + (lhs(rowCt,colCt) * rhs(colCt)));
}
}
return result;
}*/
/**
Enables the Vector to be used intuitively with output streams such as cout.
\param os The output stream to write to.
\param vector The Vector to write to the stream.
\return A reference to the output stream to allow chaining.
*/
template <boost::uint32_t Size, typename Type>
std::ostream& operator<<(std::ostream& os, const Vector<Size, Type>& vector) throw()
{
os << "(";
for(boost::uint32_t ct = 0; ct < Size; ++ct)
{
os << vector(ct);
if(ct < (Size-1))
{
os << ",";
}
}
os << ")";
return os;
}
/**
Returns the element at the given position.
\param index The index of the element to return.
\return The element.
*/
template <boost::uint32_t Size, typename Type>
inline Type Vector<Size, Type>::operator()(boost::uint32_t index) const throw()
{
return m_tElements[index];
}
//----------------------------------- Getters ----------------------------------
/**
\return A const reference to the X component of a 1, 2, 3, or 4 dimensional Vector.
*/
template <boost::uint32_t Size, typename Type>
inline Type Vector<Size, Type>::x(void) const throw()
{
return m_tElements[0];
}
/**
\return A const reference to the Y component of a 2, 3, or 4 dimensional Vector.
*/
template <boost::uint32_t Size, typename Type>
inline Type Vector<Size, Type>::y(void) const throw()
{
return m_tElements[1];
}
/**
\return A const reference to the Z component of a 3 or 4 dimensional Vector.
*/
template <boost::uint32_t Size, typename Type>
inline Type Vector<Size, Type>::z(void) const throw()
{
return m_tElements[2];
}
/**
\return A const reference to the W component of a 4 dimensional Vector.
*/
template <boost::uint32_t Size, typename Type>
inline Type Vector<Size, Type>::w(void) const throw()
{
return m_tElements[3];
}
//----------------------------------- Setters ----------------------------------
/**
\param index The index of the element to set.
\param tValue The new value for the element.
*/
template <boost::uint32_t Size, typename Type>
inline void Vector<Size, Type>::set(boost::uint32_t index, Type tValue) throw()
{
m_tElements[index] = tValue;
}
/**
\param tX The new value for the X component of a 1, 2, 3, or 4 dimensional Vector.
*/
template <boost::uint32_t Size, typename Type>
inline void Vector<Size, Type>::setX(Type tX) throw()
{
m_tElements[0] = tX;
}
/**
\param tX The new value for the Y component of a 2, 3, or 4 dimensional Vector.
*/
template <boost::uint32_t Size, typename Type>
inline void Vector<Size, Type>::setY(Type tY) throw()
{
m_tElements[1] = tY;
}
/**
\param tX The new value for the Z component of a 3 or 4 dimensional Vector.
*/
template <boost::uint32_t Size, typename Type>
inline void Vector<Size, Type>::setZ(Type tZ) throw()
{
m_tElements[2] = tZ;
}
/**
\param tX The new value for the W component of a 4 dimensional Vector.
*/
template <boost::uint32_t Size, typename Type>
inline void Vector<Size, Type>::setW(Type tW) throw()
{
m_tElements[3] = tW;
}
//-------------------------------- Other Functions -----------------------------
/**
NOTE: This function does not make much sense on integer Vectors.
\return Length of the Vector.
*/
template <boost::uint32_t Size, typename Type>
inline double Vector<Size, Type>::length(void) const throw()
{
return sqrt(lengthSquared());
}
/**
\return Squared length of the Vector.
*/
template <boost::uint32_t Size, typename Type>
inline double Vector<Size, Type>::lengthSquared(void) const throw()
{
double result = 0.0f;
for(boost::uint32_t ct = 0; ct < Size; ++ct)
{
result += m_tElements[ct] * m_tElements[ct];
}
return result;
}
/**
This function is commutative, such that a.angleTo(b) == b.angleTo(a). The angle
returned is in radians and varies between 0 and 3.14(pi). It is always positive.
NOTE: This function does not make much sense on integer Vectors.
\param Vector3D The Vector to find the angle to.
\return The angle between them in radians.
*/
template <boost::uint32_t Size, typename Type>
inline double Vector<Size, Type>::angleTo(const Vector<Size, Type>& vector) const throw()
{
return acos(dot(vector) / (vector.length() * this->length()));
}
/**
This function is used to calculate the cross product of two Vectors.
The cross product is the Vector which is perpendicular to the two
given Vectors. It is worth remembering that, unlike the dot product,
it is not commutative. E.g a.b != b.a. The cross product obeys the
right-hand rule such that if the two vectors are given by the index
finger and middle finger respectively then the cross product is given
by the thumb.
\param a first Vector.
\param b Second Vector.
\return The value of the cross product.
\see dot()
*/
template <boost::uint32_t Size, typename Type>
inline Vector<Size, Type> Vector<Size, Type>::cross(const Vector<Size, Type>& vector) const throw()
{
Type i = vector.z() * this->y() - vector.y() * this->z();
Type j = vector.x() * this->z() - vector.z() * this->x();
Type k = vector.y() * this->x() - vector.x() * this->y();
return Vector<Size, Type>(i,j,k);
}
/**
Calculates the dot product of the Vector and the parameter.
This function is commutative, such that a.dot(b) == b.dot(a).
\param rhs The Vector to find the dot product with.
\return The value of the dot product.
\see cross()
*/
template <boost::uint32_t Size, typename Type>
inline Type Vector<Size, Type>::dot(const Vector<Size, Type>& rhs) const throw()
{
Type dotProduct = static_cast<Type>(0);
for(boost::uint32_t ct = 0; ct < Size; ++ct)
{
dotProduct += m_tElements[ct] * rhs.m_tElements[ct];
}
return dotProduct;
}
/**
Divides the i, j, and k components by the length to give a Vector of length 1.0.
NOTE: This function does not make much sense on integer Vectors.
*/
template <boost::uint32_t Size, typename Type>
inline void Vector<Size, Type>::normalise(void) throw()
{
double length = this->length();
//FIXME - throw div by zero exception?
if(length < 0.0001f)
{
return;
}
for(boost::uint32_t ct = 0; ct < Size; ++ct)
{
m_tElements[ct] /= length;
}
}
}//namespace Thermite