// PrimitiveBase.cpp: implementation of the CPrimitiveBase class.
//
//////////////////////////////////////////////////////////////////////
/** \file PrimitiveBase.cpp
	\brief implementace třídy CPrimitiveBase
*/

#include "stdafx.h"
#include "PrimitiveBase.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
//#define new DEBUG_NEW
#endif

IMPLEMENT_DYNAMIC(CPrimitiveBase, CObject) 

int CPrimitiveBase::num_primitives = 0;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//MR konstruktor (který zatím používám jako jediný, ostatní používají staré verze)
CPrimitiveBase::CPrimitiveBase(char *title)
{
	TRACE("-- Entering CPrimitiveBase default constructor --\n");

	
	if (title)
	{
		m_len = strlen(title);
		m_LayerName = new char[m_len + 1];
		strcpy(m_LayerName,title);
	}
	else
	{
		m_len = 8;
		m_LayerName = new char[m_len + 1];
		strcpy(m_LayerName, "Untitled");
	}

	m_ObjectColor.R = 0;	//R
	m_ObjectColor.G = 0;	//G
	m_ObjectColor.B = 0;	//B
	m_ObjectColor.A = 255;	//pruhlednost

	m_EnvColor.R = 0;	//R
	m_EnvColor.G = 0;	//G
	m_EnvColor.B = 0;	//B
	m_EnvColor.A = 255;	//pruhlednost	

	m_distance = 0;						
	m_width = 0;							
	m_height =0;							
	m_center.X = 0;
	m_center.Y = 0;
	m_XPeriod = 0;
	m_YPeriod = 0;
	m_XPeriodCount = -1;
	m_YPeriodCount = -1;
	//m_Overflow = false;

	//vychozi normalovy vektor vn=(0,0,1). Kolmy na osu z
	m_vn[0] = 0;
	m_vn[1] = 0;
	m_vn[2] = 1;

	m_bUse = false; //vrsrva neni defaultne zarazena do vypoctu
	m_angle.alfa =m_angle.beta = m_angle.gama =0;

	num_primitives++;
	TRACE("%d: \"%s\" object created\n", num_primitives, m_LayerName);

}
/*MR
CPrimitiveBase::CPrimitiveBase(int distance, CStructures::ARGBPixel ObjectColor, CStructures::ARGBPixel EnvColor, const char* name)
{
	TRACE("-- Entering CPrimitiveBase parameter constructor --\n ");

	m_len = strlen(name);
	if(m_len == 0)
	{
		m_len = 8;
		m_LayerName = new char[m_len + 1];
		strcpy(m_LayerName, "Untitled");
	}
	else
	{
		m_LayerName = new char[m_len + 1];
		strcpy(m_LayerName, name);
	}

	m_ObjectColor.R = ObjectColor.R;	//R
	m_ObjectColor.G = ObjectColor.G;	//G
	m_ObjectColor.B = ObjectColor.B;	//B
	m_ObjectColor.A = ObjectColor.A;	//pruhlednost

	m_EnvColor.R = EnvColor.R;	//R
	m_EnvColor.G = EnvColor.G;	//G
	m_EnvColor.B = EnvColor.B;	//B
	m_EnvColor.A = EnvColor.A;	//pruhlednost

	m_distance = distance;						
	m_width = 0;							
	m_height =0;							
	m_center.X = 0;
	m_center.Y = 0;
	m_XRepeatPeriod = 0;
	m_YRepeatPeriod = 0;
	m_XPeriodCount = 1;
	m_YPeriodCount = 1;
	//m_Overflow = false;

	//vychozi normalovy vektor vn=(0,0,1). Kolmy na osu z
	m_vn[0] = 0;
	m_vn[1] = 0;
	m_vn[2] = 1;

	//
	m_angle.alfa = 0;
	m_angle.beta = 0;
	m_angle.gama = 0;

	m_bUse = false; //vrsrva neni defaultne zarazena do vypoctu

	num_primitives++;
	TRACE("%d: \"%s\" object created\n\n", num_primitives, m_LayerName);
}
*/
CPrimitiveBase::~CPrimitiveBase()
{
	TRACE("-- Entering CPrimitiveBase destructor --\n");
	TRACE("%d: \"%s\" object destructed\n", num_primitives, m_LayerName);
	--num_primitives;
	TRACE("%d left\n\n", num_primitives);

	delete [] m_LayerName;

	//Dump(afxDump);
}
/*MR v příkladu se nepoužívá
//kopirovaci konstruktor
CPrimitiveBase::CPrimitiveBase(const CPrimitiveBase & pb)
{
	TRACE("-- Entering CPrimitiveBase copy constructor --\n" );

	m_len = pb.m_len;
	m_LayerName = new char[m_len +1];
	strcpy(m_LayerName, pb.m_LayerName);

	m_ObjectColor.R = pb.m_ObjectColor.R;	//R
	m_ObjectColor.G = pb.m_ObjectColor.G;	//G
	m_ObjectColor.B = pb.m_ObjectColor.B;	//B
	m_ObjectColor.A = pb.m_ObjectColor.A;	//pruhlednost

	m_EnvColor.R = pb.m_EnvColor.R;	//R
	m_EnvColor.G = pb.m_EnvColor.G;	//G
	m_EnvColor.B = pb.m_EnvColor.B;	//B
	m_EnvColor.A = pb.m_EnvColor.A;	//pruhlednost

	m_vn[0] = pb.m_vn[0];
	m_vn[1] = pb.m_vn[1];
	m_vn[2] = pb.m_vn[2];

	m_angle.alfa = pb.m_angle.alfa;
	m_angle.beta = pb.m_angle.beta;
	m_angle.gama = pb.m_angle.gama;
	
	m_distance = pb.m_distance;						
	m_width = pb.m_width;							
	m_height = pb.m_height;							
	m_center = pb.m_center;
	m_XPeriod = pb.m_XPeriod;
	m_YPeriod = pb.m_YPeriod;
	m_XPeriodCount = pb.m_XPeriodCount;
	m_YPeriodCount = pb.m_YPeriodCount;
//	m_Overflow = pb.m_Overflow;

	m_bUse = pb.m_bUse;

	num_primitives++;
	TRACE("%d: \"%s\" object created\n\n", num_primitives, m_LayerName);
}*/
/*MR v příkladu se nepoužívá
CPrimitiveBase & CPrimitiveBase::operator=(const CPrimitiveBase &pb)
{
	if (this == &pb)
		return *this;

	delete [] m_LayerName;
	m_len = pb.m_len;
	m_LayerName = new char[m_len +1];
	strcpy(m_LayerName, pb.m_LayerName);

	m_ObjectColor.R = pb.m_ObjectColor.R;	//R
	m_ObjectColor.G = pb.m_ObjectColor.G;	//G
	m_ObjectColor.B = pb.m_ObjectColor.B;	//B
	m_ObjectColor.A = pb.m_ObjectColor.A;	//pruhlednost

	m_EnvColor.R = pb.m_EnvColor.R;	//R
	m_EnvColor.G = pb.m_EnvColor.G;	//G
	m_EnvColor.B = pb.m_EnvColor.B;	//B
	m_EnvColor.A = pb.m_EnvColor.A;	//pruhlednost

	m_vn[0] = pb.m_vn[0];
	m_vn[1] = pb.m_vn[1];
	m_vn[2] = pb.m_vn[2];

	m_angle.alfa = pb.m_angle.alfa;
	m_angle.beta = pb.m_angle.beta;
	m_angle.gama = pb.m_angle.gama;
	
	m_distance = pb.m_distance;						
	m_width = pb.m_width;							
	m_height = pb.m_height;							
	m_center = pb.m_center;
	m_XPeriod = pb.m_XPeriod;
	m_YPeriod = pb.m_YPeriod;
	m_XPeriodCount = pb.m_XPeriodCount;
	m_YPeriodCount = pb.m_YPeriodCount;

	m_bUse = pb.m_bUse;

	return *this;
}*/
/*MR v příkladu se nepoužívá
void CPrimitiveBase::Rename(const char* newName)
{
	TRACE("-- Entering CPrimitiveBase::Rename --\n");
	TRACE("Puvodni nazev: \"%s\"\n", m_LayerName);

	delete [] m_LayerName;
	m_len = strlen(newName);
	m_LayerName = new char[m_len + 1];
	strcpy(m_LayerName, newName);

	TRACE("Novy nazev: \"%s\"\n\n", m_LayerName);
}
*/
void CPrimitiveBase::SetSize(int width, int height)
{
	m_width = width;							
	m_height = height;	
}

void CPrimitiveBase::SetLayerCenter(CStructures::fPoint center)
{
	m_center = center;
}

void CPrimitiveBase::SetXRepetition(int period, int cycles)
{
	m_XPeriod = period;
	m_XPeriodCount = cycles;
}

void CPrimitiveBase::SetYRepetition(int period, int cycles)
{
	m_YPeriod = period;
	m_YPeriodCount = cycles;
}

CStructures::ARGBPixel CPrimitiveBase::GetObjectColor(bool OnObject)
{

	if(OnObject)
	{
		return m_ObjectColor;
	}
	else
	{
		return m_EnvColor;
	}
}


CStructures::iPoint CPrimitiveBase::GetSize() const
{
	//TRACE("-- Entering CPrimitiveBase::GetSize --\n");

	CStructures::iPoint size;

	size.X = m_width;
	size.Y = m_height;

	return size;
}

CStructures::fPoint CPrimitiveBase::GetCenter() const
{
	//TRACE("-- Entering CPrimitiveBase::GetCenter --\n");
	return m_center;
}

double CPrimitiveBase::GetDistanceToCamera() const
{
	return m_distance;
}


CStructures::iPoint CPrimitiveBase::GetRealPoint(CStructures::iPoint VirtualPosition)
{
	TRACE("-- Entering CPrimitiveBase::GetRealPoint --\n");

	return VirtualPosition;
}

// MR je to blbost, ale kvůli kompatibilitě
CStructures::ARGBPixel CPrimitiveBase::GetPixelValue(CStructures::iPoint position)
{
	CStructures::ARGBPixel pixel;
	 pixel.A = -1;
	 pixel.R = -1;
	 pixel.G = -1;
	 pixel.B = -1; 

	 return pixel;
}

CStructures::ARGBPixel CPrimitiveBase::GetPixelValue(double point[3])
{
	CStructures::ARGBPixel pixel;
	 pixel.A = -1;
	 pixel.R = -1;
	 pixel.G = -1;
	 pixel.B = -1; 

	 return pixel;
}


CStructures::ARGBPixel CPrimitiveBase::GetPixelValueMR(double Position[3]) 
{ // vstupem je průmět bodu na detektoru (reálná hodnota pozice v desetinách pixelu, v homogenních souřadnicích)
	int i,j;
	double point[3]={0};
	// bod vynásobím transformací rovina rovina
	for (i=0;i<3;i++)
		for (j=0;j<3;j++)
			point[i] += Plane2Plane[i][j]*Position[j];
	// provedu normalizaci bodu
	
	point[0] /= point[2];
	point[1] /= point[2];

	// zjistím hodnotu jasu v daném bodě 
	return GetPixelValue(point);
}

void CPrimitiveBase::GetPosition(double vn[])
{
	vn[0] = m_vn[0];
	vn[1] = m_vn[1];
	vn[2] = m_vn[2];
}

void CPrimitiveBase::Translate(int dx, int dy)
{
	TRACE("-- Entering CPrimitiveBase::Translate --\n");
}

void CPrimitiveBase::Rotate(double gama)
{
	TRACE("-- Entering CPrimitiveBase::Rotate --\n");
}

void CPrimitiveBase::Resample(CStructures::Supersample supersample)
{
	TRACE("-- Entering CPrimitiveBase::Resample --\n");
}
/*MR v příkladu se nepoužívá
void CPrimitiveBase::RotXY(double angleX, double angleY)
{
	const double PI = 3.14159265358979323846;
	double alfa_rad,beta_rad;

	//uhly v radianech
	alfa_rad = PI/180*angleX;
	beta_rad = PI/180*angleY;

	//matice rotace okolo X
	double rotX[] = {1,         0,           0,
					 0, cos(alfa_rad), -sin(alfa_rad),
					 0, sin(alfa_rad),  cos(alfa_rad) };

	//matice rotace okolo Y
	double rotY[] = {cos(beta_rad),         0,          sin(beta_rad),
					 0,                     1,          0,
					 -sin(beta_rad),        0,          cos(beta_rad) };

	//Nastaveni vychozi polohy roviny. Zaciname vzdy od (0,0,1)
	CPrimitiveBase::ResetPosition();

	//vytvoreni matic
	CvMat Vn = cvMat(3, 1, CV_64FC1, m_vn);
	CvMat RotX = cvMat(3, 3, CV_64FC1, rotX);
	CvMat RotY = cvMat(3, 3, CV_64FC1, rotY);

	//matice transformace a vysledna matice
	CvMat* resT = cvCreateMat(3,3,CV_64FC1);
	CvMat* resM = cvCreateMat(3,1,CV_64FC1);

	//nasobeni transformaci
	cvMatMul(&RotX,&RotY,resT);
	//nasobeni vysledne transformace s normalovym vektorem
	cvMatMul(resT,&Vn,resM);

	double* data = resM->data.db;

	m_vn[0] = data[0];
	m_vn[1] = data[1];
	m_vn[2] = data[2];

	//ulozeni uhlu natoceni
	m_angle.alfa = angleX;
	m_angle.beta = angleY;

}*/
/*MR v příkladu se nepoužívá
void CPrimitiveBase::ResetPosition()
{
	m_vn[0] = 0;
	m_vn[1] = 0;
	m_vn[2] = 1;

	m_angle.alfa = 0;
	m_angle.beta = 0;
	m_angle.gama = 0;
}*/

void CPrimitiveBase::SetAngle(CStructures::Angle angle)
{
	m_angle.alfa = angle.alfa /180 * 3.14159265358979323846 ;
	m_angle.beta = angle.beta /180 * 3.14159265358979323846 ;
	m_angle.gama = angle.gama /180 * 3.14159265358979323846 ;
}

CStructures::iPoint CPrimitiveBase::PointBegin()
{
	CStructures::iPoint point = {0,0};
	return point;
}

CStructures::iPoint CPrimitiveBase::PointEnd()
{
	CStructures::iPoint point = {0,0};
	return point;
}

void CPrimitiveBase :: SetPl2PlTr(double Tr[3][3])
{
	for (int i=0;i<3;i++)
		for (int j = 0;j<3;j++)
			Plane2Plane[i][j] = Tr[i][j];

}

double Determinant(double b1[], double b2[], double b3[],int vypust)
{
 double pom = 0;
 int i,j;
 double bp1[3],bp2[3],bp3[3];

 for (i=0,j=0;i<4;i++)
 {
  if(i==vypust) continue;
  bp1[j] = b1[i];
  bp2[j] = b2[i];
  bp3[j] = b3[i];
  j++;
 }

 pom += bp1[0]*bp2[1]*bp3[2];
 pom += bp1[1]*bp2[2]*bp3[0];
 pom += bp1[2]*bp2[0]*bp3[1];
 pom -= bp1[2]*bp2[1]*bp3[0];
 pom -= bp1[1]*bp2[0]*bp3[2];
 pom -= bp1[0]*bp2[2]*bp3[1];

 return pom;
}


// na základě vzdálenosti a natočení roviny se vygeneruje rovnice roviny
void CPrimitiveBase::DefinePlane(double Distance, double uhelx, double uhelz)
{
	double bod1[4] = {0,Distance,0,1}; // definice počátku
	double bod2[4] = {1,Distance,0,1}; // definice bodu na ose x
	double bod3[4] = {0,Distance,1,1}; // definice bodu na ose z

	bod2[0] = cos(uhelz) * bod2[0]; bod2[1] -= sin(uhelz) * 1; 
	bod3[0] = cos(uhelx) * bod2[3]; bod2[1] -= sin(uhelx) * 1;  //MR natáčím to humpolácky ale zatím to musí stačit

	Plane[0] =  Determinant(bod1,bod2,bod3,0);
	Plane[1] = -Determinant(bod1,bod2,bod3,1);
	Plane[2] =  Determinant(bod1,bod2,bod3,2);
	Plane[3] = -Determinant(bod1,bod2,bod3,3);
}

//dumping objektu
#ifdef _DEBUG

void CPrimitiveBase::Dump(CDumpContext& dc) const
{
	CObject::Dump(dc);
	dc << //"Object color: " << m_ObjectColor << 
		//"\nObject aplha: " << m_ObjectAlpha <<
		//"\nEnv color: " << m_EnvColor << 
		//"\nEnvAplha: " << m_EnvAlpha <<
		"\nvn=(" << m_vn[0] << "," << m_vn[1] << "," << m_vn[2] << ")" <<
		"\nDistance: " << m_distance <<
		"\nWidth: " << m_width <<
		"\nHeight: " << m_height <<
		"\nObject center X = " << m_center.X <<
		"\n              Y = " << m_center.Y << 
		"\nXRepeatPeriod: " << m_XPeriod <<
		"\nYRepeatPeriod: " << m_YPeriod <<
		"\nXPeriodCount: " << m_XPeriodCount <<
		"\nYPeriodCount: " << m_YPeriodCount <<
		"\n\n";  
}
#endif // _DEBUG
