/*
	Lan Wars.
	Copyright (c) 2009, Darragh Coy.
	All rights reserved.
	Original work(s), source code & author(s) details available at: http://www.darraghcoy.com

	Redistribution and use in source and binary forms, with or without modification, are permitted 
	provided that the following conditions are met:

		* 	Redistributions of source code must retain the above copyright notice, this list of 
			conditions and the following disclaimer.
		* 	Redistributions in binary form must reproduce the above copyright notice, this list of 
			conditions and the following disclaimer in the documentation.
		* 	Neither the name of the author nor the names of contributors may be used to endorse or 
			promote products derived from this software without specific prior written permission.
		* 	The use of any third party libraries, modules or data files provided with the source 
			form of the program must follow and respect the individual licensing terms of these 
			components. You do not have permission to modify or circumvent the licensing terms for 
			provided third party components unless the third party licenses specifically allow this. 
			If you do not agree to the terms of provided third party components then you do not have 
			permission to use them in your derived work(s).
		* 	The terms of this license do not apply to separate (but related) distributions if supplied 
			by the author(s), only to the contents of this source distribution, derived works, and the 
			binaries produced by either modified or unmodified versions of the source code. The terms 
			of this license do not also apply to any third party libraries or components provided with 
			the source distribution. Such third party elements are licensed under their own separate 
			agreements.

	THIS SOFTWARE IS PROVIDED BY DARRAGH COY ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
	BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
	ARE DISCLAIMED. IN NO EVENT SHALL DARRAGH COY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
	OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
	OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
	IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef GAME_VECTOR2_H
#define GAME_VECTOR2_H

//=====================================================================================================================
//=====================================================================================================================

#include "Base\Assertion.h"
#include <cmath>

// Specific:

#ifdef GAME_SUPPORT_DIRECT_X_TYPES

	#include <D3DX10Math.h>

#endif

//=====================================================================================================================
//=====================================================================================================================

namespace Game
{
	//=================================================================================================================
	/// @brief		Two dimensional vector object. Includes all the standard vector operations.
	//=================================================================================================================

	template <class T> struct Vector2
	{
		public:

			//=========================================================================================================
			// Functions
			//=========================================================================================================

				//=====================================================================================================
				/// @brief		Constructor. Creates the vector.
				/// @param		x - x component of the vector
				/// @param		y - y component of the vector
				//=====================================================================================================
				
				inline Vector2( T x = 0 , T y = 0 )
				{
					this->x = (T) x;
					this->y = (T) y;
				}								
				
				//=====================================================================================================
				/// @brief		Constructor. Creates the vector from an array
				/// @param		a - array to create from
				/// @pre		Given pointer must not be null
				//=====================================================================================================
				
				inline Vector2( const T * a )
				{
					ENSURE(a,"Given pointer must not be null");
				
					this->x = a[0];
					this->y = a[1];
				}			

				//=====================================================================================================
				/// @brief		Constructor. Creates the vector from a given directx 2d vector
				/// @param		v - vector to create from
				//=====================================================================================================

				#ifdef GAME_SUPPORT_DIRECT_X_TYPES
	
					inline Vector2( const D3DXVECTOR2 & v )
					{
						this->x = (T) v.x;
						this->y = (T) v.y;
					}					

				#endif
				
				//=====================================================================================================
				/// @brief		Copy constructor. Creates this vector from another vector.
				/// @param		v - other vector to construct from
				//=====================================================================================================
				
				template<class VT> inline Vector2( const Vector2<VT> & v )
				{
					this->x = (T) v.x;
					this->y = (T) v.y;
				}
				
				//=====================================================================================================
				/// @brief		Assignment operator. Assigns the other vector to this vector.
				/// @param		v - other vector to assign from
				/// @returns	This vector
				//=====================================================================================================
				
				template<class VT> inline Vector2<T> & operator = ( const Vector2<VT> & v )
				{
					this->x = (T) v.x;
					this->y = (T) v.y;
					
					return * this;
				}							
				
				//=====================================================================================================
				/// @brief		Assignment operator. Assigns the given array to this vector,
				/// @param		a - array to assign to this vector.
				/// @returns	This vector
				//=====================================================================================================
				
				template<class VT> inline Vector2<T> & operator = ( const VT * a )
				{				
					this->x = (T) v[0];
					this->y = (T) v[1];
					
					return * this;
				}

				#ifdef GAME_SUPPORT_DIRECT_X_TYPES
				
				//=====================================================================================================
				/// @brief		Assignment operator. Assigns the given 2d directx vector to this vector
				/// @param		v - vector to assign
				/// @returns	this vector
				//=====================================================================================================				
	
				inline Vector2<T> & operator = ( const D3DXVECTOR2 & v )
				{
					this->x = (T) v.x;
					this->y = (T) v.y;

					return * this;
				}					

				#endif
				
				//=====================================================================================================
				/// @brief		Array index accessor. Returns a copy of the variable at the given index.
				/// @param		i - element to access
				/// @returns	chosen element
				/// @pre		Given index must be in range
				//=====================================================================================================
				
				inline T operator[]( unsigned i ) const
				{
					ENSURE(i<2,"Given index must be in range");
				
					return *((&x)+i);
				}
				
				//=====================================================================================================
				/// @brief		Array index accessor. Returns a reference of the variable at the given index.
				/// @param		i - element to access
				/// @returns	chosen element, ready for writing
				/// @pre		Given index must be in range
				//=====================================================================================================
				
				inline T & operator[]( unsigned i )
				{
					ENSURE(i<2,"Given index must be in range");
				
					return *((&x)+i);
				}																		
				
				//=====================================================================================================
				/// @brief		Addition. Adds the given vector to this vector.
				/// @param		v - other vector to add to this vector
				/// @returns	A new vector
				//=====================================================================================================
				
				template<class VT> inline Vector2<T> operator + ( const Vector2<VT> & v ) const
				{
					return Vector2<T>
					( 
						(T)( v.x + this->x ), 
						(T)( v.y + this->y )
					);
				}
				
				//=====================================================================================================
				/// @brief		Subtraction. Subtracts the given vector from this vector.
				/// @param		v - other vector to subtract from this vector
				/// @returns	A new vector
				//=====================================================================================================
				
				template<class VT> inline Vector2<T> operator - ( const Vector2<VT> & v ) const
				{
					return Vector2<T>
					( 
						(T)( this->x - v.x ), 
						(T)( this->y - v.y )
					);
				}							
				
				//=====================================================================================================
				/// @brief		Scalar product. Returns a new vector scaled by the given amount.
				/// @param		scale - scaling amount
				/// @returns	A new vector
				//=====================================================================================================
				
				template<class ST> inline Vector2<T> operator * ( ST scale ) const
				{
					return Vector2<T>
					(
						(T)( this->x * scale ), 
						(T)( this->y * scale )
					);
				}
				
				//=====================================================================================================
				/// @brief		Scalar addition. Returns a new vector with the given value added to it.
				/// @param		value - amount to add
				/// @returns	A new vector with the given amount added
				//=====================================================================================================
				
				template<class ST> inline Vector2<T> operator + ( ST value ) const 
				{
					return Vector2<T>
					(
						(T)( this->x + value ), 
						(T)( this->y + value )
					);
				}								
				
				//=====================================================================================================
				/// @brief		Scalar subtraction. Returns a new vector with the given value subtracted from it.
				/// @param		value - amount to subtract
				/// @returns	A new vector with the given amount subtracted
				//=====================================================================================================
				
				template<class ST> inline Vector2<T> operator - ( ST value ) const
				{
					return Vector2<T>
					(
						(T)( this->x - value ), 
						(T)( this->y - value )
					);
				}				
				
				//=====================================================================================================
				/// @brief		Scalar division. Returns a new vector divided by the given amount.
				/// @param		scale - scaling amount
				/// @returns	A new vector
				/// @pre		Scale must not be zero
				//=====================================================================================================
				
				template<class ST> inline Vector2<T> operator / ( ST scale ) const
				{
					ENSURE( scale != 0 , "Scale must not be zero" );
				
					return Vector2<T>
					(
						(T)( this->x / scale ),
						(T)( this->y / scale )
					);
				}
				
				//=====================================================================================================
				/// @brief		Vector addition. Adds the given vector to this vector.
				/// @param		v - vector to add
				//=====================================================================================================
				
				template<class VT> inline void operator += ( const Vector2<VT> & v )
				{
					this->x = (T)( this->x + v.x );
					this->y = (T)( this->y + v.y );
				}
				
				//=====================================================================================================
				/// @brief		Vector subtraction. Subtracts the given vector from this vector.
				/// @param		v - vector to subtract
				//=====================================================================================================
				
				template<class VT> inline void operator -= ( const Vector2<VT> & v )
				{
					this->x = (T)( this->x - v.x );
					this->y = (T)( this->y - v.y );
				}			
				
				//=====================================================================================================
				/// @brief		Scalar addition. Adds the given scalar to this vector.
				/// @param		value - value to add
				//=====================================================================================================
				
				template<class ST> inline void operator += ( ST value )
				{
					this->x = (T)( this->x + value );
					this->y = (T)( this->y + value );
				}
				
				//=====================================================================================================
				/// @brief		Scalar subtraction. Subtracts the given scalar to this vector.
				/// @param		value - value to subtract
				//=====================================================================================================
				
				template<class ST> inline void operator -= ( ST value )
				{
					this->x = (T)( this->x - value );
					this->y = (T)( this->y - value );
				}												
				
				//=====================================================================================================
				/// @brief		Scalar product. Scales this vector by the given amount.
				/// @param		scale - scaling amount
				//=====================================================================================================
				
				template<class ST> inline void operator *= ( ST scale )
				{
					this->x = (T)( this->x * scale );
					this->y = (T)( this->y * scale );
				}		
				
				//=====================================================================================================
				/// @brief		Scalar division. Scales this vector by the given amount.
				/// @param		scale - scaling amount
				/// @pre		Scale must not be zero
				//=====================================================================================================
				
				template<class ST> inline void operator /= ( ST scale )
				{
					ENSURE( scale != 0 , "Scale must not be zero" );
				
					this->x = (T)( this->x / scale );
					this->y = (T)( this->y / scale );
				}
				
				//=====================================================================================================
				/// @brief		Unary negation operator. Negates this vector.
				/// @returns	A new vector that is negated
				//=====================================================================================================
				
				inline Vector2<T> operator - ( void ) const
				{
					return Vector2<T>(-x,-y);
				}
				
				//=====================================================================================================
				/// @brief		Unary addition operator. Does nothing
				/// @returns	This vector
				//=====================================================================================================
				
				inline Vector2<T> operator + ( void ) const
				{
					return * this;
				}	
				
				//=====================================================================================================
				/// @brief		Dot product. Returns the dot product with the given vector.
				/// @param		v - vector to do a dot product with
				//=====================================================================================================
				
				template<class VT> inline T Dot ( Vector2<VT> v ) const
				{
					return (T)
					(
						( this->x * v.x )
						+ 
						( this->y * v.y )
					);
				}
				
				//=====================================================================================================
				/// @brief		Gets the squared length of this vector.
				/// @returns	Squared length of the vector
				/// @remarks	Squared length is returned in the same format as the data type of the vector		
				//=====================================================================================================
				
				inline T SqLength() const
				{
					// Return square length:
					
					return ( this->x * this->x ) + ( this->y * this->y );
				}
				
				//=====================================================================================================
				/// @brief		Gets the length of this vector.
				/// @returns	Length of the vector
				/// @remarks	Length is returned in the same format as the data type of the vector		
				//=====================================================================================================
				
				inline T Length() const
				{
					// Get square length:
					
					T sq_length = SqLength();
					
					// Get the square root of it and return: 
					
					return (T) sqrt(sq_length);
				}
				
				//=====================================================================================================
				/// @brief		Normalises the vector and returns the length of the vector in the process.
				/// @returns	Length of the vector
				/// @remarks	A check for division by zero is done
				//=====================================================================================================
				
				inline T Normalize()
				{
					// Get length
					
					T length = Length();
					
					// Normalize if not zero:
					
					if ( length != (T)(0) )
					{
						x /= length;
						y /= length;
					}
					
					// Return the length of the vector
					
					return length;
				}
				
				//=====================================================================================================
				/// @brief		Normalises the vector using approximate calculations
				/// @remarks	No check for division by zero is done. Instead a constant value is added to avoid
				///				division by zero. This will never return length 0!
				//=====================================================================================================
				
				inline void FastNormalize()
				{
					// Calculate reciprocal sqrt of square length
					
					float rsqrt = Float::FastInvSqrt( SqLength() + 0.000001f );
					
					// Normalise:
					
					x *= rsqrt;
					y *= rsqrt;
				}				
				
				//=====================================================================================================
				/// @brief		Reverses this vector, by negating all elements
				/// @returns	A new vector, which is the reverse of this vector.
				//=====================================================================================================				
				
				inline Vector2<T> Reverse() const
				{
					// Return a negated version of this:
					
					return Vector2<T>
					(
						-this->x,
						-this->y
					);
				}
				
				//=====================================================================================================
				/// @brief		Returns the normalized direction of this vector.
				/// @returns	Normalized direction of the vector.
				//=====================================================================================================												
				
				inline Vector2<T> Direction() const
				{
					// Make a copy of this vector:
					
					Vector2<T> v(*this);
					
					// Normalise:
					
					v.Normalize();
					
					// Return it:
					
					return v;
				}
				
				//=====================================================================================================
				/// @brief		Tells if the two vectors are exactly equal
				/// @param		v - other vector to compare to
				/// @returns	True if the two vectors are exactly equal
				//=====================================================================================================												
				
				template<class VT> inline bool operator == ( const Vector2<VT> & v ) const
				{
					// See if equal:
					
					if 
					( 
						(T) v.x == this->x &&
						(T) v.y == this->y
					)
					{
						return true;
					}
					else
					{
						return false;
					}
				}	
				
				//=====================================================================================================
				/// @brief		Tells if the two vectors are exactly not equal
				/// @param		v - other vector to compare to
				/// @returns	True if the two vectors are exactly not equal
				/// @remarks	Internally this function uses the precision or data type of this vector.
				//=====================================================================================================												
				
				template<class VT> inline bool operator != ( const Vector2<VT> & v ) const
				{
					// See if not equal:
					
					if 
					( 
						(T) v.x != this->x ||
						(T) v.y != this->y
					)
					{
						return true;
					}
					else
					{
						return false;
					}
				}
				
				//=====================================================================================================
				/// @brief		Tells if the length of this vector is greater than the length of the given vector
				/// @param		v - other vector to compare to
				/// @returns	True if this vectors length is greater than the other vectors length
				/// @remarks	Internally this function uses the precision or data type of this vector.
				//=====================================================================================================
				
				template<class VT> inline bool operator > ( const Vector2<VT> & v ) const
				{
					// Get the two lengths:
					
					T l1 = SqLength(); T l2 = (T) v.SqLength();
					
					// Return result:
					
					return l1 > l2;
				}		
				
				//=====================================================================================================
				/// @brief		Tells if the length of this vector is greater than or equal to the length of the given vector
				/// @param		v - other vector to compare to
				/// @returns	True if this vectors length is greater than or equal to the other vectors length
				/// @remarks	Internally this function uses the precision or data type of this vector.
				//=====================================================================================================
				
				template<class VT> inline bool operator >= ( const Vector2<VT> & v ) const
				{
					// Get the two lengths:
					
					T l1 = SqLength(); T l2 = (T) v.SqLength();
					
					// Return result:
					
					return l1 >= l2;
				}
				
				//=====================================================================================================
				/// @brief		Tells if the length of this vector is less than the length of the given vector
				/// @param		v - other vector to compare to
				/// @returns	True if this vectors length is less than the other vectors length
				/// @remarks	Internally this function uses the precision or data type of this vector.
				//=====================================================================================================
				
				template<class VT> inline bool operator < ( const Vector2<VT> & v ) const
				{
					// Get the two lengths:
					
					T l1 = SqLength(); T l2 = (T) v.SqLength();
					
					// Return result:
					
					return l1 < l2;
				}
				
				//=====================================================================================================
				/// @brief		Tells if the length of this vector is less than or equal to the length of the given vector
				/// @param		v - other vector to compare to
				/// @returns	True if this vectors length is less than or equal to the other vectors length
				/// @remarks	Internally this function uses the precision or data type of this vector.
				//=====================================================================================================
				
				template<class VT> inline bool operator <= ( const Vector2<VT> & v ) const
				{
					// Get the two lengths:
					
					T l1 = SqLength(); T l2 = (T) v.SqLength();
					
					// Return result:
					
					return l1 <= l2;
				}
				
				//=====================================================================================================
				/// @brief		Compares two vectors for equality with a given margin for error.
				/// @param		v - other vector to compare to
				/// @param		error_margin - margin for error. this is the maximum distance in length between the two 
				///				vectors.
				/// @remarks	This is slower than a normal compare, but can be useful for situations where a margin
				///				of error is required.
				//=====================================================================================================
				
				template<class VT> inline bool Equals ( const Vector2<VT> & v , T error_margin = (T) 0.0001 ) const
				{
					// Subtract the two vectors:
					
					Vector2<T> sub =
					(
						this->x - (T) v.x,
						this->y - (T) v.y
					);
					
					// Get the square length of it:
					
					T sq_length = (T) sub.SqLength();
					
					// See if less than or equal to error margin:
					
					if ( sq_length <= error_margin * error_margin  )
					{
						// Equal within margin for error:
						
						return true;
					}
					else
					{
						// Not equal:
						
						return false;
					}
				}
				
				//=====================================================================================================
				/// @brief		Casts the vector to a directx vector2
				/// @returns	A direct x vector 2
				//=====================================================================================================				
				
				#ifdef GAME_SUPPORT_DIRECT_X_TYPES
				
					inline D3DXVECTOR2 ToDxVec2() const
					{
						return D3DXVECTOR2( x , y );
					}
				
				#endif
				
				//=====================================================================================================
				/// @brief		Casts the vector to a directx vector3, setting z to zero
				/// @returns	A direct x vector 3
				//=====================================================================================================
				
				#ifdef GAME_SUPPORT_DIRECT_X_TYPES
				
					inline D3DXVECTOR3 ToDxVec3() const
					{
						return D3DXVECTOR3( x , y , 0 );
					}
					
				#endif
				
				//=====================================================================================================
				/// @brief		Casts the vector to a directx vector4, setting z to zero and w to 1
				/// @returns	A direct x vector 4
				//=====================================================================================================				
				
				#ifdef GAME_SUPPORT_DIRECT_X_TYPES
				
					inline D3DXVECTOR4 ToDxVec4() const
					{
						return D3DXVECTOR4( x , y , 0 , 1 );
					}
					
				#endif
				
				//=====================================================================================================
				/// @brief		Converts the vector into array format, saving it to the given array
				/// @param		a - array to save to
				/// @pre		Given array cannot be null
				//=====================================================================================================
				
				template <class AT> inline void ToArray( AT * a ) const
				{
					ENSURE(a,"Given array cannot be null");
					
					a[0] = (AT) x;
					a[1] = (AT) y;
				}
				
				//=====================================================================================================
				/// @brief		Returns a vector with all components set to zero.
				/// @returns	A vector with all components set to zero.
				//=====================================================================================================
				
				static inline Vector2<T> Zero()
				{
					return Vector2<T>
					(
						(T) 0 ,
						(T) 0
					);
				}
				
				//=====================================================================================================
				/// @brief		Returns a vector with all components set to one.
				/// @returns	A vector with all components set to one.
				//=====================================================================================================
				
				static inline Vector2<T> One()
				{
					return Vector2<T>
					(
						(T) 1 ,
						(T) 1
					);
				}
				
				//=====================================================================================================
				/// @brief		Returns a vector with with the x component set to one.
				/// @returns	A vector with the x component set to 1.
				//=====================================================================================================
				
				static inline Vector2<T> UnitX()
				{
					return Vector2<T>
					(
						(T) 1 ,
						(T) 0
					);
				}
				
				//=====================================================================================================
				/// @brief		Returns a vector with with the y component set to one.
				/// @returns	A vector with the y component set to 1.
				//=====================================================================================================
				
				static inline Vector2<T> UnitY()
				{
					return Vector2<T>
					(
						(T) 0 ,
						(T) 1
					);
				}
				
				//=====================================================================================================
				/// @brief		Returns a vector perpendicular to this vector. This vector points to the right of
				///				the current vector.
				/// @returns	A vector perpendicular to this vector that points in a direction to the right of this
				///				vector.
				//=====================================================================================================
				
				inline Vector2<T> Perpendicular() const { return Vec2f(y,-x); }
				
				//=====================================================================================================
				/// @brief		Returns the angle between this vector and another vector. Both vectors are interpreted 
				///				as being directional vectors.
				///	@param		v - vector to get the angle between
				/// @returns	Angle between this and the other vector
				/// @remarks	If either direction is zero then an angle of zero is returned.
				///				The minimum angle (in positive or negative values) is also returned. I.E instead of
				///				returning 270 degrees, -90 degrees is returned. 
				///				The precision of this vector is used for all calculations.
				//=====================================================================================================
				
				template<class VT> inline float AngleBetween( const Vector2<VT> & v ) const
				{
					// Make a normalised version of the given vector
					
						Vector2<T> v1 = v;
						
						// Get length of the vector
						
						T len1 = v1.Length();
						
						// If length is zero then return an angle of zero, otherwise normalise.
						
						if ( len1 == 0 ) return 0; else v1 /= len1; 
					
					// Make a normalised version of this vector
					
						Vector2<T> v2 = *this;
						
						// Get length of the vector
						
						T len2 = v2.Length();
						
						// If length is zero then return an angle of zero, otherwise normalise.
						
						if ( len2 == 0 ) return 0; else v2 /= len2;
						
					// Right: get the cosine of the angle between the vectors
					
					float cosine = v1.Dot(v2);
					
					// Make absolutely sure it is in a 0-1 range:
					
					if ( cosine < -1.0f ) cosine = -1.0f;
					if ( cosine > +1.0f ) cosine = +1.0f;
					
					// Now get the angle
					
					float angle = Float::InvCos(cosine);
					
					// Get a perpendicular to this vector
					
					Vector2<T> perp = Perpendicular();
					
					// If the dot of the given vector with the perpendicular is positive we need to negate the angle:
					
					if ( perp.Dot(v1) > 0 ){ angle = -angle; }
					
					// Return the angle
					
					return angle;
				}
				
				//=====================================================================================================
				/// @brief		Returns the angle between this vector and another vector. Both vectors are interpreted 
				///				as being directional vectors. This is an approximate method.
				///	@param		v - vector to get the angle between
				/// @returns	Angle between this and the other vector
				/// @remarks	If either direction is zero then an angle of zero is returned.
				///				The minimum angle (in positive or negative values) is also returned. I.E instead of
				///				returning 270 degrees, -90 degrees is returned. 
				///				The precision of this vector is used for all calculations.
				//=====================================================================================================
				
				template<class VT> inline float FastAngleBetween( const Vector2<VT> & v ) const
				{
					// Make a normalised version of the given vector
					
					Vector2<T> v1 = v; v1.FastNormalize();
					
					// Make a normalised version of this vector
					
					Vector2<T> v2 = *this; v2.FastNormalize();
						
					// Right: get the cosine of the angle between the vectors
					
					float cosine = v1.Dot(v2);
					
					// Make absolutely sure it is in a 0-1 range:
					
					cosine = Float::Clamp( cosine , 0 , 1 );

					// Now get the angle
					
					float angle = Float::InvCos(cosine);
					
					// Get a perpendicular to this vector
					
					Vector2<T> perp = Perpendicular();
					
					// If the dot of the given vector with the perpendicular is positive we need to negate the angle:
					
					if ( perp.Dot(v1) > 0 ){ angle = -angle; }
					
					// Return the angle
					
					return angle;
				}				

				//=====================================================================================================
				/// @brief		Gets the angle that this vector is pointing in. If the vector is of zero length then 
				///				the angle zero is returned.
				/// @returns	Angle that this vector is pointing in
				//=====================================================================================================

				inline T GetAngle() const
				{
					// Make a copy of this vector and normalise

					Vector2<T> n = * this; n.Normalize();

					// Make sure the x component is in a -1 to 1 range:

					if ( n.x < -1 ) n.x = -1;
					if ( n.x > +1 ) n.x = +1;

					// Get the inverse cosine of this angle: this is the angle of the vector

					T inv_cos = Float::InvCos(n.x);

					// If the y component is less than zero then simply negate the angle:

					if ( n.y < (T) 0 ) inv_cos = -inv_cos;

					// Return the angle

					return inv_cos;
				}
				
				//=====================================================================================================
				/// @brief		Returns the distance to another point
				/// @param		v - other point to get the distance to
				/// @returns	Distance to the given point
				//=====================================================================================================
				
				template <class VT> inline T DistanceTo( const Vector2<VT> & v ) const
				{
					// Subtract the two points
					
					T xs = (T)(v.x) - x;
					T ys = (T)(v.y) - y;
					
					// Get the square distance:
					
					T sq_dist = xs * xs + ys * ys;
					
					// Now get the square root of it and return:
					
					return Float::Sqrt(sq_dist);
				}
				
				//=====================================================================================================
				/// @brief		Returns the approximate distance to another point
				/// @param		v - other point to get the distance to
				/// @returns	Distance to the given point
				/// @remarks	To prevent division by zero, the result is never 0. This property can be used in
				///				some cases to avoid division by zero checks.
				//=====================================================================================================
				
				template <class VT> inline T FastDistanceTo( const Vector2<VT> & v ) const
				{
					// Subtract the two points
					
					T xs = (T)(v.x) - x;
					T ys = (T)(v.y) - y;
					
					// Get the square distance:
					
					T sq_dist = xs * xs + ys * ys;
					
					// Now get the fast inverse square root, invert and return:
					
					return 1.0f / Float::FastInvSqrt(sq_dist+0.000001f);
				}				
				
				//=====================================================================================================
				/// @brief		Returns the square distance to another point
				/// @param		v - other point to get the distance to
				/// @returns	Distance to the given point
				//=====================================================================================================
				
				template <class VT> inline T SqDistanceTo( const Vector2<VT> & v ) const
				{
					// Subtract the two points
					
					T xs = (T)(v.x) - x;
					T ys = (T)(v.y) - y;
					
					// Get the square distance:
					
					T sq_dist = xs * xs + ys * ys;
					
					// Return the square distance
					
					return sq_dist;
				}				
		
			//=========================================================================================================
			// Variables
			//=========================================================================================================
			
				/// X component for the vector
				
				T x;
				
				/// Y component for the vector
				
				T y;
	};
};

#endif 
