|
|
#ifndef _VecMath_h
#define _VecMath_h
// File: VecMath.h
//
// Classes to support 2D and 3D linear vector space and their duals
// D. P. Mitchell 95/06/02.
//
// History:
// -@- 07/06/95 (mikemarr) - added Print and Read functions
// -@- 08/01/95 (mikemarr) - added fuzzy compare for floats
// -@- 04/15/96 (mikemarr) - changed stdio stuff to don's stream stuff
// -@- 04/18/96 (mikemarr) - added vector.inl to this file
// -@- 06/21/96 (mikemarr) - added +=, etc. operators
// -@- 06/21/96 (mikemarr) - added Rotate
// -@- 10/29/97 (mikemarr) - removed I/O
// - changed +=,-=,*=,/= operators to return reference
// - added operator const float *
// - added Unitize, Perp, NormSquared, SetNorm, Negate
// - comments/cleanup
// - changed fuzzy equal to be IsEqual, operator == to be exact
// - bug fix on Transpose
// - changed multiple divides to be 1 divide + multiplies
// - assert on divide by zero
// -@- 11/04/97 (mikemarr) - added intialization with SIZE
// Function: FloatEquals
// Peform a "fuzzy" compare of two floating point numbers. This relies
// on the IEEE bit representation of floating point numbers.
int FloatEquals(float x1, float x2);
class CoVector2; class CoVector3; class Vector3;
// Class: Vector2
// Hungarian: v
// Description:
// This class represents a floating point 2D column vector useful for computational
// geometry calculations.
class Vector2 { public: Vector2() {} Vector2(float a, float b) : x(a), y(b) {} Vector2(const SIZE &siz) : x(float(siz.cx)), y(float(siz.cy)) {}
friend Vector2 operator +(const Vector2 &u, const Vector2 &v); friend Vector2 operator -(const Vector2 &u, const Vector2 &v); friend Vector2 operator -(const Vector2 &u); friend Vector2 operator *(const Vector2 &u, float a); friend Vector2 operator *(float a, const Vector2 &u); friend Vector2 operator /(const Vector2 &u, float a); friend int operator ==(const Vector2 &u, const Vector2 &v); friend int operator !=(const Vector2 &u, const Vector2 &v);
friend Vector2 & operator +=(Vector2 &u, const Vector2 &v); friend Vector2 & operator -=(Vector2 &u, const Vector2 &v); friend Vector2 & operator *=(Vector2 &u, float a); friend Vector2 & operator /=(Vector2 &u, float a);
#ifndef DISABLE_CROSSDOT
friend float Cross(const Vector2 &u, const Vector2 &v); friend float Dot(const Vector2 &u, const Vector2 &v); #endif
friend int IsEqual(const Vector2 &u, const Vector2 &v);
operator const float *() const { return &x; }
CoVector2 Transpose() const; float Norm() const; float NormSquared() const; void SetNorm(float a); Vector2 Unit() const; void Unitize(); Vector2 Perp() const; // points to left
void Negate();
public: float x, y; };
// Class: CoVector2
// Hungarian: cv
// Description:
// This class represents a floating point 2D row vector useful for computational
// geometry calculations.
class CoVector2 { public: CoVector2() {} CoVector2(float a, float b) : x(a), y(b) {} CoVector2(const SIZE &siz) : x(float(siz.cx)), y(float(siz.cy)) {}
friend CoVector2 operator +(const CoVector2 &u, const CoVector2 &v); friend CoVector2 operator -(const CoVector2 &u, const CoVector2 &v); friend CoVector2 operator -(const CoVector2 &u); friend CoVector2 operator *(const CoVector2 &u, float a); friend CoVector2 operator *(float a, const CoVector2 &u); friend CoVector2 operator /(const CoVector2 &u, float a); friend int operator ==(const CoVector2 &u, const CoVector2 &v); friend int operator !=(const CoVector2 &u, const CoVector2 &v);
friend CoVector2 & operator +=(CoVector2 &u, const CoVector2 &v); friend CoVector2 & operator -=(CoVector2 &u, const CoVector2 &v); friend CoVector2 & operator *=(CoVector2 &u, float a); friend CoVector2 & operator /=(CoVector2 &u, float a);
#ifndef DISABLE_CROSSDOT
friend float Cross(const CoVector2 &u, const CoVector2 &v); friend float Dot(const CoVector2 &u, const CoVector2 &v); #endif
friend int IsEqual(const CoVector2 &u, const CoVector2 &v);
operator const float *() const { return &x; }
Vector2 Transpose() const; float Norm() const; float NormSquared() const; void SetNorm(float a); CoVector2 Unit() const; void Unitize(); friend float operator *(const CoVector2 &c, const Vector2 &v); CoVector2 Perp() const; // points to left
void Negate();
public: float x, y; };
// Class: Vector3
// Hungarian: v
// Description:
// This class represents a floating point 3D column vector useful for computational
// geometry calculations.
class Vector3 { public: Vector3() {} Vector3(float a, float b, float c) : x(a), y(b), z(c) {}
friend Vector3 operator +(const Vector3 &u, const Vector3 &v); friend Vector3 operator -(const Vector3 &u, const Vector3 &v); friend Vector3 operator -(const Vector3 &u); friend Vector3 operator *(const Vector3 &u, float a); friend Vector3 operator *(float a, const Vector3 &u); friend Vector3 operator /(const Vector3 &u, float a); friend int operator ==(const Vector3 &u, const Vector3 &v); friend int operator !=(const Vector3 &u, const Vector3 &v);
friend Vector3 & operator +=(Vector3 &u, const Vector3 &v); friend Vector3 & operator -=(Vector3 &u, const Vector3 &v); friend Vector3 & operator *=(Vector3 &u, float a); friend Vector3 & operator /=(Vector3 &u, float a);
#ifndef DISABLE_CROSSDOT
friend Vector3 Cross(const Vector3 &u, const Vector3 &v); friend float Dot(const Vector3 &u, const Vector3 &v); #endif
friend int IsEqual(const Vector3 &u, const Vector3 &v);
operator const float *() const { return &x; }
CoVector3 Transpose() const; float Norm() const; float NormSquared() const; void SetNorm(float a); Vector3 Unit() const; void Unitize(); Vector2 Project(DWORD iAxis) const; void Rotate(const Vector3 &vAxis, float fTheta); void Negate();
public: float x, y, z; };
// Class: CoVector3
// Hungarian: cv
// Description:
// This class represents a floating point 3D row vector useful for computational
// geometry calculations.
class CoVector3 { public: CoVector3() {} CoVector3(float a, float b, float c) : x(a), y(b), z(c) {}
friend CoVector3 operator +(const CoVector3 &u, const CoVector3 &v); friend CoVector3 operator -(const CoVector3 &u, const CoVector3 &v); friend CoVector3 operator -(const CoVector3 &u); friend CoVector3 operator *(const CoVector3 &u, float a); friend CoVector3 operator *(float, const CoVector3 &u); friend CoVector3 operator /(const CoVector3 &u, float a); friend int operator ==(const CoVector3 &u, const CoVector3 &v); friend int operator !=(const CoVector3 &u, const CoVector3 &v);
friend CoVector3 & operator +=(CoVector3 &u, const CoVector3 &v); friend CoVector3 & operator -=(CoVector3 &u, const CoVector3 &v); friend CoVector3 & operator *=(CoVector3 &u, float a); friend CoVector3 & operator /=(CoVector3 &u, float a);
#ifndef DISABLE_CROSSDOT
friend CoVector3 Cross(const CoVector3 &u, const CoVector3 &v); friend float Dot(const CoVector3 &u, const CoVector3 &v); #endif
friend int IsEqual(const CoVector3 &u, const CoVector3 &v);
operator const float *() const { return &x; }
Vector3 Transpose() const; float Norm() const; float NormSquared() const; void SetNorm(float a); CoVector3 Unit() const; void Unitize(); friend float operator *(const CoVector3 &c, const Vector3 &u); // linear form
void Negate();
public: float x, y, z; };
////////////
// Vector2
////////////
inline Vector2 operator +(const Vector2 &u, const Vector2 &v) { return Vector2(u.x+v.x, u.y+v.y); }
inline Vector2 operator -(const Vector2 &u, const Vector2 &v) { return Vector2(u.x-v.x, u.y-v.y); }
inline Vector2 operator -(const Vector2 &v) { return Vector2(-v.x, -v.y); }
inline Vector2 operator *(float a, const Vector2 &v) { return Vector2(a*v.x, a*v.y); }
inline Vector2 operator *(const Vector2 &v, float a) { return Vector2(a*v.x, a*v.y); }
inline Vector2 operator /(const Vector2 &v, float a) { MMASSERT(a != 0.f); float fTmp = 1.f/a; return Vector2(v.x * fTmp, v.y * fTmp); }
inline int operator ==(const Vector2 &u, const Vector2 &v) { return ((u.x == v.x) && (u.y == v.y)); }
inline int IsEqual(const Vector2 &u, const Vector2 &v) { return (FloatEquals(u.x, v.x) && FloatEquals(u.y, v.y)); }
inline int operator !=(const Vector2 &u, const Vector2 &v) { return !(u == v); }
inline Vector2 & operator +=(Vector2 &u, const Vector2 &v) { u.x += v.x; u.y += v.y; return u; }
inline Vector2 & operator -=(Vector2 &u, const Vector2 &v) { u.x -= v.x; u.y -= v.y; return u; }
inline Vector2 & operator *=(Vector2 &u, float a) { u.x *= a; u.y *= a; return u; }
inline Vector2 & operator /=(Vector2 &u, float a) { MMASSERT(a != 0.f); float fTmp = 1.f/a; u.x *= fTmp; u.y *= fTmp; return u; }
#ifndef DISABLE_CROSSDOT
inline float Cross(const Vector2 &u, const Vector2 &v) { return u.x*v.y - u.y*v.x; }
inline float Dot(const Vector2 &u, const Vector2 &v) { return u.x*v.x + u.y*v.y; } #endif
inline CoVector2 Vector2::Transpose() const { return CoVector2(x, y); }
inline Vector2 Vector2::Unit() const { return *this/this->Norm(); }
inline void Vector2::Unitize() { *this /= this->Norm(); }
inline Vector2 Vector2::Perp() const { return Vector2(-y, x); }
inline float Vector2::NormSquared() const { return x*x + y*y; }
inline void Vector2::SetNorm(float a) { *this *= (a / Norm()); }
inline void Vector2::Negate() { x = -x; y = -y; }
//////////////
// CoVector2
//////////////
inline CoVector2 operator +(const CoVector2 &u, const CoVector2 &v) { return CoVector2(u.x+v.x, u.y+v.y); }
inline CoVector2 operator -(const CoVector2 &u, const CoVector2 &v) { return CoVector2(u.x-v.x, u.y-v.y); }
inline CoVector2 operator -(const CoVector2 &v) { return CoVector2(-v.x, -v.y); }
inline CoVector2 operator *(float a, const CoVector2 &v) { return CoVector2(a*v.x, a*v.y); }
inline CoVector2 operator *(const CoVector2 &v, float a) { return CoVector2(a*v.x, a*v.y); }
inline CoVector2 operator /(const CoVector2 &v, float a) { MMASSERT(a != 0.f); float fTmp = 1.f/a; return CoVector2(v.x * fTmp, v.y * fTmp); }
inline int operator ==(const CoVector2 &u, const CoVector2 &v) { return ((u.x == v.x) && (u.y == v.y)); }
inline int IsEqual(const CoVector2 &u, const CoVector2 &v) { return (FloatEquals(u.x, v.x) && FloatEquals(u.y, v.y)); }
inline int operator !=(const CoVector2 &u, const CoVector2 &v) { return !(u == v); }
inline CoVector2 & operator +=(CoVector2 &u, const CoVector2 &v) { u.x += v.x; u.y += v.y; return u; }
inline CoVector2 & operator -=(CoVector2 &u, const CoVector2 &v) { u.x -= v.x; u.y -= v.y; return u; }
inline CoVector2 & operator *=(CoVector2 &u, float a) { u.x *= a; u.y *= a; return u; }
inline CoVector2 & operator /=(CoVector2 &u, float a) { MMASSERT(a != 0.f); float fTmp = 1.f/a; u.x *= fTmp; u.y *= fTmp; return u; }
#ifndef DISABLE_CROSSDOT
inline float Cross(const CoVector2 &u, const CoVector2 &v) { return u.x*v.y - u.y*v.x; }
inline float Dot(const CoVector2 &u, const CoVector2 &v) { return u.x*v.x + u.y*v.y; } #endif
inline Vector2 CoVector2::Transpose() const { return Vector2(x, y); }
inline CoVector2 CoVector2::Unit() const { return *this/this->Norm(); }
inline void CoVector2::Unitize() { *this /= this->Norm(); }
inline float operator *(const CoVector2 &c, const Vector2 &v) { return c.x*v.x + c.y*v.y; }
inline CoVector2 CoVector2::Perp() const { return CoVector2(-y, x); }
inline float CoVector2::NormSquared() const { return x*x + y*y; }
inline void CoVector2::SetNorm(float a) { *this *= (a / Norm()); }
inline void CoVector2::Negate() { x = -x; y = -y; }
////////////
// Vector3
////////////
inline Vector3 operator +(const Vector3 &u, const Vector3 &v) { return Vector3(u.x+v.x, u.y+v.y, u.z+v.z); }
inline Vector3 operator -(const Vector3 &u, const Vector3 &v) { return Vector3(u.x-v.x, u.y-v.y, u.z-v.z); }
inline Vector3 operator -(const Vector3 &v) { return Vector3(-v.x, -v.y, -v.z); }
inline Vector3 operator *(float a, const Vector3 &v) { return Vector3(a*v.x, a*v.y, a*v.z); }
inline Vector3 operator *(const Vector3 &v, float a) { return Vector3(a*v.x, a*v.y, a*v.z); }
inline Vector3 operator /(const Vector3 &v, float a) { float fTmp = 1.f / a; return Vector3(v.x * fTmp, v.y * fTmp, v.z * fTmp); }
inline int operator ==(const Vector3 &u, const Vector3 &v) { return ((u.x == v.x) && (u.y == v.y) && (u.z == v.z)); }
inline int IsEqual(const Vector3 &u, const Vector3 &v) { return (FloatEquals(u.x, v.x) && FloatEquals(u.y, v.y) && FloatEquals(u.z, v.z)); }
inline int operator !=(const Vector3 &u, const Vector3 &v) { return !(u == v); }
inline Vector3 & operator +=(Vector3 &u, const Vector3 &v) { u.x += v.x; u.y += v.y; u.z += v.z; return u; }
inline Vector3 & operator -=(Vector3 &u, const Vector3 &v) { u.x -= v.x; u.y -= v.y; u.z -= v.z; return u; }
inline Vector3 & operator *=(Vector3 &u, float a) { u.x *= a; u.y *= a; u.z *= a; return u; }
inline Vector3 & operator /=(Vector3 &u, float a) { MMASSERT(a != 0.f); float fTmp = 1.f/a; u.x *= fTmp; u.y *= fTmp; u.z *= fTmp; return u; }
#ifndef DISABLE_CROSSDOT
inline Vector3 Cross(const Vector3 &u, const Vector3 &v) { return Vector3(u.y*v.z-u.z*v.y, u.z*v.x-u.x*v.z, u.x*v.y-u.y*v.x); }
inline float Dot(const Vector3 &u, const Vector3 &v) { return u.x*v.x + u.y*v.y + u.z*v.z; } #endif
inline float operator *(const CoVector3 &c, const Vector3 &v) { return c.x*v.x + c.y*v.y + c.z*v.z; }
inline CoVector3 Vector3::Transpose() const { return CoVector3(x, y, z); }
inline Vector3 Vector3::Unit() const { return *this/this->Norm(); }
inline void Vector3::Unitize() { *this /= this->Norm(); }
inline float Vector3::NormSquared() const { return x*x + y*y + z*z; }
inline void Vector3::SetNorm(float a) { *this *= (a / Norm()); }
inline void Vector3::Negate() { x = -x; y = -y; z = -z; }
inline Vector2 Vector3::Project(DWORD iAxis) const { switch (iAxis) { case 0: return Vector2(y, z); case 1: return Vector2(x, z); case 2: return Vector2(x, y); } return Vector2(0.f, 0.f); }
//////////////
// CoVector3
//////////////
inline CoVector3 operator +(const CoVector3 &u, const CoVector3 &v) { return CoVector3(u.x+v.x, u.y+v.y, u.z+v.z); }
inline CoVector3 operator -(const CoVector3 &u, const CoVector3 &v) { return CoVector3(u.x-v.x, u.y-v.y, u.z-v.z); }
inline CoVector3 operator -(const CoVector3 &v) { return CoVector3(-v.x, -v.y, -v.z); }
inline CoVector3 operator *(float a, const CoVector3 &v) { return CoVector3(a*v.x, a*v.y, a*v.z); }
inline CoVector3 operator *(const CoVector3 &v, float a) { return CoVector3(a*v.x, a*v.y, a*v.z); }
inline CoVector3 operator /(const CoVector3 &v, float a) { MMASSERT(a != 0.f); float fTmp = 1.f/a; return CoVector3(v.x * fTmp, v.y * fTmp, v.z * fTmp); }
inline int operator ==(const CoVector3 &u, const CoVector3 &v) { return ((u.x == v.x) && (u.y == v.y) && (u.z == v.z)); }
inline int IsEqual(const CoVector3 &u, const CoVector3 &v) { return (FloatEquals(u.x, v.x) && FloatEquals(u.y, v.y) && FloatEquals(u.z, v.z)); }
inline int operator !=(const CoVector3 &u, const CoVector3 &v) { return !(u == v); }
inline CoVector3 & operator +=(CoVector3 &u, const CoVector3 &v) { u.x += v.x; u.y += v.y; u.z += v.z; return u; }
inline CoVector3 & operator -=(CoVector3 &u, const CoVector3 &v) { u.x -= v.x; u.y -= v.y; u.z -= v.z; return u; }
inline CoVector3 & operator *=(CoVector3 &u, float a) { u.x *= a; u.y *= a; u.z *= a; return u; }
inline CoVector3 & operator /=(CoVector3 &u, float a) { MMASSERT(a != 0.f); float fTmp = 1.f/a; u.x *= fTmp; u.y *= fTmp; u.z *= fTmp; return u; }
#ifndef DISABLE_CROSSDOT
inline CoVector3 Cross(const CoVector3 &u, const CoVector3 &v) { return CoVector3(u.y*v.z-u.z*v.y, u.z*v.x-u.x*v.z, u.x*v.y-u.y*v.x); }
inline float Dot(const CoVector3 &u, const CoVector3 &v) { return u.x*v.x + u.y*v.y + u.z*v.z; } #endif
inline Vector3 CoVector3::Transpose() const { return Vector3(x, y, z); }
inline CoVector3 CoVector3::Unit() const { return *this/this->Norm(); }
inline void CoVector3::Unitize() { *this /= this->Norm(); }
inline float CoVector3::NormSquared() const { return x*x + y*y + z*z; }
inline void CoVector3::SetNorm(float a) { *this *= (a / Norm()); }
inline void CoVector3::Negate() { x = -x; y = -y; z = -z; }
#endif
|