Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
21
Добавлен:
01.05.2014
Размер:
15.32 Кб
Скачать
// ChildView.cpp : implementation of the CChildView class
//

#include "stdafx.h"
#include "Jarvis.h"
#include "MainFrm.h"
#include "ChildView.h"
#include <math.h>

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

#define ID_PULSE 1
static	double	rndMax=(double)RAND_MAX;
static	double	deltaLen = 10.;
/////////////////////////////////////////////////////////////////////////////
// CChildView
//double 	Pi=3.141592654;
const	PointRad = 3;

CChildView::CChildView()
{
	MinPoint=-1;
	MaxPoint=-1;
	Animation=false;
	
	time_t t;
	t = time(&t);
	srand(t);
	Bluebr.CreateSolidBrush(0x00FF0000);
	Greenbr.CreateSolidBrush(0x0000FF00);
	Redbr.CreateSolidBrush(0x000000FF);
	Pi = acos(-1.);
	fileName.Empty();
	bitName.Empty();
	x = y = dx = dy = 1.;
//	bits = NULL;
}

CChildView::~CChildView()
{
}


BEGIN_MESSAGE_MAP(CChildView,CWnd )
	//{{AFX_MSG_MAP(CChildView)
	ON_WM_PAINT()
	ON_WM_LBUTTONDOWN()
	ON_WM_RBUTTONDOWN()
	ON_WM_SIZE()
	ON_WM_TIMER()
	ON_COMMAND(ID_EDIT_CLEAR_ALL, OnEditClearAll)
	ON_UPDATE_COMMAND_UI(ID_ANIMATE, OnUpdateAnimate)
	ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
	ON_COMMAND(ID_FILE_SAVE, OnFileSave)
	ON_COMMAND(ID_FILE_SAVE_AS, OnFileSaveAs)
	ON_COMMAND(ID_FILE_SAVE_COPY_AS, OnFileSaveCopyAs)
	ON_COMMAND(ID_REFRESH, OnRefresh)
	ON_UPDATE_COMMAND_UI(ID_REFRESH, OnUpdateRefresh)
	ON_COMMAND(ID_NEWPOINTS,Generate)
	ON_COMMAND(ID_ANIMATE,Animate)
	ON_COMMAND(ID_CONVEX_HULL,Create_Convex_hull)
	ON_UPDATE_COMMAND_UI(ID_EDIT_CLEAR_ALL, OnUpdateAnimate)
	ON_UPDATE_COMMAND_UI(ID_CONVEX_HULL, OnUpdateAnimate)
	ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateAnimate)
	ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_AS, OnUpdateAnimate)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CChildView message handlers

BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs) 
{
	cs.cy=500;
	if (!CWnd::PreCreateWindow(cs))
		return FALSE;
	cs.cy=500;
	cs.dwExStyle |= WS_EX_CLIENTEDGE;
	cs.style &= ~WS_BORDER;
	cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS, 
		::LoadCursor(NULL, IDC_ARROW), HBRUSH(COLOR_WINDOW+1), ::LoadIcon(NULL,MAKEINTRESOURCE(IDR_MAINFRAME)));

	return TRUE;
}

void CChildView::OnPaint() 
{
	int i,dx1,dy1,dx2,dy2;
	CString	str;
	CPaintDC dc(this); // device context for painting

	LOGFONT LogFont;
	CFont   Font;
	CFont*  OldFont;
	LogFont.lfHeight=12;
	LogFont.lfWidth =0;
	LogFont.lfEscapement =0;
	LogFont.lfOrientation =0;
	LogFont.lfWeight =FW_NORMAL;
	LogFont.lfItalic =0;
	LogFont.lfUnderline =0;
	LogFont.lfStrikeOut =0;
	LogFont.lfCharSet =ANSI_CHARSET;
	LogFont.lfOutPrecision =OUT_DEFAULT_PRECIS;
	LogFont.lfClipPrecision =CLIP_DEFAULT_PRECIS;
	LogFont.lfQuality =PROOF_QUALITY;
	LogFont.lfPitchAndFamily =VARIABLE_PITCH|FF_ROMAN;
 	strcpy(LogFont.lfFaceName,"Times New Roman");

	Font.CreateFontIndirect (&LogFont);
	OldFont=dc.SelectObject(&Font); 

    CString strX;
	CString strY;
	CString strR;
	CString strCount;

	strX.Format("%i",(int)x);
	strY.Format("%i",(int)y);
	dc.TextOut(x*dx-20,0,strX); 
	dc.TextOut(0,y*dy-20,strY);
	
	if(bRounded)	{
		dx1 = x/2;
		dy1 = y/2;
		dx2 = (dx1+dRho)*dx;
		dy2 = (dy1+dRho)*dy;
		dx1 = (dx1-dRho)*dx;
		dy1 = (dy1-dRho)*dy;
		dc.Ellipse(dx1,dy1,dx2,dy2);
   	    
		strR.Format("Radius = %i",(int)dRho);
	    dc.TextOut((x/2+dRho)*dx+5,y/2*dy,strR); 
	}
	for(i=0;i<Points.size();i++) {
		// set point color
		if(i==MinPoint)
			dc.SelectObject(&Bluebr);
		else	if(i==MaxPoint)
			dc.SelectObject(&Redbr);
		else
			dc.SelectObject(&Greenbr);
		// show point
		dc.Ellipse(Points[i].x*dx-PointRad,Points[i].y*dy-PointRad,Points[i].x*dx+PointRad,Points[i].y*dy+PointRad);
	}
	if(Animation)
	{// step by step
		// multiplication
		CPen p2(PS_SOLID,1, (COLORREF) 0x00FFCCAA);
		dc.SelectObject(&p2);
		if(TimerValue>=0)	{
			for(i=0;i<Points.size();i++) {
				if(Convex_hull[TimerValue].p1.x==Points[i].x&&Convex_hull[TimerValue].p1.y==Points[i].y)
					continue;
				drawLineEx(dc,Convex_hull[TimerValue].p1,Points[i]);
			}
			// shape
			CPen p(PS_SOLID,1, (COLORREF) 0x00FF3333);
			dc.SelectObject(&p);
			for(i=0;i<TimerValue;i++) {
				dc.MoveTo(Convex_hull[i].p1.x*dx,Convex_hull[i].p1.y*dy);
				dc.LineTo(Convex_hull[i].p2.x*dx,Convex_hull[i].p2.y*dy);
			}
		}
	}
	else	
	{// shape at once
		CPen p(PS_SOLID,1, (COLORREF) 0x00FF3333);
			dc.SelectObject(&p);
		for(i=0;i<Convex_hull.size();i++) {
			dc.MoveTo(Convex_hull[i].p1.x*dx,Convex_hull[i].p1.y*dy);
			dc.LineTo(Convex_hull[i].p2.x*dx,Convex_hull[i].p2.y*dy);
		}
	    strCount.Format("%i",Convex_hull.size());
	    dc.TextOut(5,5,"h="+strCount); 
	}
	dc.SelectObject(OldFont);
}

void CChildView::Animate()
{
	if(bRounded) {
		bRounded=false;
	}

	if(!Animation)	{
		// prepare counter
		TimerValue=-1;
		// create
		Create_Convex_hull();
		// set animation mode
		Animation=true;
		Invalidate(TRUE);
	}
	else	{
		TimerValue ++;
		if(TimerValue>=Convex_hull.size())
			Animation = false;
		Invalidate(TRUE);
	}
	// set 1 second timer tick
}

CPoint CChildView::Norm(int Mx, int My, double sigmaX,double sigmaY)
{
	CPoint p;
	double N;
	double x,y;
	x=(double)rand()/((double)rndMax+1.0);
	y=(double)rand()/((double)rndMax+1.0);
	N=sqrt(-2.0*log(x))*cos(2.0*Pi*y);
	N*=sigmaX;
	p.x=Mx+N;

	x=(double) rand()/((double) rndMax+1.0);
	y=(double)rand()/((double)rndMax+1.0);
	N=sqrt(-2.0*log(x))*cos(2.0*Pi*y);
	N*=sigmaY;
	p.y=My+N;
	return p;
}

CPoint CChildView::Even(int Mx,int My, double sigmaX,double sigmaY)
{
	CPoint p;
	double N;
	N=(double) rand()*sigmaX/((double) rndMax+1.0);
	p.x=Mx-sigmaX+2*N;
	N=(double) rand()*sigmaY/((double) rndMax+1.0);
	p.y=My-sigmaY+2*N;
	return p;
}

void CChildView::Generate()
{
	int	x,y;

	x = this->x/2;
	y = this->y/2;
	CChildView::OnEditClearAll();
	m_Distribution.mx = x;
	m_Distribution.my = y;
	if(m_Distribution.DoModal()!=IDOK)
		return;

	bRounded = false;
	if(m_Distribution.m_Item==2)	{
		bRounded = true;
		dRho = m_Distribution.m_Rho;
	}
	int sigma=m_Distribution.m_Sigma;
	for(int i=0; i<m_Distribution.m_Num;i++)	{
		switch(m_Distribution.m_Item)	{
		case 0:
			Points.push_back(Even(x,y,m_Distribution.m_Rect,m_Distribution.m_Rect));;
			break;
		case 1:
			Points.push_back(Norm(x,y,sigma,sigma));
			break;
		case 2:
			Points.push_back(Rounded(dRho));
			break;
		}
			
	}
	
	OnRefresh();
}

void CChildView::OnRButtonDown(UINT nFlags, CPoint point) 
{
	Create_Convex_hull();
	CWnd::OnRButtonDown(nFlags, point);
}

//////////////////////////////////////////////////////////////////////

void CChildView::Create_Convex_hull()
{
	CLine	line;
	// index of first point
	int iTempPoint1;
	// index of second point
	int iTempPoint2;
	// temporary variables
	int i,n1,n2;

	if(bRounded) {
		bRounded=false;
		Invalidate(TRUE);
	}

	if(Animation)	{
		// stop animation
		Animation = false;
		// redraw window
		Invalidate(TRUE);
	}
	// clear shape
	Convex_hull.clear();

	if(Points.size()>2)
	{
		// clear max and min
		MaxPoint=0;
		MinPoint=0;
		// looking for max(y) and min(y)
		for(i=1;i<Points.size();i++) {
			// minimum
			if(Points[MinPoint].y<Points[i].y) 
				MinPoint=i;
			else	if(Points[MinPoint].y==Points[i].y)
			{
				if(Points[MinPoint].x>Points[i].x)
					MinPoint=i;
			}
			// maximum
			if(Points[MaxPoint].y>Points[i].y) 
				MaxPoint=i;
			else	if(Points[MaxPoint].y==Points[i].y)
			{
				if(Points[MaxPoint].x<Points[i].x)
					MaxPoint=i;
			}
		}

		// from minimun to maximum
		iTempPoint1=MinPoint;
		
		while(iTempPoint1!=MaxPoint) {
			// init point 2
			if(iTempPoint1>0) 
				iTempPoint2=0;
			else
				iTempPoint2=1;
			// look for second point
			for(i=0;i<Points.size();i++) {
				if(i!=iTempPoint1) {
					n1 = (Points[iTempPoint2].x-Points[iTempPoint1].x)*(Points[i].y-Points[iTempPoint1].y);
					n2 = (Points[i].x-Points[iTempPoint1].x)*(Points[iTempPoint2].y-Points[iTempPoint1].y);
					if(n1>n2)
						iTempPoint2=i;
				}

			}
			// set line from 1 to 2
			line.p1=Points[iTempPoint1];
			line.p2=Points[iTempPoint2];
			// put it in storage
			Convex_hull.push_back(line);
			// set p1 to p2
			iTempPoint1=iTempPoint2;
		}
		
		// from maximum to minimun
		while(iTempPoint1!=MinPoint) {
			// init point 2
			if(iTempPoint1>0) 
				iTempPoint2=0;
			else
				iTempPoint2=1;
			//  look for second point
			for(i=0;i<Points.size();i++) {
				if(i!=iTempPoint1) {
					n1 = (Points[iTempPoint2].x-Points[iTempPoint1].x)*(Points[i].y-Points[iTempPoint1].y);
					n2 = (Points[i].x-Points[iTempPoint1].x)*(Points[iTempPoint2].y-Points[iTempPoint1].y);
					if(n1>n2)
						iTempPoint2=i;
				}

			}
			// set line from 1 to 2
			line.p1=Points[iTempPoint1];
			line.p2=Points[iTempPoint2];
			// put it in storage
			Convex_hull.push_back(line);
			// set p1 to p2
			iTempPoint1=iTempPoint2;
		}
		// refresh window
		Invalidate(FALSE);
	}
}

void CChildView::OnTimer(UINT nIDEvent)
{
	TimerValue++;
	if(TimerValue==Convex_hull.size()) {
		KillTimer(ID_PULSE);
		Animation=false;
	}
	Invalidate(TRUE);
	

	CWnd::OnTimer(nIDEvent);
}

void CChildView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	if(Animation)
		return ;
	CPoint p;
	p.x=point.x/dx;
	p.y=point.y/dy;
	Points.push_back(p);
	MinPoint=-1;
	MaxPoint=-1;
	
	if(Convex_hull.size()>0) {
		Convex_hull.clear();
		Invalidate(TRUE);
	}
	else 
		Invalidate(FALSE);
	if(bRounded) {
		Invalidate(TRUE);
		bRounded=false;
	}
	
	CWnd::OnLButtonDown(nFlags, point);

}


void CChildView::OnSize( UINT nType, int cx, int cy )
{
	static bool bFirst=true;
	CString	str;

	if(!bFirst&&ClientX&&ClientY)	{
		dx = (double)cx / (double)x;
		dy = (double)cy / (double)y;
		str.Format("%dx%d",cx,cy);
		((CMainFrame*)GetParent())->showStatus(str);
	}
	else	{
        x = 1000;
	    y = 1000;
		bFirst = false;
	}
	ClientX=1000;
	ClientY=1000;
}


void CChildView::OnEditClearAll() 
{
	if(Animation)
		return;
	fileName.Empty();
	MinPoint=-1;
	MaxPoint=-1;
	Points.clear();
	Convex_hull.clear();
	bRounded=false;
	Invalidate(TRUE);	
}

void CChildView::OnUpdateAnimate(CCmdUI* pCmdUI) 
{
	if(Points.size()<3)
		pCmdUI->Enable(FALSE);
	else
		pCmdUI->Enable(TRUE);	
}

double CChildView::drand()
{
	return (double)rand()/rndMax;
}

double CChildView::drand0()
{
	return (double)rand()/rndMax*2.-1.;
}

double CChildView::gaussian(double sigma, double mu)
{
	static	double	r,v1,v2;
	do
	{
		v1 = drand0();
		v2 = drand0();
		r = v1*v1+v2*v2;
	}while(r>=1.||r<=0.);
	return	(v1*sqrt(-2.*log(r)/r)*sigma+mu);
}

CPoint CChildView::Rounded(double rho)
{
	CPoint	p;
	bool ok=false; 
	double x1;
	double y1;

	while (!ok) {
	x1 = rho-2*rho * drand();
    y1 = rho-2*rho * drand();
	ok = (sqrt(x1*x1+y1*y1)<=rho);
	if (ok) {
	 p.x = x1 + x/2;
	 p.y = y1 + y/2;
	}

	}

	return p;
}

void CChildView::Serialize(CArchive& ar) 
{
	CString	sIO,sIn;
	bool	bData;
	int	cnt,offt,i;
	TCHAR	chr;
	CPoint	pnt;

	try	{
		if (ar.IsStoring())
		{	// storing code
			sIO.LoadString(IDR_MAINFRAME);
			ar.WriteString(sIO);
			ar << '\r' << '\n';
			sIO.LoadString(IDS_LEADIN);
			ar.WriteString(sIO);
			ar << '\r' << '\n';
			for(i=0;i<Points.size();i++)
			{
				sIO.Format(IDS_FMT,Points[i].x,Points[i].y);
				ar.WriteString(sIO);
				ar << '\r' << '\n';
			}
		}
		else
		{	// loading code
			ar.ReadString(sIn);
			sIO.LoadString(IDR_MAINFRAME);
			if(sIO.Compare(sIn)==0)
			{
				bData = false;
				sIO.LoadString(IDS_LEADIN);
				while(!bData)
				{
					if(!ar.ReadString(sIn))
						break;
					if(sIO.Compare(sIn)==0)
						bData = true;
				}
				while(ar.ReadString(sIn))
				{
					if(sIn.IsEmpty())
						break;
					cnt = 0;
					do
					{
						chr = sIn.GetAt(cnt+2);
						cnt ++;
					} while(chr!=' '&&chr!='\t'&&cnt+2<sIn.GetLength());
					if(cnt+2>sIn.GetLength())
						continue;
					sIO = sIn.Mid(2,cnt-1);
					pnt.x = atoi((LPCTSTR)sIO);
					offt = cnt + 2;
					cnt = 0;
					do
					{
						chr = sIn.GetAt(cnt+offt);
						cnt ++;
					} while(chr!='='&&cnt+offt<sIn.GetLength());
					if(cnt+offt>sIn.GetLength())
						continue;
					offt += cnt;
					cnt = sIn.GetLength() - offt;
					sIO = sIn.Mid(offt,cnt);
					pnt.y = atoi((LPCTSTR)sIO);
					Points.push_back(pnt);
				}
				Invalidate(FALSE);
			}
			else	{
				sIO.LoadString(IDS_BADFMT);
				MessageBox(sIO,"Чтение файла",MB_OK);
			}
		}
	}	catch(CFileException fe)	{
		MessageBox("FileException");
		fe.Delete();
	}	catch(CArchiveException ae)	{
		MessageBox("ArchiveException");
		ae.Delete();
	}	catch(CMemoryException me)	{
		MessageBox("MemoryException");
		me.Delete();
	}
}

