⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clusterisodatadlg.cpp

📁 IDODATA变换的实现
💻 CPP
字号:
// ClusterISODATADlg.cpp : implementation file
//

#include "stdafx.h"
#include "ClusterISODATA.h"
#include "ClusterISODATADlg.h"
#include <math.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
#define MAX 10
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CClusterISODATADlg dialog

CClusterISODATADlg::CClusterISODATADlg(CWnd* pParent /*=NULL*/)
	: CDialog(CClusterISODATADlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CClusterISODATADlg)
	m_centernum = 0;
	m_equation = 0.0;
	m_I = 0;
	m_maxlength = 0.0;
	m_maxvariance = 0.0;
	m_minlength = 0.0;
	m_minnum = 0;
	m_minvariance = 0.0;
	m_prenum = 0;
	m_times = 0;
	m_T = 0.0;
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CClusterISODATADlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CClusterISODATADlg)
	DDX_Text(pDX, IDC_centernum, m_centernum);
	DDX_Text(pDX, IDC_equation, m_equation);
	DDX_Text(pDX, IDC_I, m_I);
	DDX_Text(pDX, IDC_MaxLength, m_maxlength);
	DDX_Text(pDX, IDC_MaxVariance, m_maxvariance);
	DDX_Text(pDX, IDC_MinLength, m_minlength);
	DDX_Text(pDX, IDC_minnum, m_minnum);
	DDX_Text(pDX, IDC_MinVariance, m_minvariance);
	DDX_Text(pDX, IDC_prenum, m_prenum);
	DDX_Text(pDX, IDC_times, m_times);
	DDX_Text(pDX, IDC_T, m_T);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CClusterISODATADlg, CDialog)
	//{{AFX_MSG_MAP(CClusterISODATADlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON_IN, OnButtonIn)
	ON_BN_CLICKED(IDC_BUTTON_OUT, OnButtonOut)
	ON_BN_CLICKED(IDC_BUTTON_NEW, OnButtonNew)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CClusterISODATADlg message handlers

BOOL CClusterISODATADlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CClusterISODATADlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CClusterISODATADlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CClusterISODATADlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CClusterISODATADlg::OnButtonIn() 
{
	int i,j;
	CFileDialog file(TRUE,"txt",".txt");
	
	if(file.DoModal()==IDOK)
	{
		m_NewFileName=file.GetPathName();
	}
	
	if(m_NewFileName=="") 
	{
		MessageBox("请先打开数据文本");
		return;
	}//异常处理,必须要打开数据
 
/*	这里的打开异常有问题,未打开会大量占用内存池	*/


	else
	{
      FILE *fp;
      fp=fopen(m_NewFileName,"r");
	  fscanf(fp,"%d",&N);
	  for(i=0;i<N;i++)
	  {
		fscanf(fp,"%lf",&featurex[i]);
        fscanf(fp,"%lf",&featurey[i]);
	  }//获得文本数据
	}
	//初始化样本
	m_pattern=new Pattern[N];
	
	for(i=0;i<N;i++)
	{
		m_pattern[i].index=i+1;
		m_pattern[i].feature[0]=featurex[i];
        m_pattern[i].feature[1]=featurey[i];
	}
	UpdateData(true);

	//计算样本距离作为归并系数的参考值
	m_minlength=MAX;m_maxlength=0;
	for(i=0;i<N-1;i++)
		for(j=i+1;j<N;j++)
		{
			if(m_minlength>GetDistance(m_pattern[i],m_pattern[j]))
				m_minlength=GetDistance(m_pattern[i],m_pattern[j]);
			if(m_maxlength<GetDistance(m_pattern[i],m_pattern[j]))
				m_maxlength=GetDistance(m_pattern[i],m_pattern[j]);			
		}
	//求所有样本总方差作为标准差的参考值
	double cen[2],equ[2];
	for(i=0;i<2;i++)
	{
		cen[i]=0.0;
		equ[i]=0.0;
	}
	for (i=0;i<N;i++)
	{
		cen[0]+=m_pattern[i].feature[0];
        cen[1]+=m_pattern[i].feature[1];
	}
    for(i=0;i<2;i++)
		cen[i]=cen[i]/(double)N;
	for(i=0;i<N;i++)
	{
		equ[0]+=(m_pattern[i].feature[0]-cen[0])*(m_pattern[i].feature[0]-cen[0]);
		equ[1]+=(m_pattern[i].feature[1]-cen[1])*(m_pattern[i].feature[1]-cen[1]);
	}
	for(i=0;i<2;i++)
	{
		equ[i]=sqrt(equ[i]/(double)N);
	}
	double minequ=MAX;
	double maxequ=0.0;
	for(i=0;i<2;i++)
	{
		if(m_minvariance>equ[i])
		{
			m_minvariance=equ[i];
		}
		if(m_maxvariance<equ[i])
		{
			m_maxvariance=equ[i];
		}
	}
	UpdateData(false);
}

void CClusterISODATADlg::OnButtonOut() 
{
	// TODO: Add your control notification handler code here
	if(m_NewFileName=="") 
	{
		MessageBox("请先打开数据文本");
	}//异常处理,必须要打开数据

    UpdateData(true); 
    //输入参数
	minnum=m_minnum;
	T=m_T;
	times=m_times;
	equation=m_equation;
	centernum=m_centernum;
	l=m_l;
	prenum=m_prenum;
    //初始化类别
	precenternum=prenum;
	m_center=new Center[precenternum];
	for(i=0;i<precenternum;i++)
	{
		m_center[i].index=i+1;
		m_pattern[i].catagory=m_center[i].index;
		m_center[i].feature[0]=m_pattern[i].feature[0];
        m_center[i].feature[1]=m_pattern[i].feature[1];
	}

	int counter=1;//循环次数

	while(counter<=times)
	{//将所有样本归类
		for(j=0;j<precenternum;j++)		 
		{
			m_center[j].patternnum=0; 
		}
		for(i=0;i<N;i++)
		{
		   double td=MAX;
		   int index=0;
		   for(j=0;j<precenternum;j++)
		   {
			  if(td>GetDistance(m_pattern[i],m_center[j]))
			  {
			      td=GetDistance(m_pattern[i],m_center[j]);
				  index=j;
			  }
		   }
           m_center[index].patternnum++;
		   m_pattern[i].catagory=m_center[index].index;
		}
		
		//判断每类的样本是否足够
		for(i=0;i<precenternum;i++)
		{
			if(m_center[i].patternnum<minnum)
			{
				for(j=i;j<precenternum-1;j++)
					m_center[j]=m_center[j+1];
				precenternum--;
			}
		}

		//修正各中心
		for(i=0;i<precenternum;i++)
		{
			CalCenter(&m_center[i]);
		}

        //计算所有样本到其相应聚类中心的距离的平均值
		avedistance=new double[precenternum];
		for(i=0;i<precenternum;i++)
		{
			avedistance[i]=0.0;//每一类中样本到聚类中心的距离平均值
		}

		allavedis=0.0;//全部样本的平均距离
		
		for(i=0;i<precenternum;i++)
		{
			double dis=0.0;
			int num=0;
			for(j=0;j<N;j++)
			{
				if(m_pattern[j].catagory==m_center[i].index)
				{
					++num;
					dis+=GetDistance(m_pattern[j],m_center[i]);
				}
			}
			allavedis+=dis;
			avedistance[i]=(double)(dis/(double)num);
		}

		allavedis/=N;
		
        //合并
		if((precenternum>=2*centernum)||((counter%2)==0)&&(precenternum>centernum/2)&&(precenternum<2*centernum))
		{
			//找距离最近的2个类
			double td=MAX;
			int ti,tj;
			for(i=0;i<precenternum;i++)
				for(j=i+1;j<precenternum;j++)
				{
					double tdin;
					tdin=GetDistance(m_center[i],m_center[j]);
					if(td<tdin)
					{
						td=tdin;
						ti=i;
						tj=j;
					}
				}
			   //判断是否进行合并
               if(td<T)
			   {
				 //合并
				 for(i=0;i<precenternum;i++)
				 {
					 if(m_pattern[i].catagory==m_center[tj].index)
						 m_pattern[i].catagory=m_center[ti].index;
					 if(m_pattern[i].catagory>m_center[tj].index)
						 m_pattern[i].catagory--;
				 }
				 //形成新的类别
				 CalCenter(&m_center[ti]);
				 for(i=tj;i<precenternum-1;i++)
				 {
					 m_center[i]=m_center[i+1];
					 m_center[i].index--;
				 }
				 precenternum--;
			 }
		}//合并完
		else if((precenternum<=centernum/2)||((counter%2)!=0)&&(precenternum>centernum/2)&&(precenternum<2*centernum))//分裂
		{//分裂
			double **mequation;//标准差
			int ti,tj;//记录最大标准差出现的位置,第ti+1号类的第tj+1位

			mequation=new double *[precenternum];
			for(i=0;i<precenternum;i++)
			{
				mequation[i]=new double[2];
				mequation[i][0]=0.0;
				mequation[i][1]=0.0;
			}
			//计算标准差向量
			for(i=0;i<precenternum;i++)
			{
				for(j=0;j<N;j++)
				{
					if(m_pattern[j].catagory==m_center[i].index)
					{							
							mequation[i][0]+=(m_pattern[j].feature[0]-m_center[i].feature[0])*(m_pattern[j].feature[0]-m_center[i].feature[0]);
							mequation[i][1]+=(m_pattern[j].feature[1]-m_center[i].feature[1])*(m_pattern[j].feature[1]-m_center[i].feature[1]);
					}
				}
				mequation[i][0]=sqrt(mequation[i][0]/m_center[i].patternnum);
				mequation[i][1]=sqrt(mequation[i][1]/m_center[i].patternnum);
			}

			//找最大标准差
			ti=0;
			tj=0;
			for(i=0;i<precenternum;i++)
				for(j=0;j<2;j++)
				{
					if(mequation[i][j]>mequation[ti][tj])
					{
						ti=i;tj=j;
					}
				}
        
            //判断是否要分裂
            if(mequation[ti][tj]>equation)//大于给定阈值
			{
				if((avedistance[ti]>allavedis&&m_center[ti].patternnum)||(precenternum<=centernum/2))//类平均距离大于总平均距离
				{
					precenternum++;
					Center *tempcenter;
					tempcenter=new Center[precenternum];
					for(i=0;i<precenternum-1;i++)
					{
						tempcenter[i]=m_center[i];
					    tempcenter[precenternum-1].index=precenternum;
					}
					for(j=0;j<2;j++)
					{
						tempcenter[precenternum-1].feature[j]=m_center[ti].feature[j];
					}
					tempcenter[precenternum-1].feature[tj]-=0.5*mequation[ti][tj];
					tempcenter[ti].feature[tj]+=0.5*mequation[ti][tj];	
					tempcenter[ti].patternnum--;
					m_center=tempcenter;
				}
			}
		    //修正各中心
		    for(i=0;i<precenternum;i++)
			{
			    CalCenter(&m_center[i]);
			}
		}//end 分裂
		counter++;
	}//end while
	UpdateData(false);
	CString str="聚类分析结果.txt";//结果输出
	FILE *fpt;
	fpt=fopen(str,"w+");
	for(j=0;j<N;j++)
	{
	    for(i=0;i<precenternum;i++)
		{
	        if(m_center[i].index==m_pattern[j].catagory)
			{
                fprintf(fpt,"%s%4.2f %4.2f%s%d%s%4.2f %4.2f%s\n","(",m_pattern[j].feature[0],m_pattern[j].feature[1],")属于第",m_center[i].index,"类(",m_center[i].feature[0],m_center[i].feature[1],")");
			}
		}
	}
	fclose(fpt);
	ShellExecute(hwnd,NULL,str,NULL,NULL,SW_SHOWNORMAL);
	
}
double CClusterISODATADlg::GetDistance(CClusterISODATADlg::Center mCenter1,CClusterISODATADlg::Center mCenter2)
{
	double result;
	result=(mCenter1.feature[0]-mCenter2.feature[0])*(mCenter1.feature[0]-mCenter2.feature[0])+(mCenter1.feature[1]-mCenter2.feature[1])*(mCenter1.feature[1]-mCenter2.feature[1]);
	return (double)sqrt(result);
}

double CClusterISODATADlg::GetDistance(CClusterISODATADlg::Pattern pattern,CClusterISODATADlg::Center center)
{
	double result;
	result=(pattern.feature[0]-center.feature[0])*(pattern.feature[0]-center.feature[0])+(pattern.feature[1]-center.feature[1])*(pattern.feature[1]-center.feature[1]);
	return (double)sqrt(result);
}

double CClusterISODATADlg::GetDistance(CClusterISODATADlg::Pattern pattern1,CClusterISODATADlg::Pattern pattern2)
{
	double result;
	result=(pattern1.feature[0]-pattern2.feature[0])*(pattern1.feature[0]-pattern2.feature[0])+(pattern1.feature[1]-pattern2.feature[1])*(pattern1.feature[1]-pattern2.feature[1]);
	return (double)sqrt(result);
}
void CClusterISODATADlg::CalCenter(CClusterISODATADlg::Center *pcenter)
{
	int i;
	double x=0.0,y=0.0;
	for(i=0;i<N;i++)
	{
       if(m_pattern[i].catagory==pcenter->index)
	   {
		   x+=m_pattern[i].feature[0];
		   y+=m_pattern[i].feature[1];
	   }	   
	}
	if(x==0.0&&y==0.0)
	{
		return;
	}
	pcenter->feature[0]=x/double(pcenter->patternnum);
	pcenter->feature[1]=y/double(pcenter->patternnum);
}

void CClusterISODATADlg::OnButtonNew() 
{
	// TODO: Add your control notification handler code here
	ShellExecute(NULL,"Open","C:/Windows/Notepad.exe",NULL,NULL,SW_SHOWNORMAL);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -