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

📄 childview.cpp

📁 一个VC++生成DElaunay三焦网的简洁易懂的代码
💻 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 + -