📄 ourworkdlg.cpp
字号:
return HBRUSH(GetStockObject(NULL_BRUSH));
//
}
// TODO: Return a different brush if the default is not desired
return hbr;
}
void COurWorkDlg::OnButtonIsodata()
{
m_nType=2;
m_bIsFinish=FALSE;
m_bIsIsoData=TRUE;
m_nCountOfDieDai=0;
CString strTemp=_T("");
int nCount=0;//迭代次数
CDlgSetIsoData dlg;
if(IDOK!=dlg.DoModal())
{
return;
}
ClearArray();///清空所有数组
////////////产生随机颜色//////////////////
/*MakeRndColor(m_nColor);
while(JudgeColorRepeate(m_nColor))
{
MakeRndColor(m_nColor);
}*/
///////////////////////////////////////
/////如果已经设定好了参数//////////////////
m_fBottom =(float) atof(dlg.m_strBottom);
m_nCenterNum =(int) atoi(dlg.m_strCenterNum);
m_nLeastNum = (int) atoi(dlg.m_strLeastNum);
m_nMostCountNum = (int) atoi(dlg.m_strMostCountNum);
m_nMostPair = (int) atoi(dlg.m_strMostPair);
m_nTypeNum = (int) atoi(dlg.m_strTypeNum);
m_fUpper = (float) atof(dlg.m_strUpper);
m_strBottom=dlg.m_strBottom;
m_strCenterNum=dlg.m_strCenterNum;
m_strLeastNum=dlg.m_strLeastNum;
m_strMostCountNum=dlg.m_strMostCountNum;
m_strMostPair=dlg.m_strMostPair;
m_strTypeNum=dlg.m_strTypeNum;
m_strUpper=dlg.m_strUpper;
SetISODataInfo();
//////选择初始聚类的中心//////////
//int nCount=int(atoi(m_strCenterNum));
for(int n=0;n<m_nCenterNum;n++)
{
strTemp.Format(_T("%0.3f"),m_fX[n]);
m_strArrayCenterX.Add(strTemp);
strTemp.Format(_T("%0.3f"),m_fY[n]);
m_strArrayCenterY.Add(strTemp);
}
///////////////////////////////////////
///开始迭代////////////////////////////////////////
while(m_nCountOfDieDai<=m_nMostCountNum)
//while(1)
{
m_nCountOfDieDai++;
m_bIsSplitter=FALSE;
///清空数组////////////
m_nArrayEachNum.RemoveAll();
/*for(int n=0;n<m_ObjArray.GetSize();n++)
delete (CTypeAndData*)m_ObjArray.GetAt(n);
m_ObjArray.RemoveAll();*/
for( n=0;n<m_ObjArrayISOData.GetSize();n++)
delete (CTypeAndData*)m_ObjArrayISOData.GetAt(n);
m_ObjArrayISOData.RemoveAll();
for( n=0;n<m_ObArrayEachInfo.GetSize();n++)
delete (CEachGroupInfo*)m_ObArrayEachInfo.GetAt(n);
m_ObArrayEachInfo.RemoveAll();
/////////////////////////
/////按最小距离原则分类并记录下每个模式属于哪一类和该模式特征的/////////////////////
CountDistance(&m_strArrayCenterX,&m_strArrayCenterY,m_nCenterNum);
int nIndex=0;//用来记录是哪个组的个数小于了预设值
while(IsCancelCenter(nIndex))
{///当检测到有一组小于预设值的时候,将该组中心去掉,在重新分类,直到所有的分组的个数都大于预设值
m_nCenterNum=m_nCenterNum-1;
/*for(int n=0;n<m_ObjArray.GetSize();n++)
delete (CTypeAndData*)m_ObjArray.GetAt(n);
m_ObjArray.RemoveAll();*/
for( n=0;n<m_ObArrayEachInfo.GetSize();n++)
delete (CEachGroupInfo*)m_ObArrayEachInfo.GetAt(n);
m_ObArrayEachInfo.RemoveAll();
if(m_nCenterNum==0)
return;
if(m_strArrayCenterX.GetSize()>=1)
{
m_strArrayCenterX.RemoveAt(nIndex);
}
else
return;
if(m_strArrayCenterY.GetSize()>=1)
{
m_strArrayCenterY.RemoveAt(nIndex);
}
else
return;
CountDistance(&m_strArrayCenterX,&m_strArrayCenterY,m_nCenterNum);
}
/////////////////////////////////////////////////////////////
/////计算各类的中心/////////////////////////
if(ISODataCountNewCenter(m_nCenterNum))
//ISODataCountNewCenter(m_nCenterNum,&m_strArrayCenterX,&m_strArrayCenterY);
{///如果已经迭带成功
strTemp.Format(_T("ISODATA算法,迭代次数为%d,共分成了%d类"),m_nCountOfDieDai,m_nCenterNum);
SetDlgItemText(IDC_STATIC_ISODATAINFO,strTemp);
m_bIsFinish=TRUE;
break;
}
////////////////////////////////////////////
/////计算各类中模式到类心的平均距离和各个模式到其类心的总体平均距离///////////
for( n=0;n<m_ObArrayEachInfo.GetSize();n++)
delete (CEachGroupInfo*)m_ObArrayEachInfo.GetAt(n);
m_ObArrayEachInfo.RemoveAll();
int nType=1;///记录最大的分量是属于第几类
ISODataCountAverDistance(nType);
/////////////////////////////////////////////
if(m_nCountOfDieDai==m_nMostCountNum)
{///如果达到迭代次数,跳转到第9步
ISODataCountDistanceBetweenClass();
if(!m_bIsFinish)
{///如果次数已经达到,但还没有收敛,那么提示//
MessageBox(_T("已经达到迭代次数,但尚未收敛!"),_T(";友情提示"));
strTemp.Format(_T("ISODATA算法,迭代次数为%d,但尚未收敛!"),m_nCountOfDieDai,m_nCenterNum);
SetDlgItemText(IDC_STATIC_ISODATAINFO,strTemp);
m_fBottom=0.000f;
}
continue;
}
if((m_nCenterNum<=m_nTypeNum/2)&&(m_nCountOfDieDai< m_nMostCountNum))
{//转到第六步
ISODataSplitter(nType);
if(m_bIsSplitter)
continue;
ISODataCountDistanceBetweenClass();
}
else if((m_nCenterNum>2*m_nTypeNum)&&(m_nCountOfDieDai< m_nMostCountNum))
{//转至第九步,计算类间距离
ISODataCountDistanceBetweenClass();
}
else if(m_nCenterNum>m_nTypeNum/2&&m_nCenterNum<2*m_nTypeNum&&m_nCountOfDieDai< m_nMostCountNum)
{
if(m_nCountOfDieDai>0&&m_nCountOfDieDai%2==0)
{//转第九步
ISODataCountDistanceBetweenClass();
}
else if(m_nCountOfDieDai>0&&m_nCountOfDieDai%2==1)
{//转第六步
ISODataSplitter(nType);
if(m_bIsSplitter)
continue;
ISODataCountDistanceBetweenClass();
}
}
if(m_nCountOfDieDai==m_nMostCountNum)
{
MessageBox(_T("已经迭代完成,但尚未收敛!"),_T("友情提示"));
}
}
m_bIsType=TRUE;
Invalidate(TRUE);////窗口重绘并擦除原来的背景
DrawOrder();
DrawPic();
}
void COurWorkDlg::ClearArray()
{
m_nArrayEachNum.RemoveAll();
/*for(int n=0;n<m_ObjArray.GetSize();n++)
delete (CTypeAndData*)m_ObjArray.GetAt(n);
m_ObjArray.RemoveAll();*/
m_strArrayCenterX.RemoveAll();
m_strArrayCenterY.RemoveAll();
//m_strArrayEachAver.RemoveAll();
for( int n=0;n<m_ObArrayEachInfo.GetSize();n++)
delete (CEachGroupInfo*)m_ObArrayEachInfo.GetAt(n);
m_ObArrayEachInfo.RemoveAll();
/*int nCount=m_ObjArrayISOData.GetSize();
if(nCount>0)
{
for(int k=0;k<nCount;k++)
delete (CTypeAndData*)m_ObjArrayISOData.GetAt(k);
m_ObjArrayISOData.RemoveAll();
}*/
m_bFlag=FALSE;
}
BOOL COurWorkDlg::IsCancelCenter(int &nIndex)
{
int k=1,nSumNumer=0;
int nCount=m_ObjArrayISOData.GetSize();
while(k<=m_nCenterNum)
{
nSumNumer=0;
for(int n=0;n<nCount;n++)
{
CTypeAndData *pmyTpyeAndData=(CTypeAndData *)m_ObjArrayISOData.GetAt(n);
if(pmyTpyeAndData->nIndex==k)
{
nSumNumer++;
}
}
if(nSumNumer<m_nLeastNum)
{///如果比预期设定的数目少,则返回并重新分类
nIndex=k-1;
return TRUE;
}
k++;
}
return FALSE;
}
BOOL COurWorkDlg::ISODataCountNewCenter(int nCtypeCount)
{
////重新计算中心点////////////
//pstrArrayX->RemoveAll();
//pstrArrayY->RemoveAll();
CStringArray strArrayX;
CStringArray strArrayY;
for(int k=0;k<nCtypeCount;k++)
{
float fSumX=0.000f;
float fSumY=0.000f;
//int nCountSum=m_nArrayEachNum.GetAt(k);
int nCountSum=0;
for(int i=0;i<NCOUNT;i++)
{
CTypeAndData *pmyTpyeAndData=(CTypeAndData *)m_ObjArrayISOData.GetAt(i);
if(pmyTpyeAndData->nIndex==k+1)
{
fSumX+=(pmyTpyeAndData->fX);
fSumY+=(pmyTpyeAndData->fY);
nCountSum++;
}
}
CString strTemp=_T("");
float fTemp=0.000f;
if(nCountSum==0)
{
break;
}
fTemp=(fSumX/nCountSum);
strTemp.Format(_T("%0.3f"),fTemp);
strArrayX.Add(strTemp);
strTemp.Format("X中心%0.3f",fTemp);
//MessageBox(strTemp);
fTemp=(fSumY/nCountSum);
strTemp.Format(_T("%0.3f"),fTemp);
strArrayY.Add(strTemp);
strTemp.Format(_T("Y中心%0.3f"),fTemp);
//MessageBox(strTemp);
strTemp.Format("%d每类总数%d",k+1,nCountSum);
//MessageBox(strTemp);
}
//CountDistance(&strArrayX,&strArrayY);
/////比较现在的中心点和原来的是否相同////////////////////
for(int i=0;i<nCtypeCount;i++)
{
if(m_strArrayCenterX.GetAt(i)!=strArrayX.GetAt(i)||m_strArrayCenterY.GetAt(i)!=strArrayY.GetAt(i))
{////如果任意有一个不等,则重新计算,并保留此次的中心
m_strArrayCenterX.RemoveAll();
m_strArrayCenterY.RemoveAll();
for(int j=0;j<nCtypeCount;j++)
{
m_strArrayCenterX.Add(strArrayX.GetAt(j));
m_strArrayCenterY.Add(strArrayY.GetAt(j));
}
return FALSE;
}
}
return TRUE;
///////////////////////////////////////////////////////////
//////////////////////////////////
}
void COurWorkDlg::ISODataCountAverDistance(int &nType)
{
///第5步
int nCount=m_ObjArray.GetSize();
CString strTemp=_T("");
CStringArray strArrayX,strArrayY;
int nCountSum=0;
float fAllSum=0.000f;
if(m_nCenterNum<=0)
return;
for(int n=0;n<m_nCenterNum;n++)
{
nCountSum=0;
float fCenterX=(float)atof(m_strArrayCenterX.GetAt(n));//第n个中心的X
float fCenterY=(float)atof(m_strArrayCenterY.GetAt(n));//第n个中心的Y
float fSum=0.000f,fSiLiang=0.000f;
for(int i=0;i<nCount;i++)
{
CTypeAndData *pmyTpyeAndData=(CTypeAndData *)m_ObjArray.GetAt(i);
if(pmyTpyeAndData->nIndex==n+1)
{
float fX=pmyTpyeAndData->fX;
float fY=pmyTpyeAndData->fY;
fSum+=(float)sqrt((fX-fCenterX)*(fX-fCenterX)+(fY-fCenterY)*(fY-fCenterY));
fSiLiang+=(float)((fX-fCenterX)*(fX-fCenterX)+(fY-fCenterY)*(fY-fCenterY));
fAllSum+=fSum;
nCountSum++;
}
}
/////第6步////////////////////////////////////////////
float fAver=fSum/nCountSum;
float fAverSiLiang=(float)sqrt(fSiLiang/nCountSum);//标准差矢量
CEachGroupInfo *pEachGroupInfo=new CEachGroupInfo();
pEachGroupInfo->fCenterX=fCenterX;
pEachGroupInfo->fCenterY=fCenterY;
pEachGroupInfo->fEachAver=fAver;
pEachGroupInfo->nCount=nCountSum;
pEachGroupInfo->fSiLiangAver=fAverSiLiang;
//pEachGroupInfo->nIndex=n;///
m_ObArrayEachInfo.Add(pEachGroupInfo);
}
//计算总体平均距离/////////////////////
m_fAllAver=fAllSum/m_nCenterNum;
/////////////////////////////////////////
///第7步查找最大的标准差矢量分量////////////////
//int nIndex=1;///记录最大的分量是属于第几类
nCount=m_ObArrayEachInfo.GetSize();
if(nCount<=0)
return;
CEachGroupInfo *pEachGroupInfo=(CEachGroupInfo*)m_ObArrayEachInfo.GetAt(0);
m_fMaxSiLiang=pEachGroupInfo->fSiLiangAver;
for(n=1;n<nCount;n++)
{
pEachGroupInfo=(CEachGroupInfo*)m_ObArrayEachInfo.GetAt(n);
if(m_fMaxSiLiang<pEachGroupInfo->fSiLiangAver)
{
m_fMaxSiLiang=pEachGroupInfo->fSiLiangAver;
nType=n+1;
}
}
////////////////////////////////////////////
}
void COurWorkDlg::ISODataCountDistanceBetweenClass()
{//第九步,计算类间距离
CObArray ObArray;
int nCount=m_ObArrayEachInfo.GetSize();
for(int n=0;n<nCount-1;n++)
{
CEachGroupInfo *pEachGroupInfo1=(CEachGroupInfo*)m_ObArrayEachInfo.GetAt(n);
for(int i=n+1;i<nCount;i++)
{
CEachGroupInfo *pEachGroupInfo2=(CEachGroupInfo*)m_ObArrayEachInfo.GetAt(i);
///计算距离/////////////////////////////
float fTemp1X=pEachGroupInfo1->fCenterX;
float fTemp1Y=pEachGroupInfo1->fCenterY;
float fTemp2X=pEachGroupInfo2->fCenterX;
float fTemp2Y=pEachGroupInfo2->fCenterY;
float fDistance=(float)sqrt((fTemp1X-fTemp2X)*(fTemp1X-fTemp2X)+(fTemp1Y-fTemp2Y)*(fTemp1Y-fTemp2Y));
if(fDistance<m_fBottom)
{//如果小于类间最小距离,则应该合并
CHeBingInfo *pHeBingInfo=new CHeBingInfo();
pHeBingInfo->nIndexOfHeBing1=n;
pHeBingInfo->nIndexOfHeBing2=i;
pHeBingInfo->fDistanceBetweenClass=fDistance;
ObArray.Add(pHeBingInfo);
}
////////////////////////////////////////
}
}
////转到第10步///////////
ISODateMergeClass(&ObArray);
//////////////////////////////
nCount=ObArray.GetSize();
for(n=0;n<nCount;n++)
delete (CHeBingInfo*)ObArray.GetAt(n);
ObArray.RemoveAll();
}
void COurWorkDlg::ISODateMergeClass(CObArray *pObArray)
{///第10步,合并
CString strTemp=_T("");
CHeBingInfo *pTemp=new CHeBingInfo();
int nCount=pObArray->GetSize();
int nCountOfMerg=0;
if(nCount<m_nMostPair)
return;
///冒泡排序/////////////////////////////
for(int n=1;n<nCount;n++)
{
for(int i=n;i>n;i--)
{
CHeBingInfo *pHeBing1=(CHeBingInfo*)pObArray->GetAt(i-1);
CHeBingInfo *pHeBing2=(CHeBingInfo*)pObArray->GetAt(i);
if(pHeBing1->fDistanceBetweenClass>pHeBing2->fDistanceBetweenClass)
{
pTemp=pHeBing1;
pHeBing1=pHeBing2;
pHeBing2=pTemp;
pObArray->SetAt(i-1,pHeBing2);
pObArray->SetAt(i,pHeBing1);
}
}
}
///////////////////////////////////////////
int nTemp1,nTemp2;
//////开始合并/////////////////////////////
if(nCount<m_nMostPair)
m_nMostPair=nCount;
for(n=0;n<m_nMostPair;n++)
{
CHeBingInfo *pHeBing=(CHeBingInfo*)pObArray->GetAt(n);
int nIndex1=pHeBing->nIndexOfHeBing1;
int nIndex2=pHeBing->nIndexOfHeBing2;
if(nTemp1==nIndex1||nTemp1==nIndex2||nTemp2==nIndex1||nTemp2==nIndex2)
{///如果某一类已经合并过了,那么就不在合并
continue;
}
CEachGroupInfo *pEachGroupInfo1=(CEachGroupInfo*)m_ObArrayEachInfo.GetAt(nIndex1);
CEachGroupInfo *pEachGroupInfo2=(CEachGroupInfo*)m_ObArrayEachInfo.GetAt(nIndex2);
int nCount1=pEachGroupInfo1->nCount;
int nCount2=pEachGroupInfo1->nCount;
////如果新的nIndex1或nIndex2在原来的nIndex2的后面,那么要将其值减一
if(nIndex1>=nTemp2&&nIndex1!=0)
nIndex1=nIndex1-nCountOfMerg;
if(nIndex2>=nTemp2&&nIndex2!=0)
nIndex2=nIndex2-nCountOfMerg;
/////////////////////////////////////////////////////////////
float fCenterXPre1=(float )atof(m_strArrayCenterX.GetAt(nIndex1));
int k=m_strArrayCenterX.GetSize();
float fCenterYPre1=(float)atof(m_strArrayCenterY.GetAt(nIndex1));
float fCenterXPre2=(float)atof(m_strArrayCenterX.GetAt(nIndex2));
float fCenterYPre2=(float)atof(m_strArrayCenterY.GetAt(nIndex2));
////计算新的中心//////////////
float fCenterX=(nCount1*fCenterXPre1+nCount2*fCenterXPre2)/(nCount1+nCount2);
float fCenterY=(nCount1*fCenterYPre1+nCount2*fCenterYPre2)/(nCount1+nCount2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -