#pragma once #include "scalar.h" #include template class Vector2DOf { public: #if defined(USE_SIGNATURE) friend int Is_Signature_Bad(const volatile Vector2DOf *p); #endif // static const Vector2DOf // identity; T x, y; Vector2DOf() {} Vector2DOf(T x, T y) : x(x), y(y) {} friend Logical Small_Enough(const Vector2DOf &v, Scalar e); Logical operator!() const { return Small_Enough(*this,SMALL); } friend Logical Close_Enough(const Vector2DOf &v1, const Vector2DOf &v2, Scalar e); Logical operator==(const Vector2DOf& v) const { return Close_Enough(*this,v,SMALL); } Logical operator!=(const Vector2DOf& v) const { return !Close_Enough(*this,v,SMALL); } const T& operator[](size_t index) const { Check(this); Warn(index>Y_Axis); return (&x)[index]; } T& operator[](size_t index) { Check(this); Warn(index>Y_Axis); return (&x)[index]; } // //----------------------------------------------------------------------- // The following operators all assume that this points to the destination // of the operation results //----------------------------------------------------------------------- // Vector2DOf& Negate(const Vector2DOf &v); Vector2DOf& Add(const Vector2DOf& v1, const Vector2DOf& v2); Vector2DOf& operator+=(const Vector2DOf& v) { return Add(*this,v); } Vector2DOf& Subtract(const Vector2DOf& v1, const Vector2DOf& v2); Vector2DOf& operator-=(const Vector2DOf& v) { return Subtract(*this,v); } T operator*(const Vector2DOf& v) const { Check(this); Check(&v); return x*v.x + y*v.y; } Vector2DOf& Multiply(const Vector2DOf& v, T Scale); Vector2DOf& operator*=(T v) { return Multiply(*this,v); } Vector2DOf& Multiply(const Vector2DOf& v1, const Vector2DOf& v2); Vector2DOf& operator*=(const Vector2DOf &v) { return Multiply(*this,v); } Vector2DOf& Divide(const Vector2DOf& v, T scale); Vector2DOf& operator/=(T v) { return Divide(*this,v); } Vector2DOf& Divide(const Vector2DOf& v1, const Vector2DOf& v2); Vector2DOf& operator/=(const Vector2DOf &v) { return Divide(*this,v); } T LengthSquared() const { Check(this); return operator*(*this); } T Length() const { Check(this); return (T)Sqrt(LengthSquared()); } Vector2DOf& Normalize(const Vector2DOf &v); #if 0 Vector2DOf& Combine(const Vector2DOf& v1, Scalar t1, const Vector2DOf& v2, Scalar t2); Vector2DOf& Lerp(const Vector2DOf& v1, const Vector2DOf& v2, Scalar t) { return Combine(v1,1.0f-t,v2,t); } #endif friend std::ostream& operator<<(std::ostream& stream, const Vector2DOf& v); Logical TestInstance() const; }; #if defined(USE_SIGNATURE) template int Is_Signature_Bad(const volatile Vector2DOf *) { return False; } #endif // template const Vector2DOf // Vector2DOf::identity(0.0f,0.0f); template inline Logical Small_Enough(const Vector2DOf &v,Scalar e) { Check(&v); return Small_Enough(v.x,e) && Small_Enough(v.y,e); } //REMOVED: RB 1/15/07 //template Logical // Close_Enough( // const Vector2DOf &v1, // const Vector2DOf &v2, // Scalar e // ) //{ // Check(&v1); // Check(&v2); // return Close_Enough(v1.x,v2.x,e) && Close_Enough(v1.y,v2.y,e); //} inline Logical Close_Enough(const Vector2DOf &v1, const Vector2DOf &v2, Scalar e) { Check(&v1); Check(&v2); return Close_Enough(v1.x, v2.x,e) && Close_Enough(v1.y, v2.y,e); } inline Logical Close_Enough(const Vector2DOf &v1, const Vector2DOf &v2, Scalar e) { Check(&v1); Check(&v2); return Close_Enough(v1.x, v2.x,e) && Close_Enough(v1.y, v2.y,e); } template inline Vector2DOf& Vector2DOf::Negate(const Vector2DOf &v) { Check(this); Check(&v); x = -v.x; y = -v.y; return *this; } template inline Vector2DOf& Vector2DOf::Add( const Vector2DOf& v1, const Vector2DOf& v2 ) { Check(this); Check(&v1); Check(&v2); x = v1.x + v2.x; y = v1.y + v2.y; return *this; } template inline Vector2DOf& Vector2DOf::Subtract( const Vector2DOf& v1, const Vector2DOf& v2 ) { Check(this); Check(&v1); Check(&v2); x = v1.x - v2.x; y = v1.y - v2.y; return *this; } template inline Vector2DOf& Vector2DOf::Multiply( const Vector2DOf& v, T scale ) { Check(this); Check(&v); x = v.x * scale; y = v.y * scale; return *this; } template inline Vector2DOf& Vector2DOf::Multiply( const Vector2DOf& v1, const Vector2DOf& v2 ) { Check(this); Check(&v1); Check(&v2); x = v1.x * v2.x; y = v1.y * v2.y; return *this; } template inline Vector2DOf& Vector2DOf::Divide( const Vector2DOf& v, T scale ) { Check(this); Check(&v); Verify(!Small_Enough(scale)); x = v.x / scale; y = v.y / scale; return *this; } template inline Vector2DOf& Vector2DOf::Divide( const Vector2DOf& v1, const Vector2DOf& v2 ) { Check(this); Check(&v1); Check(&v2); Verify(!Small_Enough(v2.x)); Verify(!Small_Enough(v2.y)); x = v1.x / v2.x; y = v1.y / v2.y; return *this; } template inline Vector2DOf& Vector2DOf::Normalize(const Vector2DOf &v) { Check_Pointer(this); Check(&v); T len = v.Length(); Verify(!Small_Enough(len)); x = v.x/len; y = v.y/len; return *this; } //template std::ostream& operator<<(std::ostream& stream, const Vector2DOf& v) //{ // Check(&v); // return stream << '<' << v.x << ',' << v.y << '>'; //} template inline Logical Vector2DOf::TestInstance() const { return true; } inline std::ostream& operator<<(std::ostream& stream, const Vector2DOf& v) { Check(&v); return stream << '<' << v.x << ',' << v.y << '>'; } #if 0 template Vector2DOf& Combine( const Vector2DOf& v1, Scalar t1, const Vector2DOf& v2, Scalar t2 ) { Check(this); Check(&v1); Check(&v2); x = v1.x*t1 + v2.x*t2; y = v1.y*t1 + v2.y*t2; return *this; } #endif