📄 childview.cpp
字号:
// ChildView.cpp
//
#include "stdafx.h"
#include "DelaunayDemo.h"
#include "ChildView.h"
#include "QPerformanceTimer.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
const int range = 1000;
#define colVertex (RGB(255, 128, 0))
#if(WINVER >= 0x0400)
#define FONT DEFAULT_GUI_FONT
#else
#define FONT SYSTEM_FONT
#endif
inline int Int(REAL r) { return (int) floor(r + 0.5f); } // properly round of a REAL
// Function object to draw a vertex; to be used in for_each algorithm.
class drawVertex
{
public:
drawVertex(CDC& dc, REAL hScale, REAL vScale) : m_DC(dc), m_hScale(hScale), m_vScale(vScale) {}
void operator()(const vertex& v) const
{
const int halfSize = 2;
CRect rc;
rc.SetRectEmpty();
rc.InflateRect(halfSize, halfSize);
rc.OffsetRect(Int(m_hScale * v.GetX()), Int(m_vScale * v.GetY()));
m_DC.FillSolidRect(& rc, colVertex);
}
protected:
CDC& m_DC;
REAL m_hScale;
REAL m_vScale;
};
// Function object to draw an edge.
class drawEdge
{
public:
drawEdge(CDC& dc, REAL hScale, REAL vScale) : m_DC(dc), m_hScale(hScale), m_vScale(vScale) {}
void operator()(const edge& e) const
{
m_DC.MoveTo(Int(m_hScale * e.m_pV0->GetX()), Int(m_vScale * e.m_pV0->GetY()));
m_DC.LineTo(Int(m_hScale * e.m_pV1->GetX()), Int(m_vScale * e.m_pV1->GetY()));
}
protected:
CDC& m_DC;
REAL m_hScale;
REAL m_vScale;
};
// Function object to draw a triangle.
class drawTriangle
{
public:
drawTriangle(CDC& dc, REAL hScale, REAL vScale) : m_DC(dc), m_hScale(hScale), m_vScale(vScale) {}
void operator()(const triangle& tri) const
{
const vertex * v0 = tri.GetVertex(0);
m_DC.MoveTo(Int(m_hScale * v0->GetX()), Int(m_vScale * v0->GetY()));
const vertex * v1 = tri.GetVertex(1);
m_DC.LineTo(Int(m_hScale * v1->GetX()), Int(m_vScale * v1->GetY()));
const vertex * v2 = tri.GetVertex(2);
m_DC.LineTo(Int(m_hScale * v2->GetX()), Int(m_vScale * v2->GetY()));
m_DC.LineTo(Int(m_hScale * v0->GetX()), Int(m_vScale * v0->GetY()));
}
protected:
CDC& m_DC;
REAL m_hScale;
REAL m_vScale;
};
////////////////////
// CChildView
CChildView::CChildView()
: m_nVertices(200)
, m_nTime(0)
{
}
CChildView::~CChildView()
{
}
BEGIN_MESSAGE_MAP(CChildView, CWnd)
ON_WM_PAINT()
ON_WM_SIZE()
ON_WM_CREATE()
ON_COMMAND(ID_FILE_OPTIONS, OnFileOptions)
END_MESSAGE_MAP()
BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs)
{
if (!CWnd::PreCreateWindow(cs))
return FALSE;
cs.dwExStyle |= WS_EX_CLIENTEDGE;
cs.style &= ~WS_BORDER;
cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS,
::LoadCursor(NULL, IDC_ARROW), reinterpret_cast<HBRUSH>(COLOR_WINDOW+1), NULL);
return TRUE;
}
void CChildView::OnPaint()
{
CPaintDC dc(this);
dc.SetViewportOrg(m_hMargin, m_vMargin);
// for_each(m_Triangles.begin(), m_Triangles.end(), drawTriangle(dc, m_hScale, m_vScale)); // for debugging
// If we simply draw all the triangles, most of the edges are drawn twice.
// Therefore, we first eliminate the superfluous edges.
edgeSet edges;
Delaunay d;
d.TrianglesToEdges(m_Triangles, edges);
for_each(edges.begin(), edges.end(), drawEdge(dc, m_hScale, m_vScale));
for_each(m_Vertices.begin(), m_Vertices.end(), drawVertex(dc, m_hScale, m_vScale));
CGdiObject * pOldFont = dc.SelectStockObject(FONT);
int oldBkMode = dc.SetBkMode(TRANSPARENT);
CString s;
s.Format(IDS_FORMAT, m_nVertices, m_nTime);
dc.TextOut(0, m_yText, s);
dc.SetBkMode(oldBkMode);
if (pOldFont) dc.SelectObject(pOldFont);
}
void CChildView::OnSize(UINT nType, int cx, int cy)
{
const int marginFactor = 20;
CWnd::OnSize(nType, cx, cy);
if (cx == 0 || cy == 0) return;
CClientDC dc(this);
CGdiObject * pOldFont = dc.SelectStockObject(FONT);
CSize sz = dc.GetTextExtent(_T("M"), 1);
if (pOldFont) dc.SelectObject(pOldFont);
m_hMargin = cx / marginFactor;
m_vMargin = cy / marginFactor;
int w = cx - 2 * m_hMargin;
int h = cy - 2 * m_vMargin - sz.cy;
m_hScale = (REAL) w / (REAL) range;
m_vScale = (REAL) h / (REAL) range;
m_yText = h + sz.cy / 2;
}
int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
NewVertices();
return 0;
}
void CChildView::NewVertices(void)
{
// Fill m_Vertices with a new set of random vertices and calculate the Delaunay-triangulation.
m_Vertices.clear();
m_Triangles.clear();
for (int i = 0; i < m_nVertices; i++)
{
int x = rand() % range;
int y = rand() % range;
m_Vertices.insert(vertex(x, y));
}
{ // Block defines measuring time.
QPerformanceTimer timer(m_nTime);
Delaunay d;
d.Triangulate(m_Vertices, m_Triangles);
}
}
void CChildView::OnFileOptions()
{
COptionsDlg dlg;
dlg.m_nVertices = m_nVertices;
if (dlg.DoModal() == IDOK)
{
m_nVertices = dlg.m_nVertices;
NewVertices();
Invalidate();
}
}
/////////////////////
// COptionsDlg
IMPLEMENT_DYNAMIC(COptionsDlg, CDialog)
COptionsDlg::COptionsDlg(CWnd* pParent /*=NULL*/)
: CDialog(COptionsDlg::IDD, pParent)
, m_nVertices(0)
{
}
COptionsDlg::~COptionsDlg()
{
}
void COptionsDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_NVERTICES, m_nVertices);
DDV_MinMaxInt(pDX, m_nVertices, 0, 2000);
DDX_Control(pDX, IDC_SNVERICES, c_spinVertices);
}
BEGIN_MESSAGE_MAP(COptionsDlg, CDialog)
END_MESSAGE_MAP()
BOOL COptionsDlg::OnInitDialog()
{
CDialog::OnInitDialog();
c_spinVertices.SetRange(0, 2000);
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -