Добавил:
Studfiles2
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Региональный поиск метод квадрантного дерева / src / QTreeView
.cpp// 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