K-MEANS聚类遇上凸包

代码下载:http://download.csdn.net/detail/hzq20081121107/7221575

程序功能:

在对话框上随机点上一些点,

在k值处设要划分几个聚类,在T值初设置进行几次迭代(用k-means求聚类)

点击cluster按钮,程序将以不同的颜色画出k个聚类,并且用凸包圈起每个聚类(双链法求凸包)。 

程序效果图:

 

x、y为点的坐标,c为点的类别

struct cluNode
{
    double x;
    double y;
    int c;
};

clunode【】为待分类的点的集合
cluNode clunode[1000];

nodeNum为待分类的点的数量
int nodeNum;

centerNode【】为聚类中心
cluNode centerNode[100];

CPoint按y从小到大其,当y相等时按x从小到大排序
int cmp(CPoint a,CPoint b)
{
    return a.y < b.y || (a.y == b.y && a.x < b.x);
}

鼠标左键事件(取得待分类点):

View Code
 1 void C聚类Dlg::OnLButtonDown(UINT nFlags, CPoint point)
 2 {
 3     clunode[nodeNum].x=point.x;
 4     clunode[nodeNum].y=point.y;
 5     clunode[nodeNum].c=1;
 6                   nodeNum++;
 7 
 8     CDC *pDC;
 9     pDC=GetDC();
10     int r=4;
11     CBrush MyBrush;
12     MyBrush.CreateSolidBrush(RGB(255,250,0));
13                   pDC->SelectObject(&MyBrush);
14     pDC->Ellipse(point.x-r,point.y-r,point.x+r,point.y+r);
15 
16     CDialogEx::OnLButtonDown(nFlags, point);
17 }

 聚类:

View Code
void C聚类Dlg::OnBnClickedOk()
{
    UpdateData(true);
    int i,j,k;
    //设置中心点
    for(i=0;i<m_cluNum;i++)
    {
        centerNode[i]=clunode[i];
        centerNode[i].c=i;
    }
    //clusterDraw();
    //聚类
    double minDis,tempDis;
    int t=99;
    for(k=0;k<t;k++)
    {
        //重新分类
        for(i=0;i<nodeNum;i++)
        {
            clunode[i].c=0;
            minDis=(clunode[i].x-centerNode[0].x)*(clunode[i].x-centerNode[0].x)+(clunode[i].y-centerNode[0].y)*(clunode[i].y-centerNode[0].y);
            for(j=0;j<m_cluNum;j++)
            {
                tempDis=(clunode[i].x-centerNode[j].x)*(clunode[i].x-centerNode[j].x)+(clunode[i].y-centerNode[j].y)*(clunode[i].y-centerNode[j].y);
                if(tempDis<minDis)
                {
                    minDis=tempDis;
                    clunode[i].c=j;
                }
            }
        }
        //求分类中心点
        int cluLen[100]={0};
        for(i=0;i<m_cluNum;i++)    
            centerNode[i].x=centerNode[i].y=0; 
        for(i=0;i<nodeNum;i++)
        {
            centerNode[clunode[i].c].x+=clunode[i].x;
            centerNode[clunode[i].c].y+=clunode[i].y;
            cluLen[clunode[i].c]++;
        }
        for(i=0;i<m_cluNum;i++)
        {
            centerNode[i].x/=double(cluLen[i]);
            centerNode[i].y/=double(cluLen[i]);
        } 
        m_t=k;
        UpdateData(false);
        //clusterDraw();
    };
    clusterDraw();
}

根据聚类结果画凸包:

View Code
//画凸包
void C聚类Dlg::clusterDraw(void)
{
    CDC *pDC;
    pDC=GetDC();
    
    int r=4;
    int i,j,k;
    for(i=0;i<nodeNum;i++)
    {
        double ratio=double(clunode[i].c)/double(m_cluNum);
        CBrush MyBrush;
        MyBrush.CreateSolidBrush(RGB(255*ratio,255*(1-ratio),255*ratio));//255*ratio));
        pDC->SelectObject(&MyBrush);
        pDC->Ellipse(clunode[i].x-r,clunode[i].y-r,clunode[i].x+r,clunode[i].y+r);
    }

    CPoint pnt[1000];
    CPoint res[1000];
    for(j=0;j<m_cluNum;j++)
    {
        int pnum=0;
        for(i=0;i<nodeNum;i++)
        {
            if(clunode[i].c==j)
            {
              pnt[pnum].x=clunode[i].x;
              pnt[pnum].y=clunode[i].y;
              pnum++;
            }
        }
        int n=pnum;
        std::sort(pnt,pnt+n,cmp);//paixu();
        int len, k = 0, top = 1;
       
        if (n == 0) top=0; res[0] = pnt[0];
        if (n == 1) top=1; res[1] = pnt[1];
        if (n == 2) top=2; res[2] = pnt[2];
        for (i = 2; i < n; i++) 
        {
            while (top && mult(pnt[i], res[top], res[top-1]))
            top--;
            res[++top] = pnt[i];
        }
        len = top; res[++top] = pnt[n - 2];
        for (i = n - 3; i >= 0; i--) 
        {
            while (top!=len && mult(pnt[i], res[top], res[top-1])) top--;
            res[++top] = pnt[i];
        }
    
        pDC->MoveTo(res[0]);
        for(i=1;i<=top;i++)
        {
            pDC->LineTo(res[i]);
        }
    }
}


求叉积:

View Code
//叉积
bool C聚类Dlg::mult(CPoint sp, CPoint ep, CPoint op)
{
    return (sp.x - op.x) * (ep.y - op.y)>= (ep.x - op.x) * (sp.y - op.y);
}

 

 

posted @ 2013-05-03 09:04  黄QQ  阅读(758)  评论(0编辑  收藏  举报