// JamoBTWBNCore.cpp: implementation of the CJamoBTWBNCore class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "JamoBTWBNCore.h"


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

CJamoBTWBNCore::CJamoBTWBNCore()
{

}

CJamoBTWBNCore::~CJamoBTWBNCore()
{

}
/*
________________________________________________________________
  
Function Name	: InitBN
	
Purpose			: 자모간 연결획모형을 만든다. 
		
Input			: 
	pBN			: 자모간 연결획모형	
	CJorJZfg	: 초-중 또는 중-종인가를 가르는 플래그(0:초-중,1:중-종)
	PreJamoId	: 앞자모번호(CJorJZfg=0인 경우는 초성번호,CJorJZfg=1인 경우는 중성번호)
	AftJamoId	: 뒤자모번호(CJorJZfg=0인 경우는 중성번호,CJorJZfg=1인 경우는 종성번호)

Output			: No	

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

Description		: 

Ref Journal		: No
	
date			: 2009/06/5
________________________________________________________________
*/
BOOL CJamoBTWBNCore::InitBN(JamoBTWBN *pBN,BOOL CJorJZfg,int PreJamoId,int AftJamoId)
{
	pBN->bStudied = FALSE;
	pBN->CJorJZfg = CJorJZfg;
	pBN->PreJamoId = PreJamoId;
	pBN->AftJamoId = AftJamoId;
	pBN->ThDis = MAXDIS;
	CreateParentLink(pBN);
	return TRUE;

}
/*
________________________________________________________________
  
Function Name	: CreateParentLink
	
Purpose			: 자모간 연결획모형에 있는 모든 점모형들에 대하여 그의 부모관계를 설정한다.
		
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 CJamoBTWBNCore::CreateParentLink(JamoBTWBN *pBN)
{
	int i;
	PointModel* pPoint;

	for(i=0;i<WSRS;i++){
		pBN->pPoint[i] = (PointModel*)malloc(sizeof(PointModel));
	}
	///////////// 0  //////////////////
	pPoint = pBN->pPoint[0];
	pPoint->countParents = 0;
	pPoint->W[0] = (float*)malloc((pPoint->countParents*2+1)*sizeof(float));
	pPoint->W[1] = (float*)malloc((pPoint->countParents*2+1)*sizeof(float));
	///////////// 1  //////////////////
	pPoint = pBN->pPoint[1];
	pPoint->countParents = 2;
	pPoint->parent = (PointModel**)malloc(pPoint->countParents*sizeof(PointModel*));
	pPoint->parent[0] = pBN->pPoint[0];
	pPoint->parent[1] = pBN->pPoint[2];
	pPoint->W[0] = (float*)malloc((pPoint->countParents*2+1)*sizeof(float));
	pPoint->W[1] = (float*)malloc((pPoint->countParents*2+1)*sizeof(float));
	///////////// 2  //////////////////
	pPoint = pBN->pPoint[2];
	pPoint->countParents = 2;
	pPoint->parent = (PointModel**)malloc(pPoint->countParents*sizeof(PointModel*));
	pPoint->parent[0] = pBN->pPoint[0];
	pPoint->parent[1] = pBN->pPoint[4];
	pPoint->W[0] = (float*)malloc((pPoint->countParents*2+1)*sizeof(float));
	pPoint->W[1] = (float*)malloc((pPoint->countParents*2+1)*sizeof(float));
	///////////// 3  //////////////////
	pPoint = pBN->pPoint[3];
	pPoint->countParents = 2;
	pPoint->parent = (PointModel**)malloc(pPoint->countParents*sizeof(PointModel*));
	pPoint->parent[0] = pBN->pPoint[2];
	pPoint->parent[1] = pBN->pPoint[4];
	pPoint->W[0] = (float*)malloc((pPoint->countParents*2+1)*sizeof(float));
	pPoint->W[1] = (float*)malloc((pPoint->countParents*2+1)*sizeof(float));
	///////////// 4  //////////////////
	pPoint = pBN->pPoint[4];
	pPoint->countParents = 2;
	pPoint->parent = (PointModel**)malloc(pPoint->countParents*sizeof(PointModel*));
	pPoint->parent[0] = pBN->pPoint[0];
	pPoint->parent[1] = pBN->pPoint[WSRS-1];
	pPoint->W[0] = (float*)malloc((pPoint->countParents*2+1)*sizeof(float));
	pPoint->W[1] = (float*)malloc((pPoint->countParents*2+1)*sizeof(float));
	///////////// 5  //////////////////
	pPoint = pBN->pPoint[5];
	pPoint->countParents = 2;
	pPoint->parent = (PointModel**)malloc(pPoint->countParents*sizeof(PointModel*));
	pPoint->parent[0] = pBN->pPoint[4];
	pPoint->parent[1] = pBN->pPoint[6];
	pPoint->W[0] = (float*)malloc((pPoint->countParents*2+1)*sizeof(float));
	pPoint->W[1] = (float*)malloc((pPoint->countParents*2+1)*sizeof(float));
	///////////// 6  //////////////////
	pPoint = pBN->pPoint[6];
	pPoint->countParents = 2;
	pPoint->parent = (PointModel**)malloc(pPoint->countParents*sizeof(PointModel*));
	pPoint->parent[0] = pBN->pPoint[4];
	pPoint->parent[1] = pBN->pPoint[WSRS-1];
	pPoint->W[0] = (float*)malloc((pPoint->countParents*2+1)*sizeof(float));
	pPoint->W[1] = (float*)malloc((pPoint->countParents*2+1)*sizeof(float));
	///////////// 7  //////////////////
	pPoint = pBN->pPoint[7];
	pPoint->countParents = 2;
	pPoint->parent = (PointModel**)malloc(pPoint->countParents*sizeof(PointModel*));
	pPoint->parent[0] = pBN->pPoint[6];
	pPoint->parent[1] = pBN->pPoint[WSRS-1];
	pPoint->W[0] = (float*)malloc((pPoint->countParents*2+1)*sizeof(float));
	pPoint->W[1] = (float*)malloc((pPoint->countParents*2+1)*sizeof(float));
	///////////// 8  //////////////////
	pPoint = pBN->pPoint[8];
	pPoint->countParents = 1;
	pPoint->parent = (PointModel**)malloc(pPoint->countParents*sizeof(PointModel*));
	pPoint->parent[0] = pBN->pPoint[0];
	pPoint->W[0] = (float*)malloc((pPoint->countParents*2+1)*sizeof(float));
	pPoint->W[1] = (float*)malloc((pPoint->countParents*2+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 CJamoBTWBNCore::LoadBN(JamoBTWBN *pBN, FILE *file)
{
	PointModel* pPoint;
	int j,paNum;
	fread(&(pBN->CJorJZfg),sizeof(BOOL),1,file);
	fread(&(pBN->bStudied),sizeof(BOOL),1,file);
	fread(&(pBN->PreJamoId),sizeof(int),1,file);
	fread(&(pBN->AftJamoId),sizeof(int),1,file);
	fread(&(pBN->ThDis),sizeof(float),1,file);

	CreateParentLink(pBN);
	for(j=0;j<WSRS;j++){
		pPoint = pBN->pPoint[j];
		fread(pPoint->ramda,sizeof(float),2,file);
		fread(pPoint->matrix,sizeof(float),2*2,file);
		paNum = pPoint->countParents;
		fread(pPoint->W[0],sizeof(float),(paNum*2+1),file);
		fread(pPoint->W[1],sizeof(float),(paNum*2+1),file);
		memset(pPoint->P,0,sizeof(float)*2);
	}
	return TRUE;
}
/*
________________________________________________________________
  
Function Name	: LoadBN
	
Purpose			: 자모간 연결획모형을 파일에 보관한다. 
		
Input			: 
	pBN			: 자모간 연결획모형	
	file		: 보관하려는 파일구조체포인터	

Output			: No	

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

Description		: 

Ref Journal		: No
	
date			: 2009/06/5
________________________________________________________________
*/
BOOL CJamoBTWBNCore::SaveBN(JamoBTWBN *pBN, FILE *file)
{
	PointModel* pPoint;
	int j,paNum;
	fwrite(&(pBN->CJorJZfg),sizeof(BOOL),1,file);
	fwrite(&(pBN->bStudied),sizeof(BOOL),1,file);
	fwrite(&(pBN->PreJamoId),sizeof(int),1,file);
	fwrite(&(pBN->AftJamoId),sizeof(int),1,file);
	fwrite(&(pBN->ThDis),sizeof(float),1,file);

	for(j=0;j<WSRS;j++){
		pPoint = pBN->pPoint[j];
		fwrite(pPoint->ramda,sizeof(float),2,file);
		fwrite(pPoint->matrix,sizeof(float),2*2,file);
		paNum = pPoint->countParents;
		fwrite(pPoint->W[0],sizeof(float),(paNum*2+1),file);
		fwrite(pPoint->W[1],sizeof(float),(paNum*2+1),file);
	}
	return TRUE;
}
/*
________________________________________________________________
  
Function Name	: ForwardBN
	
Purpose			: 자모간 연결획모형의 정합확률 계산
		
Input			: 
	pBN			: 자모간 연결획모형		

Output			: No	

Return Value	: 자모간 연결획모형의 정합확률

Description		: 이 자모간 연결획모형에 있는 모든 점모형들의 정합확률의 적으로
				  총정합확률이 계산된다.
				  계산론적으로는 로그확률을 이용하여 합으로 계산된다.

Ref Journal		: No
	
date			: 2009/06/5
________________________________________________________________
*/
float CJamoBTWBNCore::ForwardBN(JamoBTWBN *pBN)
{
	float dis=0.0f;
	PointModel* pPoint;
	int i,j;
	int ParNum;
	float mean[2],scala[2];
	int deep = 2;
	for(i=0;i<WSRS;i++){
		if(deep==2 && i%2 != 0)continue;
		pPoint = pBN->pPoint[i];
		ParNum = pPoint->countParents;
		memset(&mean,0,sizeof(float)*2);
		for (j=0;j<ParNum;j++) {
			mean[0] += pPoint->W[0][j*2]*pPoint->parent[j]->P[0] + pPoint->W[0][j*2+1]*pPoint->parent[j]->P[1];
			mean[1] += pPoint->W[1][j*2]*pPoint->parent[j]->P[0] + pPoint->W[1][j*2+1]*pPoint->parent[j]->P[1];
		}
		mean[0] += pPoint->W[0][ParNum*2];
		mean[1] += pPoint->W[1][ParNum*2];

		mean[0] = pPoint->P[0] - mean[0];
		mean[1] = pPoint->P[1] - mean[1];
		
		scala[0] = pPoint->matrix[0][0]*mean[0] + pPoint->matrix[0][1]*mean[1];
		scala[1] = pPoint->matrix[1][0]*mean[0] + pPoint->matrix[1][1]*mean[1];
		dis += scala[0]*scala[0]/pPoint->ramda[0];//*ord[i];
		dis += scala[1]*scala[1]/pPoint->ramda[1];//*ord[i];
	}
	return dis;
}
/*
________________________________________________________________
  
Function Name	: SetDataInBN
	
Purpose			: 입력된 점 배열을 자모간 연결획모형의 모든 점모형에 대응시킨다.
		
Input			: 
	pBN			: 자모간 연결획모형	
	pPts		: 입력점 배열 
	st			: 입력점 배열에서 연결획의 시작점번호
	ed			: 입력점 배열에서 연결획의 끝점번호	

Output			: No	

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

Description		: 입력된 점 배열을 자모간 연결획모형의 모든 점모형들에 차례로 대응시킨다.				  

Ref Journal		: "Bayesian network modeling of strokes and their relationships for on-line handwriting 
					recognition"   Sung-Jung Cho*, Jin H. Kim   Pattern Recognition 37(2004) 253-264p
	
date			: 2009/06/5
________________________________________________________________
*/
BOOL CJamoBTWBNCore::SetDataInBN(JamoBTWBN *pBN,REC_POINT* pPts,int st,int ed)
{
	if(ed<=st) return FALSE;
	PointModel* pPoint;
	int i,no;
	int len = (ed-st);
	int nodes = (WSRS-1);
	for(i=0;i<WSRS-1;i++){
		if(i%2 != 0)continue;
		pPoint = pBN->pPoint[i];
		no = st + (len*i)/nodes;
 		memcpy(pPoint->P,&pPts[no],sizeof(float)*2);
	}
	pPoint = pBN->pPoint[WSRS-1];
 	memcpy(pPoint->P,&pPts[ed],sizeof(float)*2);
	return TRUE;

}
/*
________________________________________________________________
  
Function Name	: deleteBN
	
Purpose			: 자모간 연결획모형에 할당된 메모리 해제 .
		
Input			: 
	pBN			: 자모간 연결획모형	

Output			: No	

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

Description		: 

Ref Journal		: No
	
date			: 2009/06/5
________________________________________________________________
*/
BOOL CJamoBTWBNCore::deleteBN(JamoBTWBN *pBN)
{
	int j;
	PointModel* pPoint;

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