Скачиваний:
17
Добавлен:
01.05.2014
Размер:
15.71 Кб
Скачать
// QTreeView.cpp : implementation of the CQTreeView class
//

#include "stdafx.h"
#include "QTree.h"

#include "QTreeDoc.h"
#include "QTreeView.h"
#include "MainFrm.h"

#include "MainStructures.h"

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

#define _X				10			//точка расположения начала координат
#define	_Y				10

#define	SIZEPOINT		10			//размер отображаемых точек

#define NUMRANDPOINTS	100


extern int mouseX,mouseY;		//текущие координаты мыши
extern int X1,Y1,X2,Y2;			//область поиска
/////////////////////////////////////////////////////////////////////////////
// CQTreeView

IMPLEMENT_DYNCREATE(CQTreeView, CView)

BEGIN_MESSAGE_MAP(CQTreeView, CView)
	//{{AFX_MSG_MAP(CQTreeView)
	ON_WM_LBUTTONDOWN()
	ON_WM_RBUTTONDOWN()
	ON_WM_MOUSEMOVE()
	ON_WM_RBUTTONUP()
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CQTreeView construction/destruction

CQTreeView::CQTreeView()
{
	//установка кисти и карандаша для отображения точек
	m_PointBrush.CreateSolidBrush(RGB(255,0,0));
	m_PointPen.CreatePen(PS_SOLID,1,RGB(255,0,0));
	//установка кисти и карандаша для отображения точек,
	//попавших в область поиска
	m_qPointBrush.CreateSolidBrush(RGB(255,220,220));
	m_qPointPen.CreatePen(PS_SOLID,1,RGB(255,220,220));

	m_pPointBrush.CreateSolidBrush(RGB(0,0,155));
	m_pPointPen.CreatePen(PS_SOLID,3,RGB(0,0,155));
	//установка карандаша для отображения области поиска
	m_RectPen.CreatePen(PS_DOT,5,RGB(0,0,255));
	m_RectPenWhite.CreatePen(PS_DOT,5,RGB(255,255,255));

	//установка карандаша для отображения сетки
	m_GridPen.CreatePen(PS_SOLID,1,RGB(100,100,100));
	//установка карандаша для отображения квадрантов дерева
	m_QTreePen.CreatePen(PS_SOLID,5,RGB(0,200,0));
	m_QTreeByStepsBrush.CreateStockObject(BLACK_BRUSH);
	m_QTreeByStepsBrush_.CreateSolidBrush(RGB(255,255,0));
	//установка карандаша для отображения осей координат
	m_OrgPen.CreatePen(PS_SOLID,6,RGB(0,0,0));
}

CQTreeView::~CQTreeView()
{
}

BOOL CQTreeView::PreCreateWindow(CREATESTRUCT& cs)
{
	if (!CView::PreCreateWindow(cs))
		return FALSE;

	cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS, 
		::LoadCursor(NULL, IDC_ARROW), NULL, NULL);

	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CQTreeView drawing

void CQTreeView::OnDraw(CDC* paintDC)
{
	CDC *pDC = new CDC;
	CBitmap bmp;

	CRect rect;
	GetClientRect(rect);

	//paintDC->SetMapMode(MM_LOMETRIC);
	//paintDC->DPtoLP(&rect);
	pDC->CreateCompatibleDC(paintDC);

	bmp.CreateCompatibleBitmap(paintDC, rect.Width(), rect.Height());
	pDC->SelectObject(&bmp);
	pDC->SelectStockObject(BLACK_BRUSH);
	pDC->Rectangle(rect);

	//устанавливаем новый режим отображения
	pDC->SetMapMode(MM_LOMETRIC);

	//устанавливаем прозрачную кисть
	pDC->SelectStockObject(NULL_BRUSH);

	UpdateGridSize(pDC);

	//устанавливаем новое положения начала координат
	pDC->SetViewportOrg(m_X,rect.Height()-m_Y);

	//устанавливаем прозрачный режим фона
	pDC->SetBkMode(TRANSPARENT);

	//отображаем координатные оси
	pDC->SelectObject(&m_OrgPen);
	CPoint p(m_X,m_Y);
	pDC->DPtoLP(&p);
	pDC->LineTo(p);
	pDC->MoveTo(0,0);
	p=CPoint(rect.Height(),rect.Height()-m_Y);
	pDC->DPtoLP(&p);
	pDC->LineTo(p);

	//если дана команда произвести поиск по области,
	//то производим этот поиск
	if (m_FindBySteps)
	{
		CRect r=RectangleLog;
		Rect rec(ELEMENT(r.left,r.bottom),ELEMENT(r.right,r.top));
		Rect curRange(ELEMENT(0,0),ELEMENT(0,0));
		ELEMENT curPoint;
		int level_=0;
		listPointsInRect=*m_QTree.RangeQuery(rec,level_,maxIndexFindBySteps,
											 curRange,curPoint);
		
		
		pDC->SelectObject(&m_QTreeByStepsBrush_);
		r.left=curRange.sw.x;
		r.top=curRange.ne.y;
		r.right=curRange.ne.x;
		r.bottom=curRange.sw.y;
		
		pDC->Rectangle(&r);

		CRect rect((int)curPoint.x-m_sp-4,(int)curPoint.y+m_sp+4,
				   (int)curPoint.x+m_sp+4,(int)curPoint.y-m_sp-4);
	
		if(curPoint.x!=-1)
		{
		//отображаем точку:
		pDC->SelectObject(&m_pPointPen);
		pDC->SelectObject(&m_pPointBrush);
		pDC->Ellipse(&rect);
		}
		
		//устанавливаем прозрачную кисть
		pDC->SelectStockObject(NULL_BRUSH);
	}
	 else
		if (m_RunFounding)
		{
			CRect r=RectangleLog;
			Rect rec(ELEMENT(r.left,r.bottom),ELEMENT(r.right,r.top));
			Rect curRange(ELEMENT(0,0),ELEMENT(0,0));
			ELEMENT curPoint;
			maxIndexFindBySteps=100000;
			int level_=0;
			listPointsInRect=*m_QTree.RangeQuery(rec,level_,maxIndexFindBySteps,
												 curRange,curPoint);
			m_RunFounding=FALSE;
		}

	//если установлен признак того, что дерево должно быть
	//изменено или включен режим автоизменения дерева,
	//то мы производим переструктуризацию сетки и дерева
	if (m_RunBuildQTree || m_CheckAutoBuildQTree)
	{
		CWaitCursor wc;
		//обновление сетки
		m_Grid.Create(m_SizeGrid,listPoints,listPoints.Lenght(),m_NumCells);
		//создание нового дерева
		while(listBySteps.Lenght()>0)
		{
			listBySteps.First();
			listBySteps.Remove();
		}

		m_QTree.Create(m_Grid,M,D,listBySteps);
	}

	if (m_BuildQTreeBySteps)
	{
		int k=0;
		int ps=0;
		int tmp=m_SizeGrid/m_NumCells;
		CRect curRect;
		int x1,y1,x2,y2;
		pDC->SelectObject(&m_QTreeByStepsBrush_);
		pDC->SelectObject(&m_QTreePen);
		for(listBySteps.First();
		    !listBySteps.isHead()&&(k<=maxIndexBuildBySteps);
			listBySteps.Next())
		{
			ps++;
			if (ps==1)
			{
				x1=listBySteps.Val()->x*tmp;
				y1=listBySteps.Val()->y*tmp;
			}
			 else
			 {
				x2=listBySteps.Val()->x*tmp+tmp;
				y2=listBySteps.Val()->y*tmp+tmp;
				ps=0;
				if (k==maxIndexBuildBySteps)
					pDC->SelectObject(&m_QTreeByStepsBrush_);
				 else
					pDC->SelectObject(&m_QTreeByStepsBrush);
				k++;
				curRect.left=x1;
				curRect.top=y2;
				curRect.right=x2;
				curRect.bottom=y1;
				pDC->Rectangle(&curRect);
			}
		}
		if (listBySteps.isHead()) 
		{
			MaxBQTree=TRUE;
		}
		//устанавливаем прозрачную кисть
		pDC->SelectStockObject(NULL_BRUSH);
	}
	 else
		{
			//отображаем дерево, если включен режим автоизменения дерева
			//или поступила команда построить новое дерево
			if (m_CheckAutoBuildQTree || m_RunBuildQTree || m_ShowQTree)
			{
				pDC->SelectObject(&m_QTreePen);
				m_QTree.DrawQTree(pDC);
				m_RunBuildQTree=FALSE;
			}
		}

	//стираем прямоугольную зону поиска
	//pDC->SelectObject(&m_RectPenWhite);
	//pDC->Rectangle(&RectangleLog);

	//проверяем, изменили ли область поиска через форму
	if (m_ChangeRange)
	{
		RectangleLog.left=X1;
		RectangleLog.top=Y1;
		RectangleLog.right=X2;
		RectangleLog.bottom=Y2;
		m_ChangeRange=FALSE;
		Rectangle=RectangleLog;
		pDC->LPtoDP(&Rectangle);
	}
		else
	{
		//физические координаты выделенной области переводим в логические
		RectangleLog=Rectangle;
		pDC->DPtoLP(&RectangleLog);
		X1=RectangleLog.left;
		Y1=RectangleLog.top;
		X2=RectangleLog.right;
		Y2=RectangleLog.bottom;
	}

	//отображаем прямоугольную зону поиска
	pDC->SelectObject(&m_RectPen);
	pDC->Rectangle(&RectangleLog);

	//отображаем сетку
	pDC->SelectObject(&m_GridPen);
	int SizeCell=m_SizeGrid/m_NumCells;
	for(int i=0;i<=m_SizeGrid;i+=SizeCell)
	{
		pDC->MoveTo(i,0);
		pDC->LineTo(i,m_SizeGrid);
		pDC->MoveTo(0,i);
		pDC->LineTo(m_SizeGrid,i);
	};

	//отображаем точки:
	pDC->SelectObject(&m_PointPen);
	pDC->SelectObject(&m_PointBrush);
	for(listPoints.First();
		!listPoints.isHead();
		listPoints.Next())
	{
		ELEMENT p;
		p=*listPoints.Val();
		CRect rect((int)p.x-m_sp,(int)p.y+m_sp,(int)p.x+m_sp,(int)p.y-m_sp);
		pDC->Ellipse(&rect);
	}

	//отображаем точки из области поиска:
	pDC->SelectObject(&m_qPointPen);
	pDC->SelectObject(&m_qPointBrush);
	for(listPointsInRect.First();
		!listPointsInRect.isHead();
		listPointsInRect.Next())
	{
		ELEMENT p;
		p=*listPointsInRect.Val();
		CRect rect((int)p.x-m_sp,(int)p.y+m_sp,(int)p.x+m_sp,(int)p.y-m_sp);
		pDC->Ellipse(&rect);
	}
	GetClientRect(rect);
	pDC->DPtoLP(&rect);
	paintDC->SetMapMode(MM_LOMETRIC);
	paintDC->BitBlt(0,0, rect.Width(), rect.Height(), 
		pDC, rect.left, rect.top, SRCCOPY);
	delete pDC;
}