void CChildView::OnFileOpen() 
{
	CFileDialog	fd(TRUE,"txt",fileName,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"Текстовые файлы|*.txt\0Все файлы|*.*\0\0",this);
	
	if(fd.DoModal()!=IDCANCEL)
	{
		OnEditClearAll();
		fileName = fd.GetPathName();
		CFile	f(fileName,0);
		CArchive ar(&f,1,4096,NULL);
		Serialize(ar);
	}
}

void CChildView::OnFileSave() 
{
	if(fileName.IsEmpty())
	{
		OnFileSaveAs();
	}
	else
	{
		CFile	f(fileName,1|0x1000|0x2000);
		CArchive ar(&f,0,4096,NULL);
		Serialize(ar);
	}
}

void CChildView::OnFileSaveAs() 
{
	CFileDialog	fd(FALSE,"txt",fileName,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"Текстовые файлы|*.txt\0Все файлы|*.*\0\0",this);

	if(fd.DoModal()!=IDCANCEL)
	{
		fileName = fd.GetPathName();
		CFile	f(fileName,1|0x1000|0x2000);
		CArchive ar(&f,0,4096,NULL);
		Serialize(ar);
	}
}

void CChildView::OnFileSaveCopyAs() 
{
	BOOL WriteWindowToDIB( LPCTSTR szFile, CRect	rect, CWnd *pWnd);
	CRect	r;

	CFileDialog	fd(FALSE,"bmp",bitName,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"Windows bitmap|*.bmp\0Все файлы|*.*\0\0",this);

	if(fd.DoModal()!=IDCANCEL)
	{
		bitName = fd.GetPathName();
		this->GetClientRect(r);
		WriteWindowToDIB((LPCTSTR)bitName,r,this);
	}
}

void CChildView::drawLineEx(CDC &dc, CPoint p1, CPoint p2)
{
	int	dx1,dy1;

	//////////////////////////////////////////////////
	// move p1 from p2 for 10 points by ordinate axis
	//////////////////////////////////////////////////
	dx1 = p2.x - p1.x;
	dy1 = p2.y - p1.y;
	//////////////////////////////////////////////////
	// leave original point unchanged
	//////////////////////////////////////////////////
	p2.x += deltaLen*(double)dx1/sqrt(dx1*dx1+dy1*dy1);
	p2.y += deltaLen*(double)dy1/sqrt(dx1*dx1+dy1*dy1);
	//////////////////////////////////////////////////
	// just draw it
	//////////////////////////////////////////////////
	dc.MoveTo(p1.x*dx,p1.y*dy);
	dc.LineTo(p2.x*dx,p2.y*dy);
}


void CChildView::OnRefresh() 
{
 Convex_hull.clear();
 Animation = false;
 MaxPoint=-1;
 MinPoint=-1;
 Invalidate(TRUE);
}


void CChildView::OnUpdateRefresh(CCmdUI* pCmdUI) 
{
	if(Points.size()<3)
		pCmdUI->Enable(FALSE);
	else
		pCmdUI->Enable(TRUE);	
}
Соседние файлы в папке SOURCE