/* ImLib3D
 * Copyright (c) 2001, ULP-IPB Strasbourg.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
/*! \file RectZone2D.hpp */

#ifndef _RectZone2D_hpp
#define _RectZone2D_hpp

#include<math.h>
#include<ImLib3D/Vect2D.hpp>

//! Rectangular zone x0<=x<=x1 &&  y0<=y<=y1
template<class RectType,class Real=RectType>
class RectZone2D
{
protected:
public:
	typedef Vect2D<RectType,Real> Vect2DType;

	RectType x0,y0;
	RectType x1,y1;

	RectType Width()  const {return x1-x0+1;}
	RectType Height() const {return y1-y0+1;}
	Vect2DType GetP0(){return Vect2DType(x0,y0);}
	Vect2DType GetP1(){return Vect2DType(x1,y1);}

	Vect2Df SelfCoords(const Vect2DType &P)
	{
		return Vect2Df((P.x-x0)/(float)(x1-x0),
					   (P.y-y0)/(float)(y1-y0) );
	}

	void Translate(const float x,const float y)
	{
		x0+=x;
		y0+=y;
		x1+=x;
		y1+=y;
	}
	inline void ToStart(RectType &x,RectType &y) const {x=x0;y=y0;}
	bool IsInside(const Vect2DType & vect) const {return IsInside(vect.x, vect.y);}
	bool IsInside(RectType x,RectType y) const 
	{
		if( x<x0 ) {return false;}
		if( y<y0 ) {return false;}
		if( x>x1 ) {return false;}
		if( y>y1 ) {return false;}
		return true;
	}
	bool operator==(const RectZone2D<RectType> &other)
	{
		return 
			x0==other.x0 &&
			y0==other.y0 &&
			x1==other.x1 &&
			y1==other.y1    ;
	}
	RectZone2D( const Vect2DType &p0,const Vect2DType p1):
		x0(p0.x),y0(p0.y),
		x1(p1.x),y1(p1.y)
	{

	}
	RectZone2D( RectType _x0, RectType _y0,
				RectType _x1, RectType _y1) :
		x0(_x0),y0(_y0),
		x1(_x1),y1(_y1)
	{
		;
	}
protected:
	RectZone2D(){;}
};

typedef RectZone2D<float> RectZone2Df;

//! Rectangular zone x0<=x<=x1 &&  y0<=y<=y1
class RectZone2Di : public RectZone2D<int,float>
{
public:
	inline int  ToNext(int &x,int &y) const
	{
		x++;
		if(x>x1)
		{
			x=x0;
			y++;
			if(y>y1){return 2;}
			return 1;
		}
		else { return 0;}
	}
	inline int  ToPrev(int &x,int &y) const
	{
		x--;
		if(x<x0)
		{
			x=x1;
			y--;
			if(y<y0){return 2;}
			return 1;
		}
		else { return 0;}
	}

	RectZone2Di ( const RectZone2Df & , int );
	RectZone2Di (const Vect2Di &p0,const Vect2Di &p1):
		RectZone2D<int,float>(p0,p1)
	{
		;
	}
	RectZone2Di( int _x0, int _y0,
				 int _x1, int _y1 ) :
		RectZone2D<int,float>(_x0,_y0,_x1,_y1)
	{
		;
	}

};


inline RectZone2Di::RectZone2Di( const RectZone2Df &s0, int type)
{
	if(type==0)
	{
		x0= (int)ceil (s0.x0);
		y0= (int)ceil (s0.y0);
		x1= (int)floor(s0.x1);
		y1= (int)floor(s0.y1);
	}
	else
	{
		x0= (int)floor(s0.x0);
		y0= (int)floor(s0.y0);
		x1= (int)ceil (s0.x1);
		y1= (int)ceil (s0.y1);
	}
}

#endif // _RectZone2D_hpp