/////////////////////////////////////////////////////////////////////////////
// CQTreeView printing

BOOL CQTreeView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CQTreeView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CQTreeView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CQTreeView diagnostics

#ifdef _DEBUG
void CQTreeView::AssertValid() const
{
	CView::AssertValid();
}

void CQTreeView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CQTreeDoc* CQTreeView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CQTreeDoc)));
	return (CQTreeDoc*)m_pDocument; 
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CQTreeView message handlers

//блок инициализации: задание начальных параметров
void CQTreeView::OnInitialUpdate() 
{
	CView::OnInitialUpdate();
	//получаем указатель на объект "документ"
	CQTreeDoc *pDoc=GetDocument();
	//задание максимальных значений:
	m_maxM=pDoc->m_maxM;				//коэффициента заполняемости ячейки
	m_maxD=pDoc->m_maxD;				//предельной глубины
	
	//задание начальных значений:
	M=pDoc->M;							//коэффициента заполняемости ячейки
	D=pDoc->D;							//предельной глубины

	m_SizeGrid=pDoc->m_SizeGrid;		//начальное значение размерности сетки
	m_NumCells=pDoc->m_NumCells;		//начальное значение количества ячеек в строке

	m_maxSizeGrid=pDoc->m_maxSizeGrid;	//максимальная размерность сетки
	m_maxNumCells=pDoc->m_maxNumCells;	//максимальное количество ячеек в строке

	//задание списка точек
	listPoints=pDoc->listPoints;
	//удаляем результаты последнего поиска
	while(listPointsInRect.Lenght()>0)
	{
		listPointsInRect.First();
		listPointsInRect.Remove();
	}
	
	//получаем указатель на объект "главное окно"
	CMainFrame *pWnd=(CMainFrame*)AfxGetMainWnd();


	MaxFind=FALSE;
	MaxBQTree=FALSE;

	//устанавливаем пределы изменения размеров сетки
	//и начальное значение
	CSpinButtonCtrl *pSpin=(CSpinButtonCtrl*)pWnd->m_wndDlgBar.GetDlgItem(IDC_SPIN1);
	pSpin->SetRange(2,m_maxSizeGrid);
	pSpin->SetPos(m_SizeGrid);
	
	//устанавливаем пределы изменения числа ячеек
	//и начальное значение
	pSpin=(CSpinButtonCtrl*)pWnd->m_wndDlgBar.GetDlgItem(IDC_SPIN2);
	pSpin->SetRange(1,m_maxNumCells);
	pSpin->SetPos(m_NumCells);

	//устанавливаем пределы изменения коэффициента
	//заполняемости ячейки и начальное значение
	pSpin=(CSpinButtonCtrl*)pWnd->m_wndDlgBar.GetDlgItem(IDC_SPIN3);
	pSpin->SetRange(1,m_maxM);
	pSpin->SetPos(M);

	//устанавливаем пределы изменения предельной глубины 
	//и начальное значение
	pSpin=(CSpinButtonCtrl*)pWnd->m_wndDlgBar.GetDlgItem(IDC_SPIN4);
	pSpin->SetRange(1,m_maxD);
	pSpin->SetPos(D);

	//в данный момент отображение области поиска не производится
	m_DrawRect=FALSE;
	m_DrawQTree=FALSE;
	//устанавливаем вырожденный случай области поиска
	Rectangle.left=Rectangle.right=Rectangle.top=Rectangle.bottom=0;
	X1=Y1=X2=Y2=0;
	//разрешаем начальные значения области поиска по умолчанию
	m_ChangeRange=FALSE;

	//точка расположения начала координат
	m_X=_X;
	m_Y=_Y;
	
	//размер отображаемых точек
	m_sp=SIZEPOINT;

	m_numberRandomPoints=NUMRANDPOINTS;

	//создание сетки на основе первоначальных данных
	m_Grid.Create(m_SizeGrid,listPoints,listPoints.Lenght(),m_NumCells);
	//создание дерева на основе первоначальных данных
	m_QTree.Create(m_Grid,M,D,listBySteps);
	//устанавливаем признак демонстрации дерева
	m_ShowQTree=TRUE;
	//отключаем режим автоматического построения дерева
	//m_CheckAutoBuildQTree=FALSE;
	m_CheckAutoBuildQTree=TRUE;
	//устанавливаем признак обновления дерева в false
	m_RunBuildQTree=FALSE;
	//запрещаем поиск по области
	m_RunFounding=FALSE;
	//запрещаем построение дерева по шагам
	m_BuildQTreeBySteps=FALSE;
	//запрещаем поиск по шагам
	m_FindBySteps=FALSE;
}

void CQTreeView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	CView::OnLButtonDown(nFlags, point);

	if (!(m_BuildQTreeBySteps || m_FindBySteps))
	{
	CClientDC pDC(this);
	pDC.SelectStockObject(WHITE_BRUSH);
	pDC.SetMapMode(MM_LOMETRIC);
	CRect rect;
	GetClientRect(rect);
	pDC.SetViewportOrg(m_X,rect.Height()-m_Y);
	pDC.DPtoLP(&point);

	//если точка не лежит в положительном квадранте,
	//то мы ее игнорируем
	if ((point.x<0) || (point.y<0)) return;
	//иначе добавляем в общий список точек
	ELEMENT p;
	p.x=(POINTTYPE)point.x;
	p.y=(POINTTYPE)point.y;
	listPoints.Append(ELEMENT(p));

	//отменяем режим демонстрации дерева вследствии 
	//необходимости его изменения
	m_ShowQTree=FALSE;
	//отменяем признак формирования нового дерева
	m_RunBuildQTree=FALSE;
	//удаляем все точки последнего поиска
	while(listPointsInRect.Lenght()>0)
	{
		listPointsInRect.First();
		listPointsInRect.Remove();
	}

	CQTreeDoc *pDoc=GetDocument();
	//обновляем данные документа
	pDoc->listPoints=listPoints;
	pDoc->SetModifiedFlag();

	//отображаем новую точку на экране
	Invalidate();
	}
}

void CQTreeView::OnRButtonDown(UINT nFlags, CPoint point) 
{
	if (!(m_BuildQTreeBySteps || m_FindBySteps))
	{
	//формируем область поиска при нажатии и удерживании
	//правой клавиши мыши
	Rectangle=CRect(point.x,point.y,point.x,point.y);
	//разрешаем отображение области поиска
	m_DrawRect=TRUE;
	//и удаляем результаты предыдущего поиска
	List tmpList;
	listPointsInRect=tmpList;
	}

	CView::OnRButtonDown(nFlags, point);
}

void CQTreeView::OnMouseMove(UINT nFlags, CPoint point) 
{
	if (!(m_BuildQTreeBySteps || m_FindBySteps))
	{
	static int flag=0;
	if ((m_DrawRect) && (flag%1)==0)
	{
		//при перемещении мыши изменяется область поиска:
		Rectangle.right=point.x;
		Rectangle.bottom=point.y;	
		Invalidate();
	}
	//увеличиваем значение параметра flag и следим, чтобы не было переполнения
	flag=(++flag>1000)?0:flag;

	//преобразуем физические координаты в логические
	//для отображения их значений в строке состояния
	CClientDC pDC(this);
	pDC.SetMapMode(MM_LOMETRIC);
	CRect rect;
	GetClientRect(rect);
	pDC.SetViewportOrg(m_X,rect.Height()-m_Y);

	pDC.DPtoLP(&point);
	mouseX=point.x;
	mouseY=point.y;
	}

	CView::OnMouseMove(nFlags, point);
}

void CQTreeView::OnRButtonUp(UINT nFlags, CPoint point) 
{
	CView::OnRButtonUp(nFlags, point);
	m_DrawRect=FALSE;	
}

void CQTreeView::UpdateGridSize(CDC *dc)
{
	CRect rect;
	static int lastsize = 0;
	int size;
	double ratio;
	GetClientRect(&rect);
	dc->DPtoLP(&rect);
	size = min(abs(rect.Height()), abs(rect.Width()))-50;
	if(lastsize==size) return;
	ratio = (double)size/(double)lastsize;
	lastsize = size;
	m_SizeGrid = size-size%32;
	for(listPoints.First();
		!listPoints.isHead();
		listPoints.Next())
	{
		ELEMENT *p=listPoints.Val();
		p->x *= ratio;
		p->y *= ratio;
	}
	Rectangle.bottom *= 1.0/ratio;
	Rectangle.top *= 1.0/ratio;
	Rectangle.left *= ratio;
	Rectangle.right *= ratio;
}
Соседние файлы в папке src