📄 patternview.cpp
字号:
delete [] yangbenzhx;
//重画视图
OnDraw(pDC);
// 恢复光标
EndWaitCursor();
}
void CPatternView::OnThreshold()
{
// TODO: Add your command handler code here
///////////////////////////////////////////////////////////////////////////////////////////////
// bshowcen = true;
CDC* pDC;
pDC=GetDC();
int i, j, k;
float distance;
float olddis , newdis;
float sumcencx[10] = {0,0,0,0,0,0,0,0,0,0};
float sumcency[10] = {0,0,0,0,0,0,0,0,0,0};
int sumnum[10] = {0,0,0,0,0,0,0,0,0,0};
CString str;
//初始化所有样本点的颜色
for(i=0;i<iShuMu;i++)
{
for(j=0;j<iDianShu;j++)
{
samplenum[i*iDianShu+j].colorvalue = RGB(255,0,0);
}
}
//开始搜索,初始化所有未归类的样本点
for(i=0;i<iShuMu;i++)
{
for(j=0;j<iDianShu;j++)
{
samplenum[i*iDianShu+j].fseek = false;
}
}
/////////////////(循环体部份)/////////////////////////////////////////////////////////////////////////
//第一步:选择第一样本点为第一中心点
samplecen[0] = samplenum[0];
for(k = 0; k < iShuMu ; k++)
{
//第二步:搜索第一样本点为中心的第一类中的样本,阈值为类内T
sumcencx[k]=0;
sumcency[k]=0;
sumnum[k]=0;
for(i = 0; i < iShuMu*iDianShu; i++)
{
if(!samplenum[i].fseek)//初始化所有未归类的样本点samplenum[i].fseek = false;
//!samplenum[i].fseek为真即samplenum[i].fseek = false也就是所有未归类的样本点
{
distance = sqrt((samplenum[i].cx - samplecen[k].cx)*(samplenum[i].cx - samplecen[k].cx)
+ (samplenum[i].cy - samplecen[k].cy)*(samplenum[i].cy - samplecen[k].cy));
if(distance < 80)
{
samplenum[i].k = k;
samplenum[i].colorvalue = RGB(255*3/(k+1)%255,255*14/(k+1)%255,255*21/(k+1)%255);
samplenum[i].fseek = true;
sumcencx[k]=samplenum[i].cx+sumcencx[k];
sumcency[k]=samplenum[i].cy+sumcency[k];
sumnum[k]++;
}
}
}
//修改中心
sumcencx[k] = sumcencx[k]/sumnum[k];
sumcency[k] = sumcency[k]/sumnum[k];
if(sumcencx[k]!=samplecen[k].cx || sumcency[k]!=samplecen[k].cy)
{
samplecen[k].cx=sumcencx[k];
samplecen[k].cy=sumcency[k];
for(i = 0;i < iShuMu*iDianShu; i++)//将已归类的点置为未归类的点重新以新的中心点归类
{
if(samplenum[i].k==k)
samplenum[i].fseek = false;
}
k--;
continue;//结束本次循环,接着开始判断决定是否继续执行下一次循环
}
//////////////////////////////////////////////////////////////////////////////////////////
samplecen[k].fseek=true;
//是否显示中心点
bshowcen = true;
OnDraw(pDC);
//显示文本
CFont MyFont;
MyFont.CreateFont(25,0,0,0,400,FALSE,FALSE,0,
ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,DEFAULT_PITCH|FF_SWISS,"楷体_GB2312");
CFont* pOldFont=pDC->SelectObject(&MyFont);
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(RGB(255,0,255));
str=" 阈值T=80";
pDC->TextOut(650,20,str);
char number[80];
sprintf(number," 第%d个聚类中心点!",k+1);
pDC->TextOut(300,20,number);
MyFont.DeleteObject();
Sleep(1000);//
//////////////////////////////////////////////////////////////////////////////////
//找出与第一类中心距离最远的未归类的样本点samplenum[i]作为下一个中心点samplecen[k+1]
olddis = 0;
for(i = 0; i < iShuMu*iDianShu; i++)//所有未归类的点
{
if(!samplenum[i].fseek)
{
newdis = sqrt((samplenum[i].cx - samplecen[k].cx)*(samplenum[i].cx - samplecen[k].cx)
+ (samplenum[i].cy - samplecen[k].cy)*(samplenum[i].cy - samplecen[k].cy));
if(newdis > olddis)
{
olddis = newdis;
if(k + 1 < iShuMu && olddis > 80)
samplecen[k+1] = samplenum[i];//将最远的点作为下一个中心点
}
}
}
}
// for(i=0;i < 10;i++)
//{
// samplecen[i].fseek = true;
// }
bshowcen = false;
}
void CPatternView::OnMaxiMin()
{
// TODO: Add your command handler code here
bshowcen = true;
CDC* pDC;
pDC=GetDC();
int i, j, k, m, precenter;
float maxdis;
float olddis[1500] , newdis;
float sumdis;
//初始化所有样本点的颜色
for(i=0;i<iShuMu;i++)
{
for(j=0;j<iDianShu;j++)
{
samplenum[i*iDianShu+j].colorvalue = RGB(255,0,0);//在::OnMoBanSet()中随机数据
//存放于samplenum[i*iDianShu+j]中
}
}
//初始化所有未归类的样本点
for(i=0;i<iShuMu;i++)
{
for(j=0;j<iDianShu;j++)
{
samplenum[i*iDianShu+j].fseek = false;
}
}
//第一步:选择第一样本点为第一中心点
samplecen[0] = samplenum[0];
samplenum[0].fseek = true;
samplenum[0].k = 0;
//第二步:确定距离第一中心点最远的点为第二中心点
olddis[0] = 0;
for(i = 0; i < iShuMu*iDianShu; i++)
{
newdis = sqrt((samplenum[i].cx - samplecen[0].cx)*(samplenum[i].cx - samplecen[0].cx)
+ (samplenum[i].cy - samplecen[0].cy)*(samplenum[i].cy - samplecen[0].cy));
if(newdis > olddis[0])
{
olddis[0] = newdis;
samplecen[1] = samplenum[i];
k=i;//与所属类的“K”不一样
}
}
samplenum[k].fseek = true;
samplenum[k].k = 1;
//第三步:计算样本到各个样本中心的平均距离,并且小中取大
for(i = 0; i < iShuMu*iDianShu; i++)
{
olddis[i] = 2000;
}
for(m = 2; m < iShuMu; m++)//由于已有第一中心点即第0类,第二中心点即第1类,故m从第2类开始寻找第三中心点
{
maxdis = 0;
for(i = 0; i < iShuMu*iDianShu; i++)
{
if(!samplenum[i].fseek)
{
for(j = 0; j < m; j++)//未归类的每一点到已确定的各个样本中心的距离newdis,并找到最小的距离放置于olddis[i]中
{
newdis = sqrt((samplenum[i].cx - samplecen[j].cx)*(samplenum[i].cx - samplecen[j].cx)
+ (samplenum[i].cy - samplecen[j].cy)*(samplenum[i].cy - samplecen[j].cy));
if(newdis < olddis[i])
{
olddis[i] = newdis; //olddis[i]存放第i个未归类的样本点到各个已确定的样本中心点的距离中的最小值
}
}//即计算表四中每一行,olddis[i]放置每一行的最小值
if(maxdis < olddis[i])//找出距离中最小值中的最大值放置于maxdis即在表四所有行中找到最大的
{
maxdis = olddis[i];
precenter = i;//记下该样本点放置于precenter作为可能的中心点
}//即计算表四中第一列的最大值
}
}
//第四步:判断其他中心(判断可能的中心点是否为中心点)
sumdis = 0;
k = 0;
for(i = 0; i < m; i++)//i为已分出的第一中心点即第0类,第二中心点即第1类...第m-1类
{
for(j = 0; j < m; j++)//每一已确定中心点与其它已确定中心点的距离分别相加并放置于sumdis中并统计个数,以便求这些距离的均值
{
if(i != j)
{
newdis = sqrt((samplecen[i].cx - samplecen[j].cx)*(samplecen[i].cx - samplecen[j].cx)
+ (samplecen[i].cy - samplecen[j].cy)*(samplecen[i].cy - samplecen[j].cy));
sumdis += newdis;
k++;
}
}
}
sumdis /= k;//sumdis=sumdis/k求这些距离的均值
if(maxdis > sumdis/3)
{
samplecen[m] = samplenum[precenter];
samplenum[precenter].fseek = true;
samplenum[precenter].k = m;
}
else
break;
}
//第五步:分配样本到各中心点
for(i = 0; i < iShuMu*iDianShu; i++)
{
//搜索非中心点的样本点到各中心点的最小距离作为聚类的标准
olddis[0] = 2000;
for(k = 0; k < iShuMu; k++)
{
if(!samplenum[i].fseek) //!samplenum[i].fseek为除中心点之外所有未归类的点,求每一未归
//类的样本点到所有中心点的距离并求其最小距离存放于olddis[0]中,并将该样本点进行归类、着色。
//注意:并没有给已归类的样本点设置标志为true,即类似为已确定的中心点设置标志:samplenum[precenter].fseek = true;
{
newdis = sqrt((samplenum[i].cx - samplecen[k].cx)*(samplenum[i].cx - samplecen[k].cx)
+ (samplenum[i].cy - samplecen[k].cy)*(samplenum[i].cy - samplecen[k].cy));
if(newdis < olddis[0])
{
olddis[0] = newdis;
samplenum[i].k = k;//k为样本点归属的类
samplenum[i].colorvalue = RGB(255*3/(k+1)%255,255*14/(k+1)%255,255*21/(k+1)%255);
}
}
}
//中心点特殊处理。注意:samplenum[i].fseek为已确定的中心点,samplecen[m] = samplenum[precenter];samplenum[precenter].fseek = true;
//而其它的随机样本点(包括已归类的样本点)都没有设置标志。
if(samplenum[i].fseek)//samplenum[i].fseek为已确定的中心点
{
m = samplenum[i].k;//samplenum[precenter].k = m;m为中心点归属的类
samplenum[i].colorvalue = RGB(255*3/(m+1)%255,255*14/(m+1)%255,255*21/(m+1)%255);
}
}
//第六步:修改中心
float sumcencx[10] = {0,0,0,0,0,0,0,0,0,0};//一共为10类
float sumcency[10] = {0,0,0,0,0,0,0,0,0,0};
int sumnum[10] = {0,0,0,0,0,0,0,0,0,0};
for(i = 0; i < iShuMu*iDianShu; i++)//找出每一类的所有样本点并求均值作为第个类新的聚类中心
{
for(k = 0; k < iShuMu; k++)
{
if(samplenum[i].k == k)//找出每一随机样本点所属的类
{
sumcencx[k] = samplenum[i].cx + sumcencx[k];
sumcency[k] = samplenum[i].cy + sumcency[k];
sumnum[k]++;//将数组sumnum[10]的第k个数组元素的值加“1”而不是指向下一个数组元素
}
}
}
for(k = 0; k < iShuMu; k++)//求均值作为第个类新的聚类中心
{
samplecen[k].cx = sumcencx[k]/sumnum[k];
samplecen[k].cy = sumcency[k]/sumnum[k];
}
//初始化样本中心点是否显示,用于中心点以“+”显示
for(i=0;i < 10;i++)
{
samplecen[i].fseek = true;
}
OnDraw(pDC);
}
void CPatternView::OnKMeans()
{
// TODO: Add your command handler code here
bshowcen = true;
CDC* pDC;
pDC=GetDC();
int i, j ,k;
SampleDot *oldprecen;
oldprecen = new SampleDot[10];
float olddis , newdis;
//初始化所有样本点的颜色
for(i=0;i < iShuMu;i++)
{
for(j=0;j < iDianShu;j++)
{
samplenum[i*iDianShu+j].colorvalue = RGB(255,0,0);
}
}
//初始化所有未归类的样本点
for(i=0;i<iShuMu;i++)
{
for(j=0;j<iDianShu;j++)
{
samplenum[i*iDianShu+j].fseek = false;
}
}
//第一步:选择样本点前K=iShuMu个为预测类中心
for(i=0;i < iShuMu;i++)
{
oldprecen[i] = samplenum[i];
}
//第二步:逐个将样本点按最小距离原则分配到旧的样本中心
int n = 0;
lab1:
n++;
for(i=0;i<iShuMu * iDianShu;i++)
{
olddis = 2000;
for(j=0;j < iShuMu;j++)
{
newdis = sqrt((samplenum[i].cx - oldprecen[j].cx) * (samplenum[i].cx - oldprecen[j].cx)
+ (samplenum[i].cy - oldprecen[j].cy) * (samplenum[i].cy - oldprecen[j].cy));
if(newdis < olddis)
{
olddis = newdis;
samplenum[i].k = j;
samplenum[i].colorvalue = RGB(255*3/(j+1)%255,255*14/(j+1)%255,255*21/(j+1)%255);
}
}
}
//第三步:修改聚类中心
float sumcencx[10] = {0,0,0,0,0,0,0,0,0,0};
float sumcency[10] = {0,0,0,0,0,0,0,0,0,0};
int sumnum[10] = {0,0,0,0,0,0,0,0,0,0};
for(i = 0; i < iShuMu*iDianShu; i++)
{
for(k = 0; k < iShuMu; k++)
{
if(samplenum[i].k == k)
{
sumcencx[k] = samplenum[i].cx + sumcencx[k];
sumcency[k] = samplenum[i].cy + sumcency[k];
sumnum[k]++;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -