퍼지 (Fuzzy) 프로그래밍 - 2
시드값 두개를 넣어서, 퍼지로직을 이용하여,
결과값을 뽑아내는 클래스
결과값은 미리 값범위에 각각 매칭시켜 두어야 한다
//------------------------------------------------------------------------헤더
enum enFuzzyCalc
{
enFuzzyCalc_Strict,
enFuzzyCalc_Low,
enFuzzyCalc_Balance,
};
class Fuzzy5x3
{
public:
Fuzzy5x3()
{
ResetCalc();
SetColumnRow();
SetColumnRow_Point();
}
~Fuzzy5x3()
{
}
void ResetCalc()
{
memset( m_fWeight, 0, sizeof(float) * 5 * 3 );
memset( m_iSavePoint, 0, sizeof(int) * 10 );
m_iSaveCount = 0;
}
void SetColumnRow( void );
void SetColumnRow_Point( void );
int FuzzyCalc( const float _fColumnSeed, const float _fRowSeed,
const enFuzzyCalc _enF = enFuzzyCalc_Strict );
protected:
int FuzzyCalc_Strict();
int FuzzyCalc_Low();
int FuzzyCalc_Balance();
protected:
float m_fColumn[5][3]; //5x3
float m_fRow[3][3]; //3x3
int m_fCRPoint[5][3]; //5x3
float m_fWeight[5][3]; //5x3
int m_iSaveCount;
int m_iSavePoint[10];
};
//------------------------------------------------------------------------본문
/*
퍼지이론에서 사용되는 값은
딱 떨어지는 값이 아니라,
범위를 가지고, 다른 값과도 어느정도의 교집합 영역을 가지는 숫자영역으로 설정된다
예)
column[0] 의 값범위는 0 ~ 2
column[1] 의 값범위는 1 ~ 3
column[0] 과 column[1] 사이의 관계만을 볼때,
1~2 사이의 값은 column[0] 과 column[1] 에서 공통으로 가지고 있는(교집합) 숫자영역이 되겠다
*/
void
Fuzzy5x3::SetColumnRow( void )
{
//[x][1]번째 요소는 값범위안에서의 중심값
//[x][1]번째 요소는 반드시 필요한 값은 아니나, 나중에 퍼지계산시
//편하게 사용하기 위해서 추가
m_fColumn[0][0] = 0.f; m_fColumn[0][1] = 1.f; m_fColumn[0][2] = 2.f;
m_fColumn[1][0] = 1.f; m_fColumn[1][1] = 2.f; m_fColumn[1][2] = 3.f;
m_fColumn[2][0] = 2.f; m_fColumn[2][1] = 3.f; m_fColumn[2][2] = 4.f;
m_fColumn[3][0] = 3.f; m_fColumn[3][1] = 4.f; m_fColumn[3][2] = 5.f;
m_fColumn[4][0] = 4.f; m_fColumn[4][1] = 5.f; m_fColumn[4][2] = 6.f;
//
m_fRow[0][0] = 0.f; m_fRow[0][1] = 1.f; m_fRow[0][2] = 2.f;
m_fRow[1][0] = 1.f; m_fRow[1][1] = 2.f; m_fRow[1][2] = 3.f;
m_fRow[2][0] = 2.f; m_fRow[2][1] = 3.f; m_fRow[2][2] = 4.f;
}
/*
일반적인 퍼지값 분포도
(퍼지값의 범위를 1 ~ 5 라고 할때)
작음 보통 많음
매우작음 1 1 2
작음 1 2 3
보통 2 3 4
많음 3 4 5
매우많음 4 5 5
위분포도에서
컬럼부분은 캐릭터의 HP
로우부분은 캐릭터의 파워
퍼지값은 캐릭터의 특수능력값
으로 생각해볼때,
HP가 작고, 파워가 작으면 특수능력값이 작고
HP가 크고, 파워가 많으면 특수능력값이 크다라는 방식으로 구성되어졌음을 알수있다
*/
void
Fuzzy5x3::SetColumnRow_Point( void )
{
m_fCRPoint[0][0] = m_fCRPoint[0][1] = m_fCRPoint[1][0] = 1;
m_fCRPoint[2][0] = m_fCRPoint[1][1] = m_fCRPoint[0][2] = 2;
m_fCRPoint[3][0] = m_fCRPoint[2][1] = m_fCRPoint[1][2] = 3;
m_fCRPoint[4][0] = m_fCRPoint[3][1] = m_fCRPoint[2][2] = 4;
m_fCRPoint[4][1] = m_fCRPoint[3][2] = m_fCRPoint[4][2] = 5;
}
//--------------------------------------------------------------
//CREA: 2016. 9. 9. jsw
//DESC: seed 는 두개, seed 값범위는 0 ~ 1
//--------------------------------------------------------------
int
Fuzzy5x3::FuzzyCalc( float _fColumnSeed, float _fRowSeed , const enFuzzyCalc _enF )
{
float fCx = _fColumnSeed * 6.f;
float fRx = _fRowSeed * 4.f;
float fWeight_C = 0.f;
float fWeight_R = 0.f;
float fWeight = 0.f;
float fGap = 0.001f;
ResetCalc();
for( int i=0; i<5; i++ )
{
if( m_fColumn[i][0] <= fCx && fCx <= m_fColumn[i][2] )
{
for( int k=0; k<3; k++ )
{
if( m_fRow[k][0] <= fRx && fRx <= m_fRow[k][2] )
{
//컬럼씨드와 로우씨드가 공통으로 속하는 영역을 알아내서,
//컬럼과 로우에 대한 각각의 중심값에 대한, 가중치 구하기
//중심값에 가까울수록 가중치가 높다
//
if( fCx <= m_fColumn[i][1] )
{
fWeight_C = fCx - m_fColumn[i][0] + fGap;
}
else
{
fWeight_C = m_fColumn[i][2] - fCx + fGap;
}
//
if( fRx <= m_fRow[k][1] )
{
fWeight_R = fRx - m_fRow[k][0] + fGap;
}
else
{
fWeight_R = m_fRow[k][2] - fRx + fGap;
}
//
m_fWeight[i][k] = (fWeight_C + fWeight_R) * 0.5f;
//일단 속해진 영역의 포인트를 바로 구해서, 저장해둔다
//필요하면, 사용
check( m_iSaveCount < 10 )
m_iSavePoint[m_iSaveCount] = m_fCRPoint[i][k];
m_iSaveCount += 1;
}
}
}
}
switch( _enF )
{
case enFuzzyCalc_Strict: //가장 정확한 값
return FuzzyCalc_Strict();
case enFuzzyCalc_Low: //가장 낮은 가중치의 값
return FuzzyCalc_Low();
case enFuzzyCalc_Balance: //정확한값과 낮은값의 중간 값
return FuzzyCalc_Balance();
default:
{
//Sys_Error( "FuzzyCalc> error _enF(%d)!", _enF );
}
return 0;
}
}
//--------------------------------------------------------------
//CREA: 2016. 9. 9. jsw
//DESC: 가장 높은 가중치를 찾는다 - 가장 정확한 값
//--------------------------------------------------------------
int
Fuzzy5x3::FuzzyCalc_Strict()
{
int iIdxC = 0, iIdxR = 0;
float fMaxW = -1.f;
//가장높은 가중치를 찾아낸다
for( int i=0; i<5; i++ )
{
for( int k=0; k<3; k++ )
{
if( fMaxW < m_fWeight[i][k] )
{
fMaxW = m_fWeight[i][k];
iIdxC = i, iIdxR = k;
}
}
}
//찾아낸 가중치값에 해당하는 m_fCRPoint 포인트를 반환
//check( 0 <= iIdxC && iIdxC < 5 && 0 <= iIdxR && iIdxR < 3 )
int iPoint = m_fCRPoint[iIdxC][iIdxR];
return iPoint;
}
//--------------------------------------------------------------
//CREA: 2016. 9. 9. jsw
//DESC: 가장 낮은 가중치를 찾는다 - 가장 낮은 값
//--------------------------------------------------------------
int
Fuzzy5x3::FuzzyCalc_Low()
{
int iIdxC = 0, iIdxR = 0;
float fLowW = 999999.f;
//가장낮은 가중치를 찾아낸다
for( int i=0; i<5; i++ )
{
for( int k=0; k<3; k++ )
{
if( m_fWeight[i][k] > 0.f
&& fLowW > m_fWeight[i][k] )
{
fLowW = m_fWeight[i][k];
iIdxC = i, iIdxR = k;
}
}
}
//check( 0 <= iIdxC && iIdxC < 5 && 0 <= iIdxR && iIdxR < 3 )
int iPoint = m_fCRPoint[iIdxC][iIdxR];
return iPoint;
}
//--------------------------------------------------------------
//CREA: 2016. 9. 9. jsw
//DESC: 높은값과 낮은값의 평균치를 구한것
//--------------------------------------------------------------
int
Fuzzy5x3::FuzzyCalc_Balance()
{
int i1 = FuzzyCalc_Strict();
int i2 = FuzzyCalc_Low();
return ( i1 + i2 ) / 2;
}
//------------------------------------------------------------------------테스트 코드
Fuzzy5x3 fuzzy;
int ip = 0;
ip = fuzzy.FuzzyCalc( 0.5, 0.5, enFuzzyCalc_Strict );
ip = fuzzy.FuzzyCalc( 0.5, 0.5, enFuzzyCalc_Low );
ip = fuzzy.FuzzyCalc( 0.5, 0.5, enFuzzyCalc_Balance );
...
ip = fuzzy.FuzzyCalc( 0.6, 0.7, enFuzzyCalc_Strict );
ip = fuzzy.FuzzyCalc( 0.6, 0.7, enFuzzyCalc_Low );
ip = fuzzy.FuzzyCalc( 0.6, 0.7, enFuzzyCalc_Balance );
...
'프로그래밍' 카테고리의 다른 글
volume fog - 구현 정리중 (0) | 2016.10.20 |
---|---|
환경매핑 - 실시간 큐브맵 만들기, 풀씬 복사 (0) | 2016.10.07 |
퍼지 (Fuzzy) 프로그래밍 - 1 (0) | 2016.09.09 |
오브젝트 바닥 충돌 처리 (3) | 2016.04.18 |
흑백 쉐이더, 그레이 쉐이더 (0) | 2016.03.30 |