/****************************************************************************************

		Index.h

		Copyright: (c) 2001 Eovia Corp. All rights reserved.

		Author:	Alec
		Date:	5/20/98

		Revision History

		when		who			what & why
		==========	==========	======================================================
		6/16/96		Alec		added conversion operators to MCPoint
		5/20/98		Alec		new today - useful integer/index vectors
		
*****************************************************************************************/

#ifndef Index_H
#define Index_H

#include "MCBasicTypes.h"

#include <math.h>

#pragma once


class TMCPoint;
class TMCiostream;

/// Deprecated, use TMCPoint instead !
///
class TIndex2 : public TMCObject
{
	public:
		static const TIndex2 kZero;
		
	public:
		inline TIndex2()
			{ }
		inline TIndex2(
				const int32 xx,
				const int32 yy )
			: x( xx ), y( yy )
			{ }
		
		inline operator TMCPoint& ( void )
			{ return *(TMCPoint*)this; }
		inline operator const TMCPoint& ( void ) const
			{ return *(const TMCPoint*)this; }
			
		// commonly used operations	
		inline void Set(
				const int32 xx,
				const int32 yy )
			{ x = xx; y = yy; }
		
		inline real GetMagnitudeSquared( void ) const
			{ return x * x + y * y; }
		inline real GetMagnitude( void ) const
			{ return sqrt( GetMagnitudeSquared() ); }
			
		inline real GetDistance( const TIndex2& v ) const
			{ return ( *this - v ).GetMagnitude(); }
		
		void Swap( TIndex2& v );
			
		inline void Negate( void )
			{ x = -x, y = -y; }
		
		// the operators
		inline TIndex2 operator - ( void ) const
			{ return TIndex2( -x, -y ); }
	
		inline TIndex2& operator += ( const TIndex2& rhs )
			{ x += rhs.x; y += rhs.y; return *this; }
		inline TIndex2& operator -= ( const TIndex2& rhs )
			{ x -= rhs.x; y -= rhs.y; return *this; }
		
		inline TIndex2 operator + ( const TIndex2& rhs ) const
			{ return TIndex2(x + rhs.x, y + rhs.y); }
		inline TIndex2 operator-( const TIndex2& rhs ) const
			{ return TIndex2(x - rhs.x, y - rhs.y); }
			
		inline int32& operator []( const uint32 elemNum )
			{ return *(&x + elemNum); }
		inline const int32& operator []( const uint32 elemNum ) const
			{ return *(&x + elemNum); }

		inline boolean operator == ( const TIndex2& rhs ) const
			{ return (x == rhs.x) && (y == rhs.y); }
		inline boolean operator != ( const TIndex2& rhs ) const
			{ return ! (*this == rhs ); }
		inline boolean operator < ( const TIndex2& rhs ) const
			{ return (x < rhs.x) || ((x == rhs.x) && (y < rhs.y)); }
	
		// the size of the index
		inline uint32 GetDimension( void ) const
			{ return 2; }	
	public:
		int32 x,y;
};

/// Stores a 3D integer point
///
class TIndex3 : public TMCObject
{
	public:
		static const TIndex3 kZero;

	public:
		inline TIndex3()
			{ }
		inline TIndex3(
				const int32 xx,
				const int32 yy,
				const int32 zz )
			: x( xx ), y( yy ), z( zz )
			{ }
		
		// commonly used operations		
		inline void Set(
				const int32 xx,
				const int32 yy,
				const int32 zz )
			{ x = xx, y = yy, z = zz; }
		
		inline real GetMagnitudeSquared( void ) const
			{ return x * x + y * y + z * z; }
		inline real GetMagnitude( void ) const
			{ return sqrt( GetMagnitude() ); }
			
		inline real GetDistance( const TIndex3& v ) const
			{ return ( *this - v ).GetMagnitude(); }
		
		void Swap( TIndex3& v );
			
		inline void Negate( void )
			{ x = -x, y = -y, z = -z; }
		
		// the operators
		inline TIndex3 operator - ( void ) const
			{ return TIndex3( -x, -y, -z ); }
	
		inline TIndex3& operator += ( const TIndex3& rhs )
			{ x += rhs.x; y += rhs.y; z += rhs.z; return *this; }
		inline TIndex3& operator -= ( const TIndex3& rhs )
			{ x -= rhs.x; y -= rhs.y; z -= rhs.z; return *this; }
		
		inline TIndex3 operator + ( const TIndex3& rhs ) const
			{ return TIndex3(x + rhs.x, y + rhs.y, z + rhs.z); }
		inline TIndex3 operator-( const TIndex3& rhs ) const
			{ return TIndex3(x - rhs.x, y - rhs.y, z - rhs.z); }
			
		inline int32& operator []( const uint32 elemNum )
			{ return *(&x + elemNum); }
		inline const int32& operator []( const uint32 elemNum ) const
			{ return *(&x + elemNum); }

		inline boolean operator == ( const TIndex3& rhs ) const
			{ return (x == rhs.x) && (y == rhs.y) && (z == rhs.z); }
		inline boolean operator != ( const TIndex3& rhs ) const
			{ return ! (*this == rhs ); }
		
		// the size of the index
		inline uint32 GetDimension( void ) const
			{ return 3; }	
				
	public:
		int32 x,y,z;
};

TMCiostream&  operator<<(TMCiostream&ss,const TIndex3& xx);
TMCiostream&  operator>>(TMCiostream&ss,TIndex3& xx);
/// Stores a 4D integer point
///
class TIndex4 : public TMCObject
{
	public:
		static const TIndex4 kZero;

	public:
		inline TIndex4()
			{ }
		inline TIndex4(
				const int32 xx,
				const int32 yy,
				const int32 zz,
				const int32 ww )
			: x( xx ), y( yy ), z( zz ), w( ww )
			{ }
			
		// commonly used operations		
		inline void Set(
				const int32 xx,
				const int32 yy,
				const int32 zz,
				const int32 ww )
			{ x = xx, y = yy, z = zz; w = ww; }
		
		inline real GetMagnitudeSquared( void ) const
			{ return x * x + y * y + z * z + w * w; }
		inline real GetMagnitude( void ) const
			{ return sqrt( GetMagnitude() ); }
			
		inline real GetDistance( const TIndex4& v ) const
			{ return ( *this - v ).GetMagnitude(); }
		
		void Swap( TIndex4& v );
			
		inline void Negate( void )
			{ x = -x, y = -y, z = -z, w = -w; }
		
		// the operators
		inline TIndex4 operator - ( void ) const
			{ return TIndex4( -x, -y, -z, -w ); }
	
		inline TIndex4& operator += ( const TIndex4& rhs )
			{ x += rhs.x; y += rhs.y; z += rhs.z; w += rhs.w; return *this; }
		inline TIndex4& operator -= ( const TIndex4& rhs )
			{ x -= rhs.x; y -= rhs.y; z -= rhs.z; w -= rhs.w; return *this; }
		
		inline TIndex4 operator + ( const TIndex4& rhs ) const
			{ return TIndex4(x + rhs.x, y + rhs.y, z + rhs.z, w + rhs.w); }
		inline TIndex4 operator-( const TIndex4& rhs ) const
			{ return TIndex4(x - rhs.x, y - rhs.y, z - rhs.z, w - rhs.w); }
			
		inline int32& operator []( const uint32 elemNum )
			{ return *(&x + elemNum); }
		inline const int32& operator []( const uint32 elemNum ) const
			{ return *(&x + elemNum); }

		inline boolean operator == ( const TIndex4& rhs ) const
			{ return (x == rhs.x) && (y == rhs.y) && (z == rhs.z) && (w == rhs.w); }
		inline boolean operator != ( const TIndex4& rhs ) const
			{ return ! (*this == rhs ); }
		
		// the size of the index
		inline uint32 GetDimension( void ) const
			{ return 4; }	
	public:
		int32 x,y,z,w;
};


#endif // Index_H