#ifdef _CH_
#pragma package <opencv>
#endif

#ifndef _EiC
#include "cv.h"
#include "cvaux.h"
#include "highgui.h"
#endif

#include "feature.h"
#include <vector>
#include <math.h>

/////////////////////////////
// Construction/Destruction//
/////////////////////////////

feature::feature()
{
	shape=NULL;
	offsetX=0;
	offsetY=0;
	scaleX =0;
	scaleY =0;
	value  =0;
	width = 0;
	height = 0;
	blackmultiplyfactor=1;	//in case white and black areas are not equal 
	whitemultiplyfactor=1;	//their weight must be equalized.
	whiterectangles.clear();
	blackrectangles.clear();
}

feature::feature(IplImage *feat) {
	shape=feat;
	offsetX=0;
	offsetY=0;
	scaleX =0;
	scaleY =0;
	width = 0;
	height = 0;
	blackmultiplyfactor=1;	//in case white and black areas are not equal 
	whitemultiplyfactor=1;	//their weight must be equalized.
	value  =0;
	whiterectangles.clear();
	blackrectangles.clear();
}

feature::~feature()
{
	if (shape!=NULL)
		cvReleaseImage(&shape);
	offsetX=0;
	offsetY=0;
	scaleX =0;
	scaleY =0;
	value  =0;

	for (int di=0; di<whiterectangles.size(); ++di){			
		rectangle *e = (rectangle*) whiterectangles[di];
		delete e;
	}

	for (di=0; di<blackrectangles.size(); ++di){			
		rectangle *e = (rectangle*) blackrectangles[di];
		delete e;
	}	
}
//////////////
//Operations//
//////////////
void feature::setfeature(int offx, int offy, int scax, int scay) {
	offsetX=offx;
	offsetY=offy;
	scaleX=scax;
	scaleY=scay;
}

void feature::addRect2(int x1, int y1, int x2, int y2, int colour) {
	CvPoint &p1 = cvPoint(x1,y1);
	CvPoint &p2 = cvPoint(x2,y2);
	struct rectangle *rec = new struct rectangle(p1,p2);
	if (colour == 0)
		whiterectangles.push_back(rec);
	if (colour == 1)
		blackrectangles.push_back(rec);
}

void feature::printRectangles() {
	printf("white rectangles \n");
	for (int di=0;di<whiterectangles.size();++di){
		struct rectangle *e = ((struct rectangle*)whiterectangles[di]);
		e->printPoints();
	}
	printf("black rectangles \n");
	for (di=0;di<blackrectangles.size();++di){
		struct rectangle *e = (struct rectangle*) blackrectangles[di];
		e->printPoints();
	}
}

void feature::findWH() {
	int Round(float x);

	int whitearea=0;
	int blackarea=0;
	for (int di=0;di<whiterectangles.size();++di){
		struct rectangle *e = (struct rectangle*)whiterectangles[di];
		if (e->p1.x>width)
			width=e->p1.x;
		if (e->p1.y>height)
			height=e->p1.y;
		if (e->p2.x>width)
			width=e->p2.x;
		if (e->p2.y>height)
			height=e->p2.y;
		whitearea+=(e->p2.x-e->p1.x)*(e->p2.y-e->p1.y);
	}
	for (di=0;di<blackrectangles.size();++di){
		struct rectangle *e = (struct rectangle*) blackrectangles[di];
		if (e->p1.x>width)
			width=e->p1.x;
		if (e->p1.y>height)
			height=e->p1.y;
		if (e->p2.x>width)
			width=e->p2.x;
		if (e->p2.y>height)
			height=e->p2.y;
		blackarea+=(e->p2.x-e->p1.x)*(e->p2.y-e->p1.y);
	}
	
	if (whitearea!=blackarea) {
		int area=height*width;
		float wratio=(float)whitearea/(float)area;
		float bratio=(float)blackarea/(float)area;
		if(wratio<bratio)
			whitemultiplyfactor=Round(bratio/wratio);
		else
			blackmultiplyfactor=Round(wratio/bratio);
	}
}

int Round(float x) {
	int ret=floor(x);
	float a=x-ret;
	if (a>=0.5)
		ret++;
	
	return ret;
}

int feature::calcValue(IplImage *input, IplImage **bins, IplImage *red, IplImage *CumulativeIntensities){	//for now assume that *input is an integral image
	//void cvResize( const CvArr* I, CvArr* J, int interpolation=CV_INTER_LINEAR );
	int featwidth=shape->width;
	int featheight=shape->height;
	int whiteTotal=0;
	int blackTotal=0;
	int ret1=0;
	
	for (int di=0;di<whiterectangles.size();++di){
		struct rectangle *e = (struct rectangle*) whiterectangles[di];
		
		//get 4 points for integral image calculation
		int Ax=e->p1.x*scaleX + offsetX;
		int Ay=e->p1.y*scaleY + offsetY;
		int Dx=e->p2.x*scaleX + offsetX;
		int Dy=e->p2.y*scaleY + offsetY;
		int Bx=Ax;
		int By=Dy;
		int Cx=Dx;
		int Cy=Ay;

		float A=((float*)(input->imageData + input->widthStep*Ay))[Ax];
		float B=((float*)(input->imageData + input->widthStep*By))[Bx];
		float C=((float*)(input->imageData + input->widthStep*Cy))[Cx];
		float D=((float*)(input->imageData + input->widthStep*Dy))[Dx];
		whiteTotal+=(int)(A+D-C-B);
	}
	
	for (di=0;di<blackrectangles.size();++di){
		struct rectangle *e = (struct rectangle*) blackrectangles[di];
		
		//get 4 points for integral image calculation
		int Ax=e->p1.x*scaleX + offsetX;
		int Ay=e->p1.y*scaleY + offsetY;
		int Dx=e->p2.x*scaleX + offsetX;
		int Dy=e->p2.y*scaleY + offsetY;
		int Bx=Ax;
		int By=Dy;
		int Cx=Dx;
		int Cy=Ay;

		float A=((float*)(input->imageData + input->widthStep*Ay))[Ax];
		float B=((float*)(input->imageData + input->widthStep*By))[Bx];
		float C=((float*)(input->imageData + input->widthStep*Cy))[Cx];
		float D=((float*)(input->imageData + input->widthStep*Dy))[Dx];
		blackTotal+=(int)(A+D-C-B);
	}
	
	ret1=whiteTotal*whitemultiplyfactor-blackTotal*blackmultiplyfactor;
	return ret1;
}

#ifdef _EiC
main(1,"feature.cpp");
#endif