// JamoBoundBNCore.cpp: implementation of the CJamoBoundBNCore class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "JamoBoundBNCore.h"


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

CJamoBoundBNCore::CJamoBoundBNCore()
{

}

CJamoBoundBNCore::~CJamoBoundBNCore()
{

}
/*
________________________________________________________________
  
Function Name	: InitBN
	
Purpose			: 배치규칙번호로부터 그에 해당한 자모위치관계모형을 만든다.
		
Input			: 
	pBN			: 자모위치관계모형	
	nType		: 배치규칙번호	

Output			: No	

Return Value	: 성공이면 TRUE,실패이면 FALSE

Description		: 

Ref Journal		: No
	
date			: 2009/06/5
________________________________________________________________
*/
BOOL CJamoBoundBNCore::InitBN(JamoBoundBN *pBN,int nType)
{
	pBN->nType = nType;
	if(nType>5 || nType<0)return FALSE;
	if(nType>=0 && nType<=2)
		pBN->nRectNum = 2;
	else 
		pBN->nRectNum = 3;
	pBN->ThDis = MAXDIS;
	CreateParentLink(pBN);
	return TRUE;

}
/*
________________________________________________________________
  
Function Name	: CreateParentLink
	
Purpose			: 자모위치관계모형에 있는 모든 외접4각형모형들에 대하여 그의 부모관계를 설정한다.
		
Input			: 
	pBN			: 자모위치관계모형	

Output			: No	

Return Value	: 성공이면 TRUE,실패이면 FALSE

Description		: No

Ref Journal		: "Bayesian Network Modeling of Hangul Characters for On-line Handwriting Recognition"  
						Sung-Jung Cho*, Jin H. Kim   ICDAR (2003), pp. 207-211 vol.1
	
date			: 2009/06/5
________________________________________________________________
*/
BOOL CJamoBoundBNCore::CreateParentLink(JamoBoundBN *pBN)
{
	int i;
	int RectNum = pBN->nRectNum;
	if(RectNum < 2) return FALSE;
	for(i=0;i<RectNum;i++){
		pBN->pRect[i] = (RectModel*)malloc(sizeof(RectModel));
	}
	///////////// 0  //////////////////
	RectModel* pRect;
	pRect = pBN->pRect[0];
	pRect->ThDis = MAXDIS;
	pRect->countParents = 0;
	pRect->W[0] = (float*)malloc((pRect->countParents*4+1)*sizeof(float));
	pRect->W[1] = (float*)malloc((pRect->countParents*4+1)*sizeof(float));
	pRect->W[2] = (float*)malloc((pRect->countParents*4+1)*sizeof(float));
	pRect->W[3] = (float*)malloc((pRect->countParents*4+1)*sizeof(float));
	///////////// 1  //////////////////
	pRect = pBN->pRect[1];
	pRect->ThDis = MAXDIS;
	pRect->countParents = 1;
	pRect->parent = (RectModel**)malloc(pRect->countParents*sizeof(RectModel*));
	pRect->parent[0] = pBN->pRect[0];
	pRect->W[0] = (float*)malloc((pRect->countParents*4+1)*sizeof(float));
	pRect->W[1] = (float*)malloc((pRect->countParents*4+1)*sizeof(float));
	pRect->W[2] = (float*)malloc((pRect->countParents*4+1)*sizeof(float));
	pRect->W[3] = (float*)malloc((pRect->countParents*4+1)*sizeof(float));
	///////////// 2  //////////////////
	if(RectNum==2) return TRUE;
	pRect = pBN->pRect[2];
	pRect->ThDis = MAXDIS;
	pRect->countParents = 2;
	pRect->parent = (RectModel**)malloc(pRect->countParents*sizeof(RectModel*));
	pRect->parent[0] = pBN->pRect[0];
	pRect->parent[1] = pBN->pRect[1];
	pRect->W[0] = (float*)malloc((pRect->countParents*4+1)*sizeof(float));
	pRect->W[1] = (float*)malloc((pRect->countParents*4+1)*sizeof(float));
	pRect->W[2] = (float*)malloc((pRect->countParents*4+1)*sizeof(float));
	pRect->W[3] = (float*)malloc((pRect->countParents*4+1)*sizeof(float));

	return TRUE;
}
/*
________________________________________________________________
  
Function Name	: LoadBN
	
Purpose			: 파일로부터 자모위치관계모형을 적재한다. 
		
Input			: 
	pBN			: 자모위치관계모형	
	file		: 읽어들이려는 자모위치관계모형이 들어있는 파일구조체포인터	

Output			: No	

Return Value	: 적재성공이면 TRUE,실패이면 FALSE

Description		: 

Ref Journal		: No
	
date			: 2009/06/5
________________________________________________________________
*/
BOOL CJamoBoundBNCore::LoadBN(JamoBoundBN *pBN, FILE *file)
{
	RectModel* pRect;
	int j,paNum;
	fread(&(pBN->nType),sizeof(int),1,file);
	fread(&(pBN->nRectNum),sizeof(int),1,file);
	fread(&(pBN->ThDis),sizeof(float),1,file);

	if(!CreateParentLink(pBN)) return FALSE;
	for(j=0;j<pBN->nRectNum;j++){
		pRect = pBN->pRect[j];
		fread(&(pRect->ThDis),sizeof(float),1,file);
		fread(pRect->ramda,sizeof(float),4,file);
		fread(pRect->matrix,sizeof(float),4*4,file);
		paNum = pRect->countParents;
		fread(pRect->W[0],sizeof(float),(paNum*4+1),file);
		fread(pRect->W[1],sizeof(float),(paNum*4+1),file);
		fread(pRect->W[2],sizeof(float),(paNum*4+1),file);
		fread(pRect->W[3],sizeof(float),(paNum*4+1),file);
		memset(pRect->P,0,sizeof(float)*4);
	}
	return TRUE;
}
/*
________________________________________________________________
  
Function Name	: SaveBN
	
Purpose			: 자모위치관계모형을 파일에 보관한다. 
		
Input			: 
	pBN			: 자모위치관계모형	
	file		: 보관하려는 파일구조체포인터	

Output			: No	

Return Value	: 보관성공이면 TRUE,실패이면 FALSE

Description		: 

Ref Journal		: No
	
date			: 2009/06/5
________________________________________________________________
*/
BOOL CJamoBoundBNCore::SaveBN(JamoBoundBN *pBN, FILE *file)
{
	RectModel* pRect;
	int j,paNum;
	fwrite(&(pBN->nType),sizeof(int),1,file);
	fwrite(&(pBN->nRectNum),sizeof(int),1,file);
	fwrite(&(pBN->ThDis),sizeof(float),1,file);

	for(j=0;j<pBN->nRectNum;j++){
		pRect = pBN->pRect[j];
		fwrite(&(pRect->ThDis),sizeof(float),1,file);
		fwrite(pRect->ramda,sizeof(float),4,file);
		fwrite(pRect->matrix,sizeof(float),4*4,file);
		paNum = pRect->countParents;
		fwrite(pRect->W[0],sizeof(float),(paNum*4+1),file);
		fwrite(pRect->W[1],sizeof(float),(paNum*4+1),file);
		fwrite(pRect->W[2],sizeof(float),(paNum*4+1),file);
		fwrite(pRect->W[3],sizeof(float),(paNum*4+1),file);
	}
	return TRUE;
}
/*
________________________________________________________________
  
Function Name	: ForwardBN
	
Purpose			: 자모위치관계모형의 정합확률 계산
		
Input			: 
	pBN			: 자모위치관계모형		

Output			: No	

Return Value	: 자모위치관계모형의 정합확률

Description		: 이 자모위치관계모형에 있는 모든 외접4각형모형들의 정합확률의 적으로
				  총정합확률이 계산된다.
				  계산론적으로는 로그확률을 이용하여 합으로 계산된다.

Ref Journal		: No
	
date			: 2009/06/5
________________________________________________________________
*/
float CJamoBoundBNCore::ForwardBN(JamoBoundBN *pBN)
{
	float dis=0.0f;
	int RectNum = pBN->nRectNum;
	if(RectNum<2)return MAXDIS;
	int i;
	for(i=0;i<RectNum;i++){
		dis += ForwardRect(pBN,i);
	}
	return dis;
}
/*
________________________________________________________________
  
Function Name	: FowoardRect
	
Purpose			: 외접4각형모형의 정합확률 계산
		
Input			: 
	pBN			: 자모위치관계모형	
	RectId		: 계산하려는 외접4각형모형번호 	

Output			: No	

Return Value	: 외접4각형모형의 정합확률

Description		: 이 자모위치관계모형의  RectId번째 외접4각형모형의 정합확률이 계산된다.				  

Ref Journal		: No
	
date			: 2009/06/5
________________________________________________________________
*/
float CJamoBoundBNCore::ForwardRect(JamoBoundBN *pBN,int RectId)
{
	if(RectId<0 || RectId>=pBN->nRectNum) return MAXDIS;
	float dis=0.0f;
	RectModel* pRect;
	int j;
	int ParNum;
	float mean[4],scala[4];
	pRect = pBN->pRect[RectId];
	ParNum = pRect->countParents;
	memset(&mean,0,sizeof(float)*4);
	for (j=0;j<ParNum;j++) {
		mean[0] += pRect->W[0][j*4]*pRect->parent[j]->P[0] + pRect->W[0][j*4+1]*pRect->parent[j]->P[1]
				  +pRect->W[0][j*4+2]*pRect->parent[j]->P[2] + pRect->W[0][j*4+3]*pRect->parent[j]->P[3];
		mean[1] += pRect->W[1][j*4]*pRect->parent[j]->P[0] + pRect->W[1][j*4+1]*pRect->parent[j]->P[1]
				  +pRect->W[1][j*4+2]*pRect->parent[j]->P[2] + pRect->W[1][j*4+3]*pRect->parent[j]->P[3];
		mean[2] += pRect->W[2][j*4]*pRect->parent[j]->P[0] + pRect->W[2][j*4+1]*pRect->parent[j]->P[1]
				  +pRect->W[2][j*4+2]*pRect->parent[j]->P[2] + pRect->W[2][j*4+3]*pRect->parent[j]->P[3];
		mean[3] += pRect->W[3][j*4]*pRect->parent[j]->P[0] + pRect->W[3][j*4+1]*pRect->parent[j]->P[1]
				  +pRect->W[3][j*4+2]*pRect->parent[j]->P[2] + pRect->W[3][j*4+3]*pRect->parent[j]->P[3];
	}
	mean[0] += pRect->W[0][ParNum*4];
	mean[1] += pRect->W[1][ParNum*4];
	mean[2] += pRect->W[2][ParNum*4];
	mean[3] += pRect->W[3][ParNum*4];

	mean[0] = pRect->P[0] - mean[0];
	mean[1] = pRect->P[1] - mean[1];
	mean[2] = pRect->P[2] - mean[2];
	mean[3] = pRect->P[3] - mean[3];
		
	scala[0] = pRect->matrix[0][0]*mean[0] + pRect->matrix[0][1]*mean[1]
			+ pRect->matrix[0][2]*mean[2] + pRect->matrix[0][3]*mean[3];
	scala[1] = pRect->matrix[1][0]*mean[0] + pRect->matrix[1][1]*mean[1]
			+ pRect->matrix[1][2]*mean[2] + pRect->matrix[1][3]*mean[3];
	scala[2] = pRect->matrix[2][0]*mean[0] + pRect->matrix[2][1]*mean[1]
			+ pRect->matrix[2][2]*mean[2] + pRect->matrix[2][3]*mean[3];
	scala[3] = pRect->matrix[3][0]*mean[0] + pRect->matrix[3][1]*mean[1]
			+ pRect->matrix[3][2]*mean[2] + pRect->matrix[3][3]*mean[3];

	dis += scala[0]*scala[0]/pRect->ramda[0];//*ord[i];
	dis += scala[1]*scala[1]/pRect->ramda[1];//*ord[i];
	dis += scala[2]*scala[2]/pRect->ramda[2];//*ord[i];
	dis += scala[3]*scala[3]/pRect->ramda[3];//*ord[i];
	return dis;
}
/*
________________________________________________________________
  
Function Name	: SetDataInBN
	
Purpose			: 입력된 외접4각형 배열을 자모위치관계모형의 모든 외접4각형모형에 대응시킨다.
		
Input			: 
	pBN			: 자모위치관계모형	
	pRects		: 외접4각형 배열 	

Output			: No	

Return Value	: 성공이면 TRUE, 실패이면 FALSE

Description		: 입력된 외접4각형 배열을 자모위치관계모형의 모든 외접4각형모형들에 차례로 대응시킨다.				  

Ref Journal		: No
	
date			: 2009/06/5
________________________________________________________________
*/
BOOL CJamoBoundBNCore::SetDataInBN(JamoBoundBN *pBN,RECT* pRects)
{
	if(pRects==NULL) return FALSE;
	RectModel* pRect;
	int i;
	for(i=0;i<pBN->nRectNum;i++){
		pRect = pBN->pRect[i];
		pRect->P[0] = (float)(pRects[i].left);
		pRect->P[1] = (float)(pRects[i].top);
		pRect->P[2] = (float)(pRects[i].right-pRects[i].left);
		pRect->P[3] = (float)(pRects[i].bottom-pRects[i].top);
	}
	return TRUE;
}
/*
________________________________________________________________
  
Function Name	: SetDataInRect
	
Purpose			: 입력된 외접4각형을 자모위치관계모형의 RectId번째 4각형모형에 대응시킨다.
		
Input			: 
	pBN			: 자모위치관계모형	
	RectId		: 대응시킬 외접4각형번호
	rt			: 입력외접4각형 

Output			: No	

Return Value	: 성공이면 TRUE, 실패이면 FALSE

Description		: No

Ref Journal		: No
	
date			: 2009/06/5
________________________________________________________________
*/
BOOL CJamoBoundBNCore::SetDataInRect(JamoBoundBN *pBN,int RectId,RECT rt)
{
	if(RectId<0 || RectId>=pBN->nRectNum) return FALSE;
	RectModel* pRect;
	pRect = pBN->pRect[RectId];
	pRect->P[0] = (float)(rt.left);
	pRect->P[1] = (float)(rt.top);
	pRect->P[2] = (float)(rt.right-rt.left);
	pRect->P[3] = (float)(rt.bottom-rt.top);
	return TRUE;
}
/*
________________________________________________________________
  
Function Name	: deleteBN
	
Purpose			: 자모위치관계모형에 할당된 메모리 해제 .
		
Input			: 
	pBN			: 자모위치관계모형	

Output			: No	

Return Value	: 해제성공이면 TRUE,실패이면 FALSE

Description		: 

Ref Journal		: No
	
date			: 2009/06/5
________________________________________________________________
*/
BOOL CJamoBoundBNCore::deleteBN(JamoBoundBN *pBN)
{
	int j;
	RectModel* pRect;

	for(j=0;j<pBN->nRectNum;j++){
		pRect = pBN->pRect[j];
		if(pRect->countParents>0) free(pRect->parent);
		free(pRect->W[0]);
		free(pRect->W[1]);
		free(pRect->W[2]);
		free(pRect->W[3]);
		free(pRect);
	}
	return TRUE;
}
