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

		
		MCRealRect.h

		(c)1997 Specular International Ltd.



		Author:	link
		Date:	4/8/97

		Revision History

		when		who			what & why
		==========	==========	======================================================
		7/19/99		cph			Added InitIntFromFloat
		6/18/99		Ian			Renamed to MCRealRect.
		8/22/97		Alec		added Invalid() test
		7/8/97		Ian			Added SMCRealRect as a constructorless alternative to TMCRealRect.
		4/8/97		link		New today.

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

#if CP_PRAGMA_ONCE
#pragma once
#endif

#ifndef MCRealRect_H
#define MCRealRect_H

#include "MCBasicTypes.h"
#include "Vector2.h"

class TMCRect;

/// A rectangle class that uses floating point numbers instead of integers like TMCRect.
///	\note
///	- The member component ordering is: l,t,r,b (x0,y0,x1,y1)
///	- This class cannot have virtual functions for C size compatability
///
class TMCRealRect : public TMCObject
{	
public:
		// constant definitions
		static const TMCRealRect kZero;			///<	(0, 0, 0, 0);
		static const TMCRealRect kEmpty;		///<	(0, 0, 0, 0);
		static const TMCRealRect kInvalid;		///<	(FLT_MAX, FLT_MAX, FLT_MIN, FLT_MIN);

public:

		inline TMCRealRect			(void);
		inline TMCRealRect			(const real l, const real t, const real r, const real b);

		// element access	 	  		 
		inline real L(void) const;
		inline real T(void) const;
		inline real R(void) const;
		inline real B(void) const;

		///	Positions "centerRect" at the center of srcRect.
		///
		void CenterInside			(const TMCRealRect& inRect);

		///	Compare the components of the two rectangles and
		///	return TRUE if they are the same width and height.
		///
		boolean EqualDimensions		(const TMCRealRect& inRect) const;

		///	Return TRUE if the rectangle has no width or height.
		///
		boolean Empty				(void) const;

		///	Return TRUE if either the horizontal or vertical bounds are invalid
		///
		boolean Invalid				(void) const;
		
		///	Compare the components of the two rectangles and
		///	return TRUE if they are all the same.
		///
		boolean Equal				(const TMCRealRect& inRect) const;

		///	Calculate and return the width of the rectangle.
		///	May return a negative width.
		///
		inline real GetWidth		(void) const;

		///	Calculate and return the height of the rectangle.
		///	May return a negative width.
		///
		inline real GetHeight		(void) const;

		///	Calculate and return the center of the rectangle.
		///
		TVector2 GetCenter			(void) const;

		///	Calculate and return the area of the rectangle.
		///
		real GetArea				(void) const;

		///	InsetRect shrinks or expands the rectangle. The left and right
		///	sides are moved by dx; the top and bottom sides are moved by dy.
		///	Note: The rectangle is not set to an empty rect (0,0,0,0) if the
		///	resulting width or height is less than zero.
		///
		void Inset					(const real dx, const real dy);

		///	Intersect calculates the rectangle that is the intersection of "this" and
		///	the input rectangle, and returns TRUE if they indeed intersect or FALSE if
		///	they do not. If the rectangles do not intersect, the rect is set either empty
		///	or invalid based on the "inSetEmpty" flag.
		///
		boolean Intersect			(const TMCRealRect&	inRect,	const boolean inSetEmpty = 1 );

		///	Offset moves the rectangle by adding dx to the horizontal
		///	coordinates, and adding dy to the vertical coordinates.
		///
		void Offset					(const real dx,	const real dy);

		///	Proportionally map src rect into dst. Warning: zero width or
		///	zero height rects are dangerous.
		///
		void Proportion				(const TMCRealRect& inRect);

		///	PtToRect returns the smallest rectangle which encloses the two
		///	input points.
		///
		void PtToRect				(const TVector2& pt1, const TVector2& pt2);

		///	PtInside determines whether a point is enclosed within the
		///	specified rectangle, and returns TRUE if so and FALSE if not.
		///
		boolean PtInside			(const TVector2& inPt) const;

		///	Pin the passed in point to within the rectangle and return the
		///	resulting point.
		///
		TVector2 PinPoint			(const TVector2& inPt) const;

		///	RectInside determines whether a rectangle is enclosed within
		///	a second rectangle, and returns TRUE if so and FALSE if not.
		///
		boolean RectInside			(const TMCRealRect& inRect) const;

		///	Note: similar to above, but ignores empty rects.
		///	
		///	This routine interprets rectangles in the
		///	same way that QD does.  A rectangle will
		///	hit if any of the bits in the bitmap it 
		///	encloses overlap with any of the bits in the
		///	bitmap enclosed by the other rectangle.
		///
		boolean RectInRect			(const TMCRealRect& inRect) const;

		///	Scales each term.
		///
		void Scale					(const float inScale);

		///	Set assigns the four boundary coordinates to a rectangle.
		///	The result is a rectangle with coordinates (left,top,right,bottom).
		///
		inline void Set				(const real l, const real t, const real r, const real b);

		///	Set the rectangle to no width or height.
		///
		void SetEmpty				(void);

		///	Set the rectangle to have negative width or height.
		///	This is useful for initializing a rectangle to be
		///	the union of a set of rectangles
		///
		void SetInvalid				(void);

		///	Union calculates the smallest rectangle which encloses both
		///	input rectangles.
		///
		void Union					(const TMCRealRect& inRect);

		///	UnionPt expands the input rectangle to enclose the input point.
		///	If the point is already within the rectangle, nothing is changed.
		///
		void UnionPt				(const TVector2& inPt);
		
		/// NOTE: This function is going away please use ConvertFromIntRect()
		///	Convert the passed in integer rect to an floating point rect.
		///
		void ConvertIntToFloat		(const TMCRect& inIntegerRect);

		///	Convert the passed in integer rect to an floating point rect.
		///
		void ConvertFromIntRect		(const TMCRect& inIntegerRect);

		///	Fill out the passed in integer rect according to this floating point rect.
		///
		void InitIntFromFloat		(TMCRect& inIntegerRect);

		inline boolean	operator==	(const TMCRealRect& rr) const;
		inline boolean	operator!=	(const TMCRealRect& rr) const;

		TMCRealRect& operator=	(const int32 i)
		{
			MCAssert(i==0);

			SetEmpty();
			return *this;
		}

	public:
		union
		{
			real l;
			real left;
			real fLeft;
		};
		union
		{
			real t;
			real top;
			real fTop;
		};
		union
		{
			real r;
			real right;
			real fRight;
		};
		union
		{
			real b;
			real bottom;
			real fBottom;
		};
};


// [constant definitions] --------------------------------------------------------------//

//	void contructor.
inline TMCRealRect::TMCRealRect	(void)
	{ }

//	Component contructor.
inline TMCRealRect::TMCRealRect	(const real left, const real top, const real right, const real bottom)
						: l(left), t(top), r(right), b(bottom)
	{ }

//	Component access (although public member variables).
inline real TMCRealRect::L		(void) const
	{ return l; }	
inline real TMCRealRect::T		(void) const
	{ return t; }	
inline real TMCRealRect::R		(void) const
	{ return r; }	
inline real TMCRealRect::B		(void) const
	{ return b; }	

//	Sets the components.
inline void TMCRealRect::Set	(const real left, const real top, const real right,	const real bottom)
	{ l=left; t=top; r=right; b=bottom; }

//	Return the width.
inline real TMCRealRect::GetWidth(void) const
	{ return( r - l ); }

//	Return the height.
inline real TMCRealRect::GetHeight(void) const
	{ return( b - t ); }

inline boolean	TMCRealRect::operator==(const TMCRealRect& rr) const
	{ return Equal(rr); }
inline boolean	TMCRealRect::operator!=(const TMCRealRect& rr) const
	{ return !Equal(rr); }
#endif