// PatternManager.cpp: implementation of the CPatternManager class.
//
//////////////////////////////////////////////////////////////////////

/** \file PatternManager.cpp
	\brief implementace třídy CPatternManager
*/

#include "stdafx.h"
#include "PatternManager.h"

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

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

CPatternManager::CPatternManager()
{   
	TRACE("-- Entering CPatternManager constructor --\n");
	
	m_outPattern = NULL;
	m_listLayerCreated.RemoveAll();
//	m_projDistance = 0;
	m_xSize = 800;
	m_ySize = 600;
	
	m_supersample.X = 1;
	m_supersample.Y = 1;

	m_bDisplay = true;
	m_bSave = false;

	int len = 7;
	m_patternName = new char[len + 1];
	strcpy(m_patternName, "Pattern");
}

CPatternManager::~CPatternManager()
{
	

	CPrimitiveBase* pBase;

	while(!m_listLayerCreated.IsEmpty())
		{
			pBase = (CPrimitiveBase*)m_listLayerCreated.RemoveHead();
			cout << "Removing: " << pBase->GetName() << "\n";
			delete pBase;
		}

	//MR a co odalokování m_listLayerRegistered?

	delete [] m_patternName;

	if(m_outPattern != NULL)
	{
		m_outPattern->Destroy();
		delete m_outPattern;
		m_outPattern = NULL;
	}
	TRACE("-- Leaving  CPatternManager destructor  --\n");	
}

/*MR
void CPatternManager::Rename(const char *newName)
{
	int len;
	
	delete [] m_patternName;
	if(newName != NULL)
	{
		len = strlen(newName);
		m_patternName = new char [len + 1];
		strcpy(m_patternName, newName);
	}
	

}
*/
void CPatternManager::AddLayer(CPrimitiveBase* pPrimitive)
{
	TRACE("-- Entering CPatternManager::AddLayer --\n");	
	TRACE("------> Adding to tail position! \n");

	m_listLayerCreated.AddTail(pPrimitive);
}
void CPatternManager::RegisterLayer(CPrimitiveBase* pPrimitive, int index)
{
	TRACE("Entering CPatternManager::RegisterLayer\n");

	POSITION pos;
	 
	pos = m_listLayerRegistred.FindIndex(index);
	
	if (pos == NULL)
	{
		TRACE("------> Adding to tail position! \n");
		m_listLayerRegistred.AddTail(pPrimitive);
	}
	else
	{
		TRACE("------> Adding to position: %d\n", index );
		m_listLayerRegistred.InsertBefore(pos, pPrimitive);
	}

	pPrimitive->Use(true);
}
/*MR v příkladu se nepoužívá
void CPatternManager::RegisterAll()
{
	POSITION pos;
	CPrimitiveBase* pPB;

	pos = m_listLayerCreated.GetHeadPosition();
	while(pos)
	{
		pPB = (CPrimitiveBase*)m_listLayerCreated.GetNext(pos);
		m_listLayerRegistred.AddTail(pPB);
		pPB->Use(true);
	}
}*/
/*MR v příkladu se nepoužívá
void CPatternManager::UnregisterLayer(int index)
{
	TRACE("Entering CPatternManager::UnregisterLayer\n");

	CPrimitiveBase* pPB;
	POSITION pos;

	pos = m_listLayerRegistred.FindIndex(index);

	if (pos != NULL)
	{
		TRACE("Removing layer at position: %d\n", index);
		pPB = (CPrimitiveBase*)m_listLayerRegistred.GetAt(pos);
		pPB->Use(false);
		m_listLayerRegistred.RemoveAt(pos);
	}
	else
	{
		TRACE("Layer not found!\n");
	}
}*/
/*MR v příkladu se nepoužívá
void CPatternManager::UnregisterAll()
{
	CPrimitiveBase *pPB;

	while(!m_listLayerRegistred.IsEmpty())
		{
			pPB = (CPrimitiveBase*)m_listLayerRegistred.RemoveHead();
			pPB->Use(false);
		}
}*/
/*MR v příkladu se nepoužívá
void CPatternManager::Empty()
{
	CPrimitiveBase* pBase;

	//vyprazdni seznam zarazenych vrstev
	UnregisterAll();

	//vyprazdni seznam vsech vytvorenych vrstev
	while(!m_listLayerCreated.IsEmpty())
		{
			pBase = (CPrimitiveBase*)m_listLayerCreated.RemoveHead();
			cout << "Removing: " << pBase->GetName() << "\n";
			delete pBase;
		}

	m_supersample.X = 1;
	m_supersample.Y = 1;

}*/
/*MR v příkladu se nepoužívá
void CPatternManager::MoveUp(int index)
{
	POSITION posNew;
	POSITION posCur;
	CPrimitiveBase *pLayer;

	posCur = m_listLayerRegistred.FindIndex(index);
	posNew = m_listLayerRegistred.FindIndex(index - 1);

	if (posCur != NULL)
	{
		pLayer = (CPrimitiveBase*)m_listLayerRegistred.GetAt(posNew);
		m_listLayerRegistred.InsertAfter(posCur, pLayer);
		m_listLayerRegistred.RemoveAt(posNew);
		
	}
}*/
/*MR v příkladu se nepoužívá
void CPatternManager::MoveDown(int index)
{
	POSITION posNew;
	POSITION posCur;
	CPrimitiveBase *pLayer;

	posCur = m_listLayerRegistred.FindIndex(index);
	posNew = m_listLayerRegistred.FindIndex(index + 1);

	if (posCur != NULL)
	{
		pLayer = (CPrimitiveBase*)m_listLayerRegistred.GetAt(posCur);
		m_listLayerRegistred.InsertAfter(posNew, pLayer);
		m_listLayerRegistred.RemoveAt(posCur);
		
	}
}*/

int CPatternManager::GetCountCreated()
{
	return m_listLayerCreated.GetCount();
}
/*MR v příkladu se nepoužívá
int CPatternManager::GetCountRegistred()
{
	return m_listLayerRegistred.GetCount();
}*/

CPrimitiveBase* CPatternManager::GetLayerCreated(int index)
{
	POSITION pos;
	pos = m_listLayerCreated.FindIndex(index);

	if (pos != NULL)
	{
		//printf("Geting layer at position: %d\n", index);
		return (CPrimitiveBase*)m_listLayerCreated.GetAt(pos);
	}
	else
	{
		printf("Layer not found!\n");
		return NULL;
	}
}
/*MR v příkladu se nepoužívá
CPrimitiveBase* CPatternManager::GetLayerRegistred(int index)
{
	POSITION pos;
	pos = m_listLayerRegistred.FindIndex(index);

	if (pos != NULL)
	{
		//printf("Geting layer at position: %d\n", index);
		return (CPrimitiveBase*)m_listLayerRegistred.GetAt(pos);
	}
	else
	{
		printf("Layer not found!\n");
		return NULL;
	}
}
*/
/*/MR nevolá se (v daném příkladu volání) a prakticky asi nic nedělá kromě posunu seznamem (???) - je označena v h jako nepoužívaná
bool CPatternManager::BuildPattern()
{
	TRACE("Building pattern.....\n");

	CPrimitiveBase* pPrimitive;

	

	if (m_listLayerCreated.GetCount() > 0)
	{
		m_pos = m_listLayerCreated.GetHeadPosition();

		while(m_pos)
		{
			pPrimitive = (CPrimitiveBase*)m_listLayerCreated.GetNext(m_pos);
			GetPattern(pPrimitive);
		}

		
		return true;
	}
	else
		return false;
}
*/
/*MR označena v h jako nepoužívaná
void CPatternManager::GetPattern(CPrimitiveBase* cpatt)
{
	m_outPattern = new CPixelArray(800, 600, 4);
	m_outPattern->Clear();

	float grayValue = 0; //aktualni odstin
	float alfaWeight = 1; //vaha dane barvy (zavisi na pruhlednosti predchozich vrstev)
	CStructures::ARGBPixel actualPixel;	
	CStructures::Point actualPoint;

	int x,y;
	int width = 800;
	int heigth = 600;

	for(x = -(width/2); x < (width/2)-1; x++)
		for(y = -(heigth/2)+1; y < (heigth/2); y++)
		{	
			actualPoint.X = x; //nastavime pixel
			actualPoint.Y = y; //nastavime pixel
				
			/*ziskani ARGB hodnot pozadovaneho pixelu aktualniho objektu s ohledem na prevzorkovani* /			
			actualPixel = cpatt->GetPixelValue(actualPoint);	
				
			//grayValue = actualPixel.G;	
			grayValue += ((float(actualPixel.A/255)) * actualPixel.G); //vypocet jasu pixelu
				
			m_outPattern->SetGrayPixel(actualPoint, grayValue);	//ulozime jasovou hodnotu do dat filtru	
		}
		m_outPattern->Display("MasterImage");
}
*/

/*MR označena v h jako nepoužívaná
void CPatternManager::BuildPatternOld(int width, int heigth)
{
	CStructures::ARGBPixel valueARGB = {1,0,0,0}; //aktualni odstin ARGB
	float alfaWeight = 1; //vaha dane barvy (zavisi na pruhlednosti predchozich vrstev)
	CStructures::ARGBPixel actualPixel;	
	CStructures::Point actualPoint;
	CPrimitiveBase* pPrimitive;

	int x,y;
	m_outPattern = new CPixelArray(width, heigth, 4);
	m_outPattern->Clear();

	m_pos = m_listLayerCreated.GetHeadPosition(); //prvni vzor v rade

	for(x = -(width/2); x < (width/2)-1; x++)
		for(y = -(heigth/2)+1; y < (heigth/2); y++)
		{
			do
			{
				actualPoint.X = x; //nastavime pixel
				actualPoint.Y = y; //nastavime pixel

				pPrimitive = (CPrimitiveBase*)m_listLayerCreated.GetNext(m_pos);
				actualPixel = pPrimitive->GetPixelValue(actualPoint);
				
				valueARGB.R += ((float)(actualPixel.A/255) * valueARGB.A * actualPixel.R); //vypocet jasu pixelu
				valueARGB.G += ((float)(actualPixel.A/255) * valueARGB.A * actualPixel.G); //vypocet jasu pixelu
				valueARGB.B += ((float)(actualPixel.A/255) * valueARGB.A * actualPixel.B); //vypocet jasu pixelu
				valueARGB.A = 1 - (valueARGB.A * (float)actualPixel.A/255); //prepocitani vahy jasove hodnoty nasledujiciho objektu

			}while( (actualPixel.A < 255) && (m_pos != NULL));

			//m_outPattern->SetGrayPixel(actualPoint, grayValue);	//ulozime jasovou hodnotu do dat filtru	
			m_outPattern->SetRGBPixel(actualPoint, valueARGB);

			valueARGB.R = 0; //reset barvy pixelu na defaultni cernou
			valueARGB.G = 0; //reset barvy pixelu na defaultni cernou
			valueARGB.B = 0; //reset barvy pixelu na defaultni cernou
			valueARGB.A = 1; //reset vahy hodnoty pixelu na 100% 
			
			m_pos = m_listLayerCreated.GetHeadPosition(); //prvni vzor v rade
		}

 		m_outPattern->Display("MasterImage");
		m_outPattern->Save("c:\\Hasan\\Diplomka\\Vzory\\textura.jpg");
}
*/

//MR dávat ven ukazatel na interní prvek není šťastné
CPixelArray* CPatternManager::GetPattern()
{
	return m_outPattern;
}

void Nasob(double vys[4][4],double mat1[4][4],double mat2[4][4])
{
	double pom[4][4]={0};
	int i,j,k;

	for (i=0;i<4;i++)
		for (j=0;j<4;j++)
			for (k=0;k<4;k++)
			   pom[i][j]+=mat1[i][k]*mat2[k][j];

   for (i=0;i<4;i++)
		for (j=0;j<4;j++)
			vys[i][j] = pom [i][j];
   
}

void Nasob3(double vys[3][3],double mat1[3][3],double mat2[3][3])
{
	double pom[3][3]={0};
	int i,j,k;

	for (i=0;i<3;i++)
		for (j=0;j<3;j++)
			for (k=0;k<3;k++)
			   pom[i][j]+=mat1[i][k]*mat2[k][j];

   for (i=0;i<3;i++)
		for (j=0;j<3;j++)
			vys[i][j] = pom [i][j];
   
}


void RotaceX4(double vys[4][4],double mat[4][4], double uhel)
{
	double matuhel[4][4]={0};//MR, vysl[4][4];
//MR int i,j;
 matuhel[0][0] =  matuhel[3][3] = 1;
 matuhel[1][1] =  cos(uhel);
 matuhel[1][2] =  sin(uhel);
 matuhel[2][2] =  cos(uhel);
 matuhel[2][1] = -sin(uhel);
 Nasob(vys,mat,matuhel);

}

void RotaceY4(double vys[4][4],double mat[4][4], double uhel)
{
	double matuhel[4][4]={0};//MR, vysl[4][4];
//MR int i,j;
 matuhel[1][1] =  matuhel[3][3] = 1;
 matuhel[0][0] =  cos(uhel);
 matuhel[0][2] =  sin(uhel);
 matuhel[2][2] =  cos(uhel);
 matuhel[2][0] = -sin(uhel);
 Nasob(vys,mat,matuhel);

}

void RotaceZ4(double vys[4][4],double mat[4][4], double uhel)
{
	double matuhel[4][4]={0};//MR, vysl[4][4];
 
 matuhel[2][2] =  matuhel[3][3] = 1;
 matuhel[0][0] =  cos(uhel);
 matuhel[0][1] = -sin(uhel);
 matuhel[1][1] =  cos(uhel);
 matuhel[1][0] =  sin(uhel);
 Nasob(vys,mat,matuhel);

}

void Translace1 (double vys[4][4],double mat[4][4],double tr[4])
{
 double matp[4][4]={0};//MR, vysl[4][4];
 
 matp[0][0] = matp[2][2] =matp[3][3] =  matp[1][1] = 1;
 matp[0][3] = tr[0];
 matp[1][3] = tr[1];
 matp[2][3] = tr[2];
 matp[3][3] = tr[3];
 Nasob(vys,mat,matp);
}

void Translace (double vys[4][4],double mat[4][4],double tr[4])
{
 double matp[4][4]={0};//MR, vysl[4][4];
 
 matp[0][0] = matp[2][2] =matp[3][3] =  matp[1][1] = 1;
 matp[0][3] = tr[0];
 matp[1][3] = tr[1];
 matp[2][3] = tr[2];
 matp[3][3] = tr[3];
 Nasob(vys,matp,mat);
}


void CopyMat (double vys[4][4],double mat[4][4])
{
	int i,j;


   for (i=0;i<4;i++)
		for (j=0;j<4;j++)
			vys[i][j] = mat [i][j];
}

void TrBod(double vys[4],double tr[4][4],double bod[4])
{
	double pom[4]={0};
	int i,j;

	for (i=0;i<4;i++)
		for (j=0;j<4;j++)
			pom[i] += tr[i][j]*bod[j];
	for (i=0;i<4;i++)
		vys[i] = pom[i];
}
/*
void Inverze (double vys[4][4],double mat[4][4])
{
	int i,j,k,l;
	double pom[4][4];
	double det = 0;

	for (i=0;i<4;i++)
		for (j=0;j<4;j++)
			for (k=0;k<4;k++)
				for (l=0;l<4;l++)

   for (i=0;i<4;i++)
		for (j=0;j<4;j++)
			vys[i][j] = mat [i][j];
}
*/

 void Inverze(double vys[4][4],double mat[4][4], double ZeroRange)
{
int i,j,k,ip,jp;
double pivot,pvt,*r;


double amat[4][4]={0},bmat[4][4]={0};

bmat[0][0]=bmat[1][1]=bmat[2][2]=bmat[3][3]=1;

int n=4; //columns; // and rows

for (i=0;i<n;i++)
	for (j=0;j<n;j++)
		amat[i][j] = mat [i][j];


r=new double [n];

for(i=0;i<n;i++)
	r[i]=1;


for(k=0;k<n;k++)
	{
		pivot=0;
		for(i=0;i<n;i++)
			for(j=0;j<n;j++)
				{
					pvt=amat[i][j]*r[i];
					if(pvt<0.0)
						pvt=-pvt;
					if(pvt>pivot)
						{
							pivot=pvt;
							ip=i;
							jp=j;
						}
					}
			if (fabs(pivot)<=ZeroRange)
				{
					delete[] r;
					return ;
				}
			r[ip]=0;
			pivot=amat[ip][jp];
			for(j=0;j<n;j++)
				{
					amat[ip][j]/=pivot;
					bmat[ip][j]/=pivot;
				}
			for (i=0;i<n;i++)
				if(i!=ip)
					{
						for(j=0;j<n;j++)
							bmat[i][j]-=amat[i][jp]*bmat[ip][j];
						for(j=0;j<n;j++)
							if(j!=jp)
								amat[i][j]-=amat[i][jp]*amat[ip][j];
					}
				for(i=0;i<n;i++)
					if (i!=ip)
						amat[i][jp]=0;
				}
for(i=0;i<n;i++)
	for(j=0;j<n;j++)
		if (amat[i][j]!=0.0)
			for(k=0;k<n;k++)
				vys[j][k]=bmat[i][k];

delete[] r;
return ;
}

 void Inverze3(double vys[3][3],double mat[3][3], double ZeroRange)
{
int i,j,k,ip,jp;
double pivot,pvt,*r;


double amat[3][3]={0},bmat[3][3]={0};

bmat[0][0]=bmat[1][1]=bmat[2][2]=1;

int n=3; //columns; // and rows

for (i=0;i<n;i++)
	for (j=0;j<n;j++)
		amat[i][j] = mat [i][j];



r=new double [n];

for(i=0;i<n;i++)
	r[i]=1;


for(k=0;k<n;k++)
	{
		pivot=0;
		for(i=0;i<n;i++)
			for(j=0;j<n;j++)
				{
					pvt=amat[i][j]*r[i];
					if(pvt<0.0)
						pvt=-pvt;
					if(pvt>pivot)
						{
							pivot=pvt;
							ip=i;
							jp=j;
						}
					}
			if (fabs(pivot)<=ZeroRange)
				{
					delete[] r;
					return ;
				}
			r[ip]=0;
			pivot=amat[ip][jp];
			for(j=0;j<n;j++)
				{
					amat[ip][j]/=pivot;
					bmat[ip][j]/=pivot;
				}
			for (i=0;i<n;i++)
				if(i!=ip)
					{
						for(j=0;j<n;j++)
							bmat[i][j]-=amat[i][jp]*bmat[ip][j];
						for(j=0;j<n;j++)
							if(j!=jp)
								amat[i][j]-=amat[i][jp]*amat[ip][j];
					}
				for(i=0;i<n;i++)
					if (i!=ip)
						amat[i][jp]=0;
				}
for(i=0;i<n;i++)
	for(j=0;j<n;j++)
		if (amat[i][j]!=0.0)
			for(k=0;k<n;k++)
				vys[j][k]=bmat[i][k];

delete[] r;
return ;
}

 double Det3(double mat[3][3])
 {
  double ret = 0;
  ret += mat[0][0]*mat[1][1]*mat[2][2];
  ret += mat[0][1]*mat[1][2]*mat[2][0];
  ret += mat[0][2]*mat[1][0]*mat[2][1];
  ret -= mat[0][0]*mat[1][2]*mat[2][1];
  ret -= mat[0][1]*mat[1][0]*mat[2][2];
  ret -= mat[0][2]*mat[1][1]*mat[2][0];
  return ret;
 }

 void Body2Rovina(double rovina[4],double bod1[4],double bod2[4],double bod3[4])
 {
	 double pom[3][3]={0};
  double rov[4];
  int i,j,k;

  for (k=0;k<4;k++)
  {
	for (i=0, j = 0;i<4;i++)
	{
	  if (i == k) 
		  continue;
      pom[0][j] = bod1[i];
	  pom[1][j] = bod2[i];
	  pom[2][j] = bod3[i];
	  j++;
	}
   rov[k]=Det3(pom);
  }
  rov[1]*=-1;rov[3]*=-1;
  for (i=0 ;i<4;i++)
	  rovina[i]=rov[i];
 }

 void PrusecikPrimkaRovina(double vys[4],double rovina[4],double Q[4],double R[4])
 {
  double pom1=0, pom2=0;
  int i;

  for (i=0;i<4;i++)
  {
	  pom1 += Q[i]*rovina[i];
	  pom2 += R[i]*rovina[i];
  }
  double v[4]={0};
  for (i=0;i<4;i++)
	  v[i]= pom1 * R[i] - pom2 * Q[i];
  for (i=0;i<4;i++)
	  vys[i] = v[i];
 }


int CPatternManager::BuildMasterImage(bool bPreview , bool useFile, const char* fileName)
{
	TRACE("-- Entering CPatternManager::BuildMasterImage --\n");	
	TRACE("Creating MasterImage.... \n");
	cout << "Building pattern...\n";
	//Vytvoreni 2D obrazu, ktery se preda filtrum
	int i,j;

	if(!useFile)		
	{


		/*MR
		double vn[] = {0, 0, 1}; //normalovy vektor roviny vzoru
		double t0[] = {0, 0, 0}; //stredovy bod roviny
		double r1[] = {0, 0, 0}; //bod promitaci roviny
		double t;				 //parametr paprsku
		int distanceProj = 545;	 //vzdalenost promitaci roviny
		int distance;			 //vzdalenost roviny vzoru	
		 MR*/
		
		CStructures::iPoint projPoint;/*MR, pattPoint;
		
		CStructures::ARGBPixel valueARGB = {1, 0, 0, 0}; //aktualni odstin	MR*/
		CStructures::ARGBPixel actualPixel;
		CPrimitiveBase* pPrimitive;

	
					

		int x,y;
/*MR		
		CStructures::iPoint Size;	
		//nahled vzdy bez prevzorkovani
		if(!bPreview)
		{
			//prevzorkovani predlohy
			if(m_supersample.X > 1 || m_supersample.Y > 1)
			{
				if(!(m_pos = m_listLayerRegistred.GetHeadPosition()))
					return 1;
				do
				{  //MR bohužel tady procházím vzory a ne filtry
					pPrimitive = (CPrimitiveBase*)m_listLayerRegistred.GetNext(m_pos);
					pPrimitive->Resample(m_supersample); //MR tohle tu byt nemusí
					Center = pPrimitive->GetCenter(); //MR tohle je tu "nestasne" jen proto abych se dostal k parametrum rozmeru posledniho filtru pred prumetem
					Size = pPrimitive->GetSize();
				}while(m_pos != NULL);
			} MR*/
		
		
		//*MR		}

		//MR - tohle by se mělo vzít z posledního filtru
		// rozměry obrázku - "syrové"/skutečné pixely
		int width = m_xSize;
		int height = m_ySize;	
		CStructures::fPoint Center;
		Center.X = m_xSize/2;
		Center.Y = m_ySize/2;
		// měřítko - pro přepočet pixelů obrázku/skutečných na rozměry pixelů kamery
		double ZvetseniX = m_xScale, ZvetseniY = m_yScale; //MR zadáno před/při volání patternmanageru

		long pixels = (width * height)/100; // výpočet pixelů obrázku pro zobrazovani procent
		long pix = 0;
			
         

		//obraz promitaci roviny  - příprava na uložení výsledku 
		if(m_outPattern != NULL)
		{
			TRACE("Uvolnuji m_outPattern");
			m_outPattern->Destroy();
			//MR  m_outPattern = NULL;
			delete m_outPattern ;
		}  //MR*/
		
		m_outPattern = new CPixelArray(width, height, 4); //MR problém - dumping objects - patrně není odalokováno (?)
		m_outPattern->Clear(); // fill by zero
		
		double cc = cam.GetDistanceToO();
		// zjištění projekční transformace kamery pro přepočet projekčních bodů. Projekční střed je přímo v kameře - stejná pro všechny vzory
		double ProjCenter[4];
		cam.GetProjectionCenter(ProjCenter[0],ProjCenter[1],ProjCenter[2]);
		ProjCenter[3]= 1;
		//MR chybí zde stanovení transformace ze tří rotací - zatím pouze jednotková - jinak se vypočte ze tří úhlů uložených v kameře
		double RotCam[4][4]={1,0,0,0,  0,1,0,0,  0,0,1,0,  0,0,0,1}; // rotace camery
		double ucx, ucy, ucz;
		double TrCam[4][4]={0}; // transformace do souřadné soustavy kamery
		double InvTrCam[4][4]={0}; // inverzní transformace pro zpětný převod "reálné" kamery do počátku
		double B1[4]={0,cc,0,1},B2[4]={1,cc,0,1},B3[4]={0,cc,1,1}; // bod ve středu a na osách roviny detektoru

		/*/test
int i,j;
printf("\n     A "); for(i=0,printf("\n");i<4;i++,printf("\n"))	for(j=0;j<4;j++) printf("%lf ",RotCam[i][j]);
		Inverze(InvTrCam,RotCam,1e-14);
printf("\n     A "); for(i=0,printf("\n");i<4;i++,printf("\n"))	for(j=0;j<4;j++) printf("%lf ",RotCam[i][j]);
printf("\n Inv A "); for(i=0,printf("\n");i<4;i++,printf("\n"))	for(j=0;j<4;j++) printf("%lf ",InvTrCam[i][j]);
		Nasob(TrCam,InvTrCam,RotCam);
printf("\n     A "); for(i=0,printf("\n");i<4;i++,printf("\n"))	for(j=0;j<4;j++) printf("%lf ",RotCam[i][j]);
printf("\n Inv A "); for(i=0,printf("\n");i<4;i++,printf("\n"))	for(j=0;j<4;j++) printf("%lf ",InvTrCam[i][j]);
printf("\n     I "); for(i=0,printf("\n");i<4;i++,printf("\n"))	for(j=0;j<4;j++) printf("%lf ",TrCam[i][j]);
*/
		cam.GetRotation(ucx,ucy,ucz);
		RotaceY4(RotCam,RotCam,ucy/180 * 3.14159265358979323846);		
		RotaceX4(RotCam,RotCam,ucx/180 * 3.14159265358979323846);
		RotaceZ4(RotCam,RotCam,ucz/180 * 3.14159265358979323846);

		CopyMat(TrCam,RotCam);
		Translace(TrCam,TrCam,ProjCenter);
		//tady potřebuju inverzi
		Inverze(InvTrCam,TrCam,1e-15);
		TrBod(B1,TrCam,B1);
		TrBod(B2,TrCam,B2);
		TrBod(B3,TrCam,B3);
		double Prumetna[4];

		
		Body2Rovina(Prumetna,B1,B2,B3); // rovina detektoru


// generování transformačních rovnic rovina vzoru - rovina detektoru, pro každou rovinu vzoru
//nastavit prvni vzor v rade - pro zjisteni parametru
		
		if(!(m_pos = m_listLayerRegistred.GetHeadPosition()))
			return 1;	
        while (m_pos!= NULL) {
		pPrimitive = (CPrimitiveBase*)m_listLayerRegistred.GetNext(m_pos);	

		// zvolíme tři body v rovině vzoru, nejdříve s nimi zarotujeme a posuneme v rovině
		// potom s nimi zarotujeme v prostoru, a nakonec je posuneme do správné vzdálenosti
		double P1[4]={0,0,0,1},P2[4]={1,0,0,1},P3[4]={0,0,1,1}; // bod ve středu a na osách roviny vzoru
		double RotVzor[4][4]={1,0,0,0,  0,1,0,0,  0,0,1,0,  0,0,0,1};
		
		CStructures::Angle angl = pPrimitive->GetAngle();
		CStructures::fPoint stred = pPrimitive->GetCenter();
		double H[4]={0,0,0,1}; 
		H[1] = pPrimitive->GetDistanceToCamera();
		double Pom[4]= {stred.X,0, stred.Y,1 };
		// rotace bodů kolem y
		RotaceY4(RotVzor,RotVzor,angl.beta );
		// posun bodů v rovině vzoru
		Translace(RotVzor,RotVzor,Pom );
		// rotace bodů kolem osy x
		RotaceX4(RotVzor,RotVzor,angl.alfa );
		// rotace bodů kolem osy z
		RotaceZ4(RotVzor,RotVzor,angl.gama );
		// posun bodů do vzdálenosti vzoru H
		Translace(RotVzor,RotVzor,H);
		// dosud pouze transformace, teď je uplatníme na body
		TrBod(P1,RotVzor,P1);
		TrBod(P2,RotVzor,P2);
		TrBod(P3,RotVzor,P3);
		// průmět bodů do roviny kamery (natočené) - je nutné ???
		double P1p[4],P2p[4],P3p[4];
		PrusecikPrimkaRovina(P1p,Prumetna,ProjCenter,P1);
		PrusecikPrimkaRovina(P2p,Prumetna,ProjCenter,P2);
		PrusecikPrimkaRovina(P3p,Prumetna,ProjCenter,P3);
		// průmět bodů do roviny kamery nenatočené - je-li vše správně, měla by hodnota v y se rovnat ohnisku
		TrBod(P1p,InvTrCam,P1p);
		TrBod(P2p,InvTrCam,P2p);
		TrBod(P3p,InvTrCam,P3p);
		// transformace z roviny na rovinu - zkusím nejdříve "prostý" výpočet i když by to nemělo vyjít
		double BodyVzor[3][3]={0,1,0,  0,0,1,  1,1,1};
		double BodyPrumet[3][3]={0  };
		// všechny souřadnice zatím v mm 
		for (i=0,j=0;i<4;i++)
		{
			double meritko;
			switch(i) {
			case 0: meritko = cam.GetXmm() ;break;
			case 2: meritko = cam.GetYmm() ;break;			
			default: meritko = 1;break;
			};

		 if (i == 1) continue; // souřadnice y se nekopiruje
		 BodyPrumet[j][0] = P1p[i]/meritko;
		 BodyPrumet[j][1] = P2p[i]/meritko;
		 BodyPrumet[j][2] = P3p[i]/meritko;
		 j++;
		}
		Inverze3(BodyPrumet,BodyPrumet,1e-14);
		double TrRR[3][3];
		Nasob3(TrRR,BodyVzor,BodyPrumet); // vysledna transformace rovina rovina - pokud se vše povedlo 
		// zapíšeme transformaci do pPrimitive
		pPrimitive->SetPl2PlTr(TrRR);

		}  // konec přípravy transformací z roviny vzoru do rovniny detektoru

		for(x = 0; x < width; x++) // souřadnice v obrázku
			for(y = 0; y < height; y++)
			{ // tohle by se mělo počítat jen pro bod 0,0 - je nutné vypočítat transformaci z roviny detektoru na rovinu zobrazení
				// lépe řečeno, mělo by se to připravit předem a zapsat do primitiva
				//nastavit prvni vzor v rade
		     if(!(m_pos = m_listLayerRegistred.GetHeadPosition()))
			    return 1;	
			 //MR tohle by ještě mohlo jít do všeobecné transformace rovina rovina
				double Projekce[3]; //aktualni bod na projekcni rovine - detektoru
				Projekce[0] = (x - Center.X) / ZvetseniX; // souřadnice v ploše detektoru
				Projekce[1] = (Center.Y - y) / ZvetseniY;				
				Projekce[2] = 1;
				//MR chybí projekční bod orotovat - je to přímo vektor pohledu, a působiště je projCenter kamery
				CStructures::ARGBPixel valueARGB = {1, 0, 0, 0}; //aktualni odstin pro daný bod
				
				do {	
					pPrimitive = (CPrimitiveBase*)m_listLayerRegistred.GetNext(m_pos);
					
					actualPixel = pPrimitive->GetPixelValueMR(Projekce);
					// zkombinovat pixely, průhlednost - při ukončení zapsat do výsledné mapy snímku
					valueARGB.R += ((float)(actualPixel.A/255) * valueARGB.A * actualPixel.R); //vypocet jasu pixelu
					valueARGB.G += ((float)(actualPixel.A/255) * valueARGB.A * actualPixel.G); //vypocet jasu pixelu
					valueARGB.B += ((float)(actualPixel.A/255) * valueARGB.A * actualPixel.B); //vypocet jasu pixelu
					valueARGB.A = 1 - (valueARGB.A * (float)actualPixel.A/255); //prepocitani vahy jasove hodnoty nasledujiciho objektu

				}while ((actualPixel.A < 255) && (m_pos != NULL)); 

				projPoint.X = x; projPoint.Y = y;
				m_outPattern->SetRGBPixelD(projPoint,valueARGB); //MR pracuje proti středu - nutno předělat

				/*MR		
				
				/*actualPoint.X = x;
				actualPoint.Y = y;* /

				//prepocet pozice pixelu z jemne mrizky na hrubou
				//origProjPoint = GetPixelByResolution(projPoint);

				r1[0] = projPoint.X;			//souradnice bodu
				r1[1] = projPoint.Y;			//na promitaci rovine
//MR				r1[2] = m_projDistance;
				r1[2]= cam.GetDistanceToO()  ;

				//point.X = x;        //aktualni bod
				//point.Y = y;		//na promitaci rovine
				MR*/
/*MR
				do
				{
					pPrimitive = (CPrimitiveBase*)m_listLayerRegistred.GetNext(m_pos);
					//distance = pPrimitive->GetDistanceToCamera();
					//pPrimitive->GetPosition(vn);
					
					// definice průmětu vektoru daného dvěma body a projekční roviny
					// průsečík = (center . rovina) . projekce - (projekce . rovina) . center
					int i;
					double pom1=0,pom2=0, pom[4];
					for (i = 0;i< 4;i++)
					{
					 pom1 += ProjCenter[i]*pPrimitive->Plane[i];
					 pom2 += Projekce[i]*pPrimitive->Plane[i];
					}
					for (i = 0;i< 4;i++)
						pom[i] = pom1 * Projekce[i] - pom2 * ProjCenter[i] ;

					for (i = 0;i< 4;i++) // normalizace - teď by to měl být průsečík s rovinou
 						pom[i] /= pom[3];
					
					// "zpětné" orotování bodu v případě rotované a posunuté předlohy


					//bod na rovine vzoru
					pattPoint.X = (int)t*projPoint.X; //MR ta konverze asi není nejštastnější - chtělo by to ukládat do float
						pattPoint.Y = (int)t*projPoint.Y;

						actualPixel = pPrimitive->GetPixelValue(pom);

						valueARGB.R += ((float)(actualPixel.A/255) * valueARGB.A * actualPixel.R); //vypocet jasu pixelu
						valueARGB.G += ((float)(actualPixel.A/255) * valueARGB.A * actualPixel.G); //vypocet jasu pixelu
						valueARGB.B += ((float)(actualPixel.A/255) * valueARGB.A * actualPixel.B); //vypocet jasu pixelu
						valueARGB.A = 1 - (valueARGB.A * (float)actualPixel.A/255); //prepocitani vahy jasove hodnoty nasledujiciho objektu
					}
				
				}while((actualPixel.A < 255) && (m_pos != NULL));
				/*MR
				m_outPattern->SetRGBPixel(projPoint,valueARGB); //MR pracuje proti středu - nutno předělat

				valueARGB.R = 0; //reset barvy pixelu na defaultni cernou
				valueARGB.G = 0; //reset barvy pixelu na defaultni cernou
				valueARGB.B = 0; //reset barvy pixelu na defaultni cernou
				valueARGB.A = 1; //reset vahy hodnoty pixelu na 100% 
					
				m_pos = m_listLayerRegistred.GetHeadPosition(); //prvni vzor v rade
				MR*/
				pix++;
				if((pix % pixels) == 0) printf("\rprogress: %d%% done", pix/pixels);
			}//end for   
			printf("\n"); 
	}//end if(!useFile)
	else
	{  
		cout << "Getting pattern from file...\n";
		
		if(m_outPattern != NULL) //MR
		{
			TRACE("Uvolnuji m_outPattern");
			m_outPattern->Destroy();		
			delete m_outPattern ;
		} 

		m_outPattern = new CPixelArray();
		if(!m_outPattern->Load(fileName))
			return 2;
	}
	
	if(m_bDisplay)
		m_outPattern->Display(m_patternName);
	if(m_bSave)
		m_outPattern->Save(m_outputName.c_str() );

    TRACE("Done\n");

	return 0;
}


void CPatternManager::SetOutputName(char *name)
{
	m_outputName = name;
}

/*MRXXX původní verze
int CPatternManager::BuildMasterImage(bool bPreview , bool useFile, const char* fileName)
{
	TRACE("-- Entering CPatternManager::BuildMasterImage --\n");	
	TRACE("Creating MasterImage.... \n");
	cout << "Building pattern...\n";
	//Vytvoreni 2D obrazu, ktery se preda filtrum
	
	if(!useFile)		
	{
		double vn[] = {0, 0, 1}; //normalovy vektor roviny vzoru
		double t0[] = {0, 0, 0}; //stredovy bod roviny
		double r1[] = {0, 0, 0}; //bod promitaci roviny
		double t;				 //parametr paprsku
		int distanceProj = 545;	 //vzdalenost promitaci roviny
		int distance;			 //vzdalenost roviny vzoru	

		
		CStructures::iPoint projPoint, pattPoint;

		CStructures::ARGBPixel valueARGB = {1, 0, 0, 0}; //aktualni odstin
		CStructures::ARGBPixel actualPixel;	
		CPrimitiveBase* pPrimitive;

		int width = m_xSize;
		int height = m_ySize;
		int x,y;


		
		//nahled vzdy bez prevzorkovani
		if(!bPreview)
		{
			//prevzorkovani predlohy
			if(m_supersample.X > 1 || m_supersample.Y > 1)
			{
				if(!(m_pos = m_listLayerRegistred.GetHeadPosition()))
					return 1;
				do
				{
					pPrimitive = (CPrimitiveBase*)m_listLayerRegistred.GetNext(m_pos);
					pPrimitive->Resample(m_supersample);
				}while(m_pos != NULL);
			}
		}

		long pixels = (width * height)/100;
		long pix = 0;


		//nastavit prvni vzor v rade
		if(!(m_pos = m_listLayerRegistred.GetHeadPosition()))
			return 1;

		//obraz promitaci roviny
		/*if(m_outPattern != NULL)
		{
			TRACE("Uvolnuji m_outPattern");
			m_outPattern->Destroy();
			m_outPattern = NULL;
		}* / 
		
		m_outPattern = new CPixelArray(width, height, 4);
		m_outPattern->Clear();
		

		for(x = -(width/2); x < (width/2)-1; x++)
			for(y = -(height/2)+1; y < (height/2); y++)
			{
				//aktualni bod na oversample projekcni rovine
				projPoint.X = x;
				projPoint.Y = y;

				/*actualPoint.X = x;
				actualPoint.Y = y;* /

				//prepocet pozice pixelu z jemne mrizky na hrubou
				//origProjPoint = GetPixelByResolution(projPoint);

				r1[0] = projPoint.X;			//souradnice bodu
				r1[1] = projPoint.Y;			//na promitaci rovine
				r1[2] = m_projDistance;

				//point.X = x;        //aktualni bod
				//point.Y = y;		//na promitaci rovine

				do
				{
					pPrimitive = (CPrimitiveBase*)m_listLayerRegistred.GetNext(m_pos);
					distance = pPrimitive->GetDistanceToCamera();
					pPrimitive->GetPosition(vn);

					t0[2] = distance;


					CvMat Vn = cvMat(3, 1, CV_64FC1, vn);
					CvMat T0 = cvMat(3, 1, CV_64FC1, t0);
					CvMat R1 = cvMat(3, 1, CV_64FC1, r1);

					t = (cvDotProduct(&T0, &Vn)) / (cvDotProduct(&R1, &Vn));

					if(t >= 1)
					{
						//bod na rovine vzoru
						pattPoint.X = (int)t*projPoint.X; //MR ta konverze asi není nejštastnější - chtělo by to ukládat do float
						pattPoint.Y = (int)t*projPoint.Y;

						actualPixel = pPrimitive->GetPixelValue(pattPoint);

						valueARGB.R += ((float)(actualPixel.A/255) * valueARGB.A * actualPixel.R); //vypocet jasu pixelu
						valueARGB.G += ((float)(actualPixel.A/255) * valueARGB.A * actualPixel.G); //vypocet jasu pixelu
						valueARGB.B += ((float)(actualPixel.A/255) * valueARGB.A * actualPixel.B); //vypocet jasu pixelu
						valueARGB.A = 1 - (valueARGB.A * (float)actualPixel.A/255); //prepocitani vahy jasove hodnoty nasledujiciho objektu
					}
				
				}while((actualPixel.A < 255) && (m_pos != NULL));
				
				m_outPattern->SetRGBPixel(projPoint,valueARGB);

				valueARGB.R = 0; //reset barvy pixelu na defaultni cernou
				valueARGB.G = 0; //reset barvy pixelu na defaultni cernou
				valueARGB.B = 0; //reset barvy pixelu na defaultni cernou
				valueARGB.A = 1; //reset vahy hodnoty pixelu na 100% 
					
				m_pos = m_listLayerRegistred.GetHeadPosition(); //prvni vzor v rade
				
				pix++;
				if((pix % pixels) == 0) printf("\rprogress: %d%% done", pix/pixels);
			}//end for
			printf("\n");
	}//end if(!useFile)
	else
	{
		cout << "Getting pattern from file...\n";
		m_outPattern = new CPixelArray();
		if(!m_outPattern->Load(fileName))
			return 2;
	}

	if(m_bDisplay)
		m_outPattern->Display(m_patternName);
	if(m_bSave)
		m_outPattern->Save(m_patternName);

    TRACE("Done\n");

	return 0;
}*/

/*MR označena v h jako nepoužívaná
void CPatternManager::rot(double vectn[], double angleX, double angleY)
{
	const double PI = 3.14159265358979323846;
	double alfa_rad,beta_rad;
		
	alfa_rad = PI/180*angleX;
	beta_rad = PI/180*angleY;
	

	double rotX[] = {1,         0,           0,
					 0, cos(alfa_rad), -sin(alfa_rad),
					 0, sin(alfa_rad),  cos(alfa_rad) };

	double rotY[] = {cos(beta_rad),         0,          sin(beta_rad),
					 0,                     1,          0,
					 -sin(beta_rad),        0,          cos(beta_rad) };

	CvMat Vn = cvMat(3, 1, CV_64FC1, vectn);
	CvMat RotX = cvMat(3, 3, CV_64FC1, rotX);
	CvMat RotY = cvMat(3, 3, CV_64FC1, rotY);

	CvMat* resT = cvCreateMat(3,3,CV_64FC1);
	CvMat* resM = cvCreateMat(3,1,CV_64FC1);

	cvMatMul(&RotX,&RotY,resT);
	cvMatMul(resT,&Vn,resM);

	double* data = resM->data.db;

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

	
}
*/

void CPatternManager::SetResolution(int xSize, int ySize)
{
	m_xSize = xSize;
	m_ySize = ySize;
}
/*MR v příkladu se nepoužívá
CStructures::Point CPatternManager::GetResolution()
{
	CStructures::Point res;

	res.X = m_xSize;
	res.Y = m_ySize;

	return res;
}*/
/*MR v příkladu se nepoužívá
void CPatternManager::SetSupersample(CStructures::Supersample supersample)
{
	m_supersample.X = supersample.X;
	m_supersample.Y = supersample.Y;

}
*/


void CPatternManager::SetSize(int xSize,int ySize,double xScale, double yScale)
{
	m_xSize = xSize; m_ySize = ySize;
	m_xScale = xScale; m_yScale = yScale;
}
