#include "Rect.h"
#include <stdlib.h>



#if DEBUG_RECT
#include "../x/Version.h"
#include "../x/scolplugin.h"
int Point2D::ctr=0;
int Rect2D::ctr=0;
#else
#define max(i, j)  (i>j?i:j)
#define min(i, j)  (i>j?j:i)
#endif



Point2D::Point2D()
{
	iptX=0;
	iptY=0;
#if DEBUG_RECT
	MMechostr(MSKTRACE,"Point2D:constructeur usuel:nb Point:%d\n",++ctr);
#endif
}

Point2D::Point2D(int x,int y)
{
	iptX=x;
	iptY=y;
#if DEBUG_RECT
	MMechostr(MSKTRACE,"Point2D:constructeur usuel:nb Point:%d\n",++ctr);
#endif
}

Point2D::Point2D(const Point2D &pt)
{
	iptX=pt.iptX;
	iptY=pt.iptY;
#if DEBUG_RECT
	MMechostr(MSKTRACE,"Point2D:constructeur par recopie:nb Point:%d\n",++ctr);
#endif
}

Point2D::~Point2D()
{ 
#if DEBUG_RECT
	MMechostr(MSKTRACE,"Point2D:destructeur:nb Point:%d\n",--ctr);
#endif
	0; 
}


Rect2D::Rect2D():RctHG(0,0),RctBD(0,0)
{ 
#if DEBUG_RECT
	MMechostr(MSKTRACE,"Rect2D:constructeur usuel:nb rect:%d\n",++ctr);
#endif
	0; 
}


Rect2D::Rect2D(int hgx,int hgy,int bdx,int bdy):RctHG(hgx,hgy),RctBD(bdx,bdy)
{ 
#if DEBUG_RECT
	MMechostr(MSKTRACE,"Rect2D:constructeur usuel:nb rect:%d\n",++ctr);
#endif
	0; 
}

Rect2D::Rect2D(Point2D i,Point2D j):RctHG(i),RctBD(j)
{ 
#if DEBUG_RECT
	MMechostr(MSKTRACE,"Rect2D:constructeur usuel:nb rect:%d\n",++ctr);
#endif
	0; 
}

Rect2D::Rect2D(const Rect2D &rect)
{
#if DEBUG_RECT
	MMechostr(MSKTRACE,"Rect2D:constructeur par recopie:nb rect:%d\n",++ctr);
#endif
	RctHG=rect.RctHG;
	RctBD=rect.RctBD;
}

Rect2D::~Rect2D()
{ 
#if DEBUG_RECT
	MMechostr(MSKTRACE,"Rect2D:destructeur:nb rect:%d\n",--ctr);
#endif
	0; 
}

int Rect2D::IsRectEmpty()
{
	return (
				(RctHG.iptX==0)&&
				(RctHG.iptY==0)&&
				(RctBD.iptX==0)&&
				(RctBD.iptY==0)
		   );
}

#if DEBUG_PRINT

void Rect2D::Print()
{
	MMechostr(1,"Rectangle:%d %d %d %d\n",RctHG.iptX,RctHG.iptY,RctBD.iptX,RctBD.iptY);
}
#else
void Rect2D::Print()
{
	0;
}
#endif

// renvoie 1 si le point est dans le rectangle 0 sinon
int IsPointInRectangle(Point2D pt,Rect2D rc)
{
	return ((pt.iptX<rc.RctBD.iptX)&&(pt.iptX>=rc.RctHG.iptX)&&(pt.iptY>=rc.RctHG.iptY)&&(pt.iptY<rc.RctBD.iptY));
}

// Calcul la taille du rectangle
void SizeRectangle(Rect2D Rec,int *w,int *h)
{
	*w=Rec.RctBD.iptX-Rec.RctHG.iptX+1;
	*h=Rec.RctBD.iptY-Rec.RctHG.iptY+1;
}


// definition du type Interval2D
typedef struct
{
	int ItvBegin;
	int ItvEnd;
} Interval2D;

/* Return the intersection of two intervals (nil if none)
			 Intrv1 : First interval
			 Intrv2 : Second interval */
Interval2D * IntervalIntersection(Interval2D Intrv1,Interval2D Intrv2)
{
	Interval2D * interval;
	if ((Intrv2.ItvEnd<Intrv1.ItvBegin) || (Intrv1.ItvEnd<Intrv2.ItvBegin)) return NULL;
	else
	{
		interval=(Interval2D *)malloc(sizeof(Interval2D));
		interval->ItvBegin=max(Intrv1.ItvBegin,Intrv2.ItvBegin);
		interval->ItvEnd=min(Intrv1.ItvEnd,Intrv2.ItvEnd);
		return interval;
	}
}

Rect2D IntersectionRectangle(Rect2D Rect1,Rect2D Rect2)
{
	Interval2D int1,int2,int3,int4;
	Interval2D * intervX, * intervY;
	Rect2D res;

	int1.ItvBegin=Rect1.RctHG.iptX;
	int1.ItvEnd  =Rect1.RctBD.iptX;
	int2.ItvBegin=Rect2.RctHG.iptX;
	int2.ItvEnd  =Rect2.RctBD.iptX;

	if ((intervX=IntervalIntersection(int1,int2))!=NULL)
	{
		int3.ItvBegin=Rect1.RctHG.iptY;
		int3.ItvEnd  =Rect1.RctBD.iptY;
		int4.ItvBegin=Rect2.RctHG.iptY;
		int4.ItvEnd  =Rect2.RctBD.iptY;
		if ((intervY=IntervalIntersection(int3,int4))!=NULL)
		{
			res=Rect2D( Point2D(intervX->ItvBegin,intervY->ItvBegin),
						Point2D(intervX->ItvEnd,intervY->ItvEnd)
					  );
			free(intervY);
		}
		free(intervX);	
	}
	return res;
}


// deplace le rectangle au point specifié
Rect2D MoveRectangleToPoint(Rect2D rect,Point2D pt)
{
	int w,h;
	SizeRectangle(rect,&w,&h);
	return (Rect2D(pt.iptX,pt.iptY,pt.iptX+w,pt.iptY+h));
}

// deplace le rectangle selon un vecteur
Rect2D MoveRectangleByVecteur(Rect2D rect,Point2D vect)
{
	return (Rect2D (	rect.RctHG.iptX+vect.iptX,
						rect.RctHG.iptY+vect.iptY,
						rect.RctBD.iptX+vect.iptX,
						rect.RctBD.iptY+vect.iptY
				   ));
}

