// RecogCore.cpp: implementation of the CJamoBNCore class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "RecogCore.h"
#include <math.h>

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

CJamoBNCore::CJamoBNCore()
{
}

CJamoBNCore::~CJamoBNCore()
{
}
/*
________________________________________________________________
  
Function Name	: CreateParentLink
	
Purpose			: 자모모형내에 있는 모든 점모형들에 대하여 그의 부모관계를 설정한다.
		
Input			: 
	pBN			: 자모모형	

Output			: No	

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

Description		: 이 함수에서는 깊이심도가 3이라고 보고 자모모형의 모든 획모형내에 있는
				  9개의 점에 관하여 그의 부모관계를 설정한다.				  

Ref Journal		: No
	
date			: 2009/06/5
________________________________________________________________
*/
BOOL CJamoBNCore::CreateParentLink(JAMOBN *pBN)
{
	int StrkNum = pBN->StrokeNum;
	if(StrkNum<1)return FALSE;
	int i,j,st;
	StrokeModel* pStroke,*pPreStroke;
	PointModel* pPoint;
	for(i=0;i<pBN->StrokeNum;i++){
		pStroke = &(pBN->pStroke[i]);
		pStroke->Prop = 0;
		pStroke->ThDis = MAXDIS;
		if(i==0 ){
			st=0;
			for(j=st;j<WSRS;j++){
				pStroke->pPoint[j] = (PointModel*)malloc(sizeof(PointModel));
			}
		}
		else{
			st=1;
			for(j=st;j<WSRS;j++){
				pStroke->pPoint[j] = (PointModel*)malloc(sizeof(PointModel));
			}
			pPreStroke = &(pBN->pStroke[i-1]);
			pStroke->pPoint[0] = pPreStroke->pPoint[WSRS-1];
		}
		///////////// 0  //////////////////
		pPoint = pStroke->pPoint[0];
		if(i==0){
			pPoint->countParents = 0;
			pPoint->W[0] = (float*)malloc(sizeof(float));
			pPoint->W[1] = (float*)malloc(sizeof(float));
		}
		///////////// 1  //////////////////
		pPoint = pStroke->pPoint[1];
		pPoint->countParents = 2;
		pPoint->parent = (PointModel**)malloc(pPoint->countParents*sizeof(PointModel*));
		pPoint->parent[0] = pStroke->pPoint[0];
		pPoint->parent[1] = pStroke->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 = pStroke->pPoint[2];
		pPoint->countParents = 2;
		pPoint->parent = (PointModel**)malloc(pPoint->countParents*sizeof(PointModel*));
		pPoint->parent[0] = pStroke->pPoint[0];
		pPoint->parent[1] = pStroke->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 = pStroke->pPoint[3];
		pPoint->countParents = 2;
		pPoint->parent = (PointModel**)malloc(pPoint->countParents*sizeof(PointModel*));
		pPoint->parent[0] = pStroke->pPoint[2];
		pPoint->parent[1] = pStroke->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 = pStroke->pPoint[4];
		pPoint->countParents = 2;
		pPoint->parent = (PointModel**)malloc(pPoint->countParents*sizeof(PointModel*));
		pPoint->parent[0] = pStroke->pPoint[0];
		pPoint->parent[1] = pStroke->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 = pStroke->pPoint[5];
		pPoint->countParents = 2;
		pPoint->parent = (PointModel**)malloc(pPoint->countParents*sizeof(PointModel*));
		pPoint->parent[0] = pStroke->pPoint[4];
		pPoint->parent[1] = pStroke->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 = pStroke->pPoint[6];
		pPoint->countParents = 2;
		pPoint->parent = (PointModel**)malloc(pPoint->countParents*sizeof(PointModel*));
		pPoint->parent[0] = pStroke->pPoint[4];
		pPoint->parent[1] = pStroke->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 = pStroke->pPoint[7];
		pPoint->countParents = 2;
		pPoint->parent = (PointModel**)malloc(pPoint->countParents*sizeof(PointModel*));
		pPoint->parent[0] = pStroke->pPoint[6];
		pPoint->parent[1] = pStroke->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 = pStroke->pPoint[8];
		pPoint->countParents = i+1;
		pPoint->parent = (PointModel**)malloc(pPoint->countParents*sizeof(PointModel*));
		for(j=0;j<pPoint->countParents;j++){
			pPreStroke = &(pBN->pStroke[j]);
			pPoint->parent[j] = pPreStroke->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	: deleteBN
	
Purpose			: 자모모형에 할당된 메모리 해제 .
		
Input			: 
	pBN			: 자모모형	

Output			: No	

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

Description		: 

Ref Journal		: No
	
date			: 2009/06/5
________________________________________________________________
*/
BOOL CJamoBNCore::deleteBN(JAMOBN *pBN)
{
	int StrkNum = pBN->StrokeNum;
	if(StrkNum<1)return FALSE;
	int i,j,st;
	StrokeModel* pStroke;
	PointModel* pPoint;
	for(i=0;i<pBN->StrokeNum;i++){
		pStroke = &(pBN->pStroke[i]);

		if(i==0 )st=0;
		else st=1;
		for(j=st;j<WSRS;j++){
			pPoint = pStroke->pPoint[j];
			if(pPoint->countParents>0)free(pPoint->parent);
			free(pPoint->W[0]);
			free(pPoint->W[1]);
			free(pStroke->pPoint[j]);
		}
	}
	free(pBN->pStroke);
	return TRUE;
}
/*
________________________________________________________________
  
Function Name	: InitBN
	
Purpose			: 획수와 자모Id,그리고 그룹번호로부터 하나의 자모모형을 만든다.
		
Input			: 
	pBN			: 자모모형	
	strokeNum	: 획수
	JamoId		: 자모Id
	GrpId		: 그룹Id

Output			: No	

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

Description		: 

Ref Journal		: No
	
date			: 2009/06/5
________________________________________________________________
*/
BOOL CJamoBNCore::InitBN(JAMOBN *pBN,int strokeNum,int JamoId,int GrpId)
{
	if(strokeNum < 1) return FALSE;
	pBN->JamoId = JamoId;
	pBN->GrpId = GrpId;
	pBN->StrokeNum = strokeNum;
	pBN->ThDis = MAXDIS;
	pBN->pStroke = (StrokeModel*)malloc(pBN->StrokeNum*sizeof(StrokeModel));//new StrokeModel[pBN->StrokeNum];
	BOOL b = CreateParentLink(pBN);
	return b;
}
/*
________________________________________________________________
  
Function Name	: LoadBN
	
Purpose			: 파일로부터 자모모형을 적재한다. 
		
Input			: 
	pBN			: 자모모형	
	file		: 읽어들이려는 자모모형이 들어있는 파일구조체포인터	

Output			: No	

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

Description		: 

Ref Journal		: No
	
date			: 2009/06/5
________________________________________________________________
*/
BOOL CJamoBNCore::LoadBN(JAMOBN *pBN, FILE *file)
{
	StrokeModel* pStroke;
	PointModel* pPoint;
	int i,j,st,paNum;
	fread(&(pBN->JamoId),sizeof(int),1,file);
	fread(&(pBN->GrpId),sizeof(int),1,file);
	fread(&(pBN->StrokeNum),sizeof(int),1,file);
	fread(&(pBN->ThDis),sizeof(float),1,file);

	if(pBN->StrokeNum < 1) return FALSE;
	pBN->pStroke = (StrokeModel*)malloc(pBN->StrokeNum*sizeof(StrokeModel));

	CreateParentLink(pBN);
	for(i=0;i<pBN->StrokeNum;i++){
		pStroke = &(pBN->pStroke[i]);
		fread(&(pStroke)->Prop,sizeof(int),1,file);
		fread(&(pStroke->ThDis),sizeof(float),1,file);

		if(i==0 )st=0;
		else st=1;
		for(j=st;j<WSRS;j++){
			pPoint = pStroke->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 CJamoBNCore::SaveBN(JAMOBN *pBN, FILE *file)
{
	StrokeModel* pStroke;
	PointModel* pPoint;
	int i,j,st,paNum;
	if(pBN->StrokeNum < 1) return FALSE;
	fwrite(&(pBN->JamoId),sizeof(int),1,file);
	fwrite(&(pBN->GrpId),sizeof(int),1,file);
	fwrite(&(pBN->StrokeNum),sizeof(int),1,file);
	fwrite(&(pBN->ThDis),sizeof(float),1,file);

	for(i=0;i<pBN->StrokeNum;i++){
		pStroke = &(pBN->pStroke[i]);
		fwrite(&(pStroke->Prop),sizeof(int),1,file);
		fwrite(&(pStroke->ThDis),sizeof(float),1,file);
		if(i==0 )st=0;
		else st=1;
		for(j=st;j<WSRS;j++){
			pPoint = pStroke->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			: 자모모형	
	deep		: 깊이심도

Output			: No	

Return Value	: 자모모형의 정합확률

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
________________________________________________________________
*/
float CJamoBNCore::ForwardBN(JAMOBN *pBN,int deep)
{
	float dis=0.0f;
	int StrkNum = pBN->StrokeNum;
	if(StrkNum<1)return MAXDIS;
	int i;
	for(i=0;i<pBN->StrokeNum;i++){
		dis += ForwardStroke(pBN,i,deep);
	}
	return dis;
}
/*
________________________________________________________________
  
Function Name	: ForwardStroke
	
Purpose			: 획모형의 정합확률 계산
		
Input			: 
	pBN			: 자모모형	
	StrokeId	: 계산하려는 획모형번호 
	deep		: 깊이심도

Output			: No	

Return Value	: 획모형의 정합확률

Description		: 이 자모모형의  StrokeId번째 획모형의 정합확률이 계산된다.
				  이때 획모형의 정합확률은 이 획에 들어있는 모든 점모형들의 정합확률의 
				  적으로 계산된다.
				  계산론적으로는 로그확률을 이용하여 합으로 계산된다.

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
________________________________________________________________
*/
float CJamoBNCore::ForwardStroke(JAMOBN *pBN, int StrokeId,int deep)
{
	int StrkId = StrokeId;
	StrokeModel* pStroke = &(pBN->pStroke[StrkId]);
	PointModel* pPoint;
	int i,j,st;
	if(StrkId == 0) st = 0;
	else st = 1;
	float dis=0.0f;
	int ParNum;
	float mean[2],scala[2];

	for(i=st;i<WSRS;i++){
		if(deep==2 && i%2 != 0)continue;
		if(deep==1 && i%4 != 0)continue;
		pPoint = pStroke->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];
		dis += scala[1]*scala[1]/pPoint->ramda[1];
	}
	return dis;
}
/*
________________________________________________________________
  
Function Name	: SetDataInBN
	
Purpose			: 입력된 점 배열을 자모모형의 모든 점모형에 대응시킨다.
		
Input			: 
	pBN			: 자모모형	
	pPts		: 입력점 배열 
	pSelNo		: 획의 끝점번호 배열
	SelNum		: 끝점번호개수

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 CJamoBNCore::SetDataInBN(JAMOBN *pBN,REC_POINT* pPts,int* pSelNo,int SelNum)
{
	if(SelNum!=pBN->StrokeNum+1) return FALSE;
	int i,st,ed;
	for(i=0;i<pBN->StrokeNum;i++){
		st = pSelNo[i];
		ed = pSelNo[i+1];
		SetDataInStroke(pBN,i,pPts,st,ed);
	}
	return TRUE;
}
/*
________________________________________________________________
  
Function Name	: SetDataInStroke
	
Purpose			: 입력된 점 배열을 획모형의 모든 점모형에 대응시킨다.
		
Input			: 
	pBN			: 자모모형	
	StrokeId	: 자모모형pBN내의 주목하는 획모형번호
	pPts		: 입력점 배열 
	st			: 입력점 배열에서 획의 시작점번호
	ed			: 입력점 배열에서 획의 끝점번호
	deep		: 깊이심도

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
________________________________________________________________
*/
void CJamoBNCore::SetDataInStroke(JAMOBN *pBN, int StrokeId,REC_POINT* pPts,int st,int ed,int deep)
{
	int StrkId = StrokeId;
	StrokeModel* pStroke = &(pBN->pStroke[StrkId]);
	PointModel* pPoint;
	int i,no,nst;
	int len = (ed-st);
	int nodes = (WSRS-1);
	if(StrokeId == 0 ) nst=0;
	else nst = 1;
	for(i=nst;i<WSRS-1;i++){
		if(deep==2 && i%2!=0)continue;
		pPoint = pStroke->pPoint[i];
		no = st + (len*i)/nodes;// +0.5f);
 		memcpy(pPoint->P,&pPts[no],sizeof(float)*2);
	}
	pPoint = pStroke->pPoint[WSRS-1];
 	memcpy(pPoint->P,&pPts[ed],sizeof(float)*2);

}
/*
________________________________________________________________
  
Function Name	: SetEndDataInStroke
	
Purpose			: 입력된 점 배열을 획모형의 끝점모형에만 대응시킨다.
		
Input			: 
	pBN			: 자모모형	
	StrokeId	: 자모모형pBN내의 주목하는 획모형번호
	pPts		: 입력점 배열 
	st			: 입력점 배열에서 획의 시작점번호
	ed			: 입력점 배열에서 획의 끝점번호	

Output			: No	

Return Value	: No

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
________________________________________________________________
*/
void CJamoBNCore::SetEndDataInStroke(JAMOBN *pBN, int StrokeId,REC_POINT* pPts,int st,int ed)
{
	StrokeModel* pStroke = &(pBN->pStroke[StrokeId]);
	PointModel* pPoint;
	pPoint = pStroke->pPoint[0];
	memcpy(pPoint->P,&pPts[st],sizeof(float)*2);
	pPoint = pStroke->pPoint[WSRS-1];
	memcpy(pPoint->P,&pPts[ed],sizeof(float)*2);
}
/*
________________________________________________________________
  
Function Name	: ForwardBN
	
Purpose			: 입력된 점 배열을 자모모형에 정합시키는것.
		
Input			: 
	pBN			: 자모모형	
	pPts		: 입력점 배열 
	pSamProp	: 펜Up-Down정보
	pSamNo		: 표본화점번호 배열
	SamNum		: 표본화점개수
	deep		: 깊이심도

Output			: 
	Mistake		: 점 배열이 획속성에 맞지 않는 오류개수 	

Return Value	: 정합확률

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
________________________________________________________________
*/
float CJamoBNCore::ForwardBN(JAMOBN *pBN,REC_POINT* pPts,int* pSamProp,int* pSamNo,int SamNum,int& Mistake,int deep)
{
	int i,t,b,k,bb,st,ed;
	int StrkNum = pBN->StrokeNum;
	if(SamNum<StrkNum+1) return MAXDIS;

	float minDis,tempDis,Thdis = 300.0f;
	float minStrokeDis,StrokeDis;

	float (*dis)[MAXSAMNUM];
	BOOL (*flag)[MAXSAMNUM];
	int	(*path)[MAXSAMNUM][MAXSTROKENUM];
	dis = m_dis;
	flag = m_flag;
	path = m_path;
	memset(flag,0,sizeof(BOOL)*StrkNum*MAXSAMNUM);
	dis[0][0] = 0;
	path[0][0][0] = pSamNo[0];
	dis[StrkNum-1][SamNum-1] = MAXDIS;
	for(t=1;t<SamNum;t++){
		st = max(t-(SamNum-StrkNum),0);
		if(t != SamNum-1) ed = min(t,StrkNum-1);
		else 
			ed=StrkNum;
		for(i=st;i<ed;i++){
			if(i==0){
				SetDataInStroke(pBN,0,pPts,pSamNo[0],pSamNo[t],deep);
				minDis = ForwardStroke(pBN,0,deep);

				if(t != SamNum-1 && minDis > pBN->ThDis) //거리가 매우 큰 가지는 제거 //////////////
					continue;
				dis[0][t] = minDis;
				path[0][t][0] = 0;
				path[0][t][1] = t;
				flag[0][t] = TRUE;
				continue;
			}
			minDis = MAXDIS;
			bb=-1;
			for (b=1;b<t;b++) {
				if(flag[i-1][b] == FALSE) continue;
				for(k=0;k<i;k++)
					SetEndDataInStroke(pBN,k,pPts,pSamNo[path[i-1][b][k]],pSamNo[path[i-1][b][k+1]]);
				SetDataInStroke(pBN,i,pPts,pSamNo[b],pSamNo[t],deep);
				StrokeDis = ForwardStroke(pBN,i,deep);

				tempDis	= StrokeDis + dis[i-1][b];
				if(minDis>tempDis) {
					bb = b;
					minDis = tempDis;
					minStrokeDis = StrokeDis;
				}
			}
			if(bb==-1)continue;
			if(t != SamNum-1) {

				if(minDis>=pBN->ThDis) //거리가 매우 큰 가지는 제거 //////////////
					continue;
			}
			dis[i][t] = minDis;
			memcpy(path[i][t],path[i-1][bb],sizeof(int)*(i+1));
			path[i][t][i+1] = t;
			flag[i][t] = TRUE;
		}
	}

	float rdis = dis[StrkNum-1][SamNum-1];
	Mistake=0;
	if(flag[StrkNum-1][SamNum-1] == TRUE){
		for(i=0;i<StrkNum;i++)
		{
			st = path[StrkNum-1][SamNum-1][i];
			ed = path[StrkNum-1][SamNum-1][i+1];
			if(pBN->pStroke[i].Prop == 0){
				for(int j=st;j<ed;j++){
					if(pSamProp[j] == UP_Flag){
						Mistake++;break;
					}
				}
			}
			if(pBN->pStroke[i].Prop == 2){
				if(pSamProp[st] == UP_Flag){
					Mistake++;
				}
			}
			if(pBN->pStroke[i].Prop == 3){
				if(pSamProp[ed] == DOWN_Flag){
					Mistake++;
				}
			}
		}
		return rdis;
	}else
		return MAXDIS;
}



