MFC中使用TeeChart绘制三维曲线

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/carlos_soler/article/details/78614054

TeeChart控件是功能强大,可以绘制各种图像,因此在MFC中具有较多的应用。关于使用TeeChart绘制二维图像,现在网上可以搜到很多的教程;对于三维绘图,网上也有一些教程,但是对新手来说,由于某些地方不甚详细,总是会出现一些意料不到的问题。这里计划绘制一个三维螺旋线,详细地指出每一步应该怎么去操作。

在此之前,应该保证计算机上注册过TeeChart的ActiveX控件,同时也有TeeChart的程序集(包含着TeeChart所需要的各种类)。如果只使用TeeChart activeX控件但没有程序集,就会遇到诸如“找不到函数ADDXYZ()”之类的错误。


1.新建MFC项目,导入TeeChart控件


首先先新建一个基于对话框的MFC程序,命名为Chart,对话框的标题就叫做“三维绘图”好了。建立好之后如下图所示。



随后删除掉不需要的static控件,然后再对话框上右键单击,选择“插入ActiveX控件”,在对话框中选择TeeChart Pro ActiveX Control,如下图所示。



这个控件就是用来绘图的TeeChart控件了。随后调整控件的大小和位置,调好之后双击控件,在弹出的对话框中选择chart->series,单击右边的Add按钮(以上的操作实际上是为这个teechart控件添加一个图像)。在图像类型中选择point3D,也就是三维曲线,如下图。在下图中我们也能看到,TeeChart所提供的图像类型非常多,二维的曲线图、饼图、误差棒图等,三维的曲线、曲面图一应俱全,基本上包含了我们所需要用到的一切功能。



2.导入TeeChart程序集中相应的类


把TeeChart程序集(里面包含各种.h文件与.cpp文件)放在项目目录下。我之前就是因为没有使用这个程序集,所以没有办法绘制三维曲线。



在解决方案中右击Chart,添加项->现有项,在项目中添加需要的文件。本次三维绘图需要用到的包括tchart,series,point3dseries对应的.h文件及.cpp文件,里面分别定义了CTChart,CSeries,CPoint3DSeries三个类。一般来说,TeeChart对应的关联变量需要定义成CTChart类型,而TeeChart上面的图像作为CSeries类型处理,CPoint3DSeries是三维曲线绘图需要用的类型。另外多说一句,在程序集中我们可以看到有各式各样的文件,里面具有相应的类(比如涉及到坐标轴的Axes类,涉及图属性的Aspect类,可以按照需要去引入、使用。我们这里只做一个简单的实例,所以不用那么多。我们导入的文件如下图所示。



3.添加TeeChart的关联变量


这一步算是和很多TeeChart二维绘图教程不一样的地方,而很多介绍三维绘图的相关文章中也没有提及(之前一直没有办法成功绘制三维图,就是卡在这里)。当然,我不知道我的操作算不算是官子,但是至少是可以实现的。

在这里,首先要在ChartDlg.h这个对话框类头文件中手动添加一个TeeChart的关联变量,类型为CTChart类型,也就是

private:
	CTChart m_Chart;//TEECHART对应的控件
同时别忘了添加CTChart类的头文件引用(在tchart.h这个文件中)

#include"TeeChart\tchart.h"
最终得到的对话框类头文件应该是这样的(其他语句都是自己生成的,没有做修改)

// ChartDlg.h : 头文件
//

#pragma once

#include"TeeChart\tchart.h"

// CChartDlg 对话框
class CChartDlg : public CDialogEx
{
// 构造
public:
	CChartDlg(CWnd* pParent = NULL);	// 标准构造函数

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_CHART_DIALOG };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持


// 实现
protected:
	HICON m_hIcon;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()

	//控件
private:
	CTChart m_Chart;//TEECHART对应的控件
};

随后创建m_Chart和TeeChart控件的数据绑定。在对话框类的实现文件中找到DoDataExchange函数,添加语句

DDX_Control(pDX, IDC_TCHART1, m_Chart);//控件的绑定
这里IDC_TCHART1是我们所用的TeeChart控件的ID。
如果你看过一些二维绘图教程,你会发现在这里我们的操作是不同的。很多二维绘图教程没有添加TeeChart的程序集,让我们在控件上右键点击去自动建立关联变量m_Chart。但是如果使用这种方法,很有可能最后得到的变量类型是CTchart1类型的(而非CTChart类型),相应的三维绘图函数是找不到的。有时候你如果两种方法都尝试,可能还会造成重复定义类型的错误。所以我猜测可能我们所导入的程序集中的类功能更加完善一些吧,因此我觉得使用程序集更好一些。


4.绘图


我们尝试绘制如下曲线:

$$\left\{\begin{matrix} x=\cos \left( 2 \pi t/100 \right) \\ y= \sin \left( 2 \pi t/100 \right) \\ z= t/10 \end{matrix}\right.$$

该曲线表示以t为参数的螺旋线。在OnInitDialog()函数中添加如下程序段:

	const double pi = 3.14;//定义pi	  
	for (int i = 0; i<300; i++)
		m_Chart.Series(0).GetAsPoint3D().AddXYZ(cos(2*pi*i/100), sin(2*pi*i/100), i/10, NULL, RGB(0, 0, 255));//前三个是点坐标,最后一个参数时点的颜色
其他的地方不需要做修改。不过同时记得添加相应的头文件

#include "TeeChart\tchart.h"
#include"TeeChart\series.h"
#include"TeeChart\point3dseries.h"
对话框类实现文件为:

// ChartDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "Chart.h"
#include "ChartDlg.h"
#include "afxdialogex.h"

#include "TeeChart\tchart.h"
#include"TeeChart\series.h"
#include"TeeChart\point3dseries.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
	CAboutDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_ABOUTBOX };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CChartDlg 对话框



CChartDlg::CChartDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(IDD_CHART_DIALOG, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CChartDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_TCHART1, m_Chart);//控件的绑定
}

BEGIN_MESSAGE_MAP(CChartDlg, CDialogEx)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
END_MESSAGE_MAP()


// CChartDlg 消息处理程序

BOOL CChartDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		BOOL bNameValid;
		CString strAboutMenu;
		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
		ASSERT(bNameValid);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	const double pi = 3.14;//定义pi	  
	for (int i = 0; i<300; i++)
		m_Chart.Series(0).GetAsPoint3D().AddXYZ(cos(2*pi*i/100), sin(2*pi*i/100), i/10, NULL, RGB(0, 0, 255));//前三个是点坐标,最后一个参数时点的颜色

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CChartDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialogEx::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CChartDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CChartDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

运行后,可以得到如图所示的螺旋线



这样一个三维曲线图像就绘制完成了。接下来可以对图进行设置(坐标轴、标题、图例、标记点的类型等),使得绘图效果看起来更加漂亮一些。设置的方法有两种,一种是静态的,你可以在控件上直接双击,然后进行操作;另一种是动态的,就需要你添加上TeeChart程序集里面相应的类,然后用后台代码去修改。比如说我加一个标题,去掉图例,再稍微做一些小修小补,就可以得到下图所示的最终结果。



以上就是我对TeeChart三维曲线绘图的一些粗浅的理解。欢迎大家一起交流讨论。

展开阅读全文

没有更多推荐了,返回首页