#ifdef _CH_
#pragma package <opencv>
#endif

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

#ifndef _COMPONENTS_H
#define _COMPONENTS_H

#include <vector>

// Struct to hold snap shot of an ellipse.
class ellipse{
public:
	// First 5 doubles are the ellipse equation (ie. X), h, k, offsetX, offsetY
	double *data;
	ellipse(double* X, double h, double k, double offsetX, double offsetY){		
		data = new double[9];
		data[0]=X[0]; data[1]=X[1]; data[2]=X[2]; data[3]=X[3]; data[4]=X[4];
		data[5]=h;
		data[6]=k;
		data[7]=offsetX; 
		data[8]=offsetY;		
	}
	void releaseResources(){
		delete [] data;
		data=NULL;
	}
	~ellipse(){
		releaseResources();
	}

};

class components  
{
protected:

	int pixels;
	int label;
	int imWidth;
	int imHeight;
	int offsetX;
	int offsetY;
	struct point {
		short x;
		short y;
	};
	struct point **curves;	//2D array of points
	int *pointCounter;
	short *validLabel;
	double *X;
	short *realElypse;
	short **skinstatus;

	bool Xrotdone;	//used in error finding for ellipses
	double *Xrot;
	/*double loci1X;	//loci of ellipse in actual image,
	double loci1Y;	//used to find distance from point to ellipse
	double loci2X;
	double loci2Y;*/
	double h;	//center of ellipse
	double k;
	double a2;	//major and minor axes
	double b2;
	double q;	//angle of rot

public:
	components();
	virtual ~components();
	
	// vector elipses is the return type. (so pass by reference)
	IplImage *Components(IplImage *input, IplImage *skin, std::vector<ellipse*>& ellipses);	//extract every curve of connected points
	
	void sameComp(int *A, int *B, int *minlabel);	//helper function for Components
	void elypses(int *minX, int *minY, int *maxX, int*maxY, IplImage *input, short **skinstatus, int **complabel, IplImage *skinbinary, std::vector<ellipse*>& ellipses);	//Median ellipse finding method
	bool GaussElim(double **g, int width, int height);	//perform Gaussian elimination with maximal column pivoting
	void fillGauss(double **Gauss, int label, int *minX, int *minY, int *maxX, int*maxY);	//fills g matrix with values
	bool checkElypse2(point **curves, int index, double *X, int minX, int maxX, int minY, int maxY, IplImage *skinbinary);
	void paintElypses(IplImage *skinbinary);
	void findAverages(double **Avs, double *res, int count);
	double **Matrix(int x, int y);	//allocate 2d array
	void ClearMatrix(double **M, int x, int y);
	void DeleteMatrix(double **M, int nSize);
	void iquicksort(double a[], int fst, int lst);
	void findMedians(double **Avs, double *res, int count);	//find median values of ellipse variables
	void fitElipse(IplImage *im, IplImage *skinbinary);	//OpenCV fit ellipse
	void calcOffset(int index);	//move all points closer to origin to decrease calc error
	double EOF13(double x1, double y1, double *X, IplImage *el);	//calc distance between point and ellipse

	// Returns true if given point x1, y1 is in elipse, Xnew is double array size 5
	bool isInElipse(double *Xnew, CvPoint point);	
	int isTit(std::vector<ellipse*>& listOfElipses, std::vector<struct Nipple*>& nippleCenters, IplImage *originalImage);
	

};

#endif // !defined(AFX_COMPONENTS_H__65EA8A0D_D944_4E7C_8950_A1030642BF00__INCLUDED_)

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