您的位置:首页 > 其它

mfc绘制曲线

2017-12-06 21:04 162 查看

自带库绘制

用mfc自带的绘图函数绘制一个sin曲线,可以说是非常费力和傻了,基于对话框程序在onPaint()函数中添加绘制代码。效果也并不是很好。

void CdrawLineDlg::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
{
CPaintDC dc(this); // 用于绘制的设备上下文
HPEN pen = CreatePen(PS_SOLID, 2, RGB(rand() % 256, rand() % 256, rand() % 256));
//选择画笔
HPEN oldPen = (HPEN)SelectObject(dc, pen);
//指定原点
dc.SetViewportOrg(80, 180);
SetTextColor(dc,RGB(255, 0, 0));
//绘制横坐标
CString sPIText[] = { "-1/2π","1/2π","π","3/2π","2π","5/2π","3π","7/2π","4π","9/2π","5π" };
for (int n = 0; n<10; n++)
{
LineTo(dc,60 * n, 0);//坐标横线
LineTo(dc,60 * n, -5);
MoveToEx(dc,60 * n, 0,NULL);
TextOut(dc,60 * n - sPIText
.GetLength() * 3, 16, sPIText
, sPIText
.GetLength());
}
MoveToEx(dc,0, 0,NULL);

CString sTemp;
//绘制纵坐标
for (int n = -4, nTemp = 0; nTemp <= 180; n++, nTemp = 60 * n)
{
LineTo(dc,0, 60 * n);
LineTo(dc,5, 60 * n);
MoveToEx(dc,0, 60 * n,NULL);
sTemp.Format("%d", -n);
TextOut(dc,10, 60 * n, sTemp,sTemp.GetLength());
}

double y, radian;
//绘制相关曲线
for (int x = -60; x<600; x++)
{
//弧度=X坐标/曲线宽度*角度*π
//Y坐标=振幅*曲线宽度*sin(弧度)
radian = x / ((double)60 * 2)*PI;
y = sin(radian) * 2 * 60;
MoveToEx(dc,(int)x, -(int)y,NULL);
LineTo(dc,(int)x, -(int)y);
}
//恢复画笔
SelectObject(dc, oldPen);
CDialogEx::OnPaint();
}
}


TeeChart控件绘制

控件下载(搬运):https://pan.baidu.com/s/1o69nOZS

安装参考:https://www.cnblogs.com/qiengo/p/4238567.html

动态曲线绘制参考:http://blog.csdn.net/zang141588761/article/details/50536788

这个扩展的控件可以说是非常好用的了。放到对话框当中,直接就可以对其添加变量进行画图操作了。



动态绘制主要是维护两个数组,一个是横坐标,一个是待写入数据的纵坐标。根据定时器不断左移数组完成动态绘制。我这里用到了6个图表,其中第一第二 第四第五都是3条曲线,第二2条,第六一条。定义六个数组。

double m_ThumbArray[3][32]; //大拇指角度数组
CSeries LineThumb[3];   //大拇指曲线

double m_IndexArray[3][32]; //食指角度数组
CSeries LineIndex[3];   //食指曲线

double m_MiddleArray[2][32];    //中指角度数组
CSeries LineMiddle[2];  //中指曲线

double m_RingArray[3][32];  //无名指角度数组
CSeries LineRing[3];    //无名指曲线

double m_LittleArray[3][32];    //小指角度数组
CSeries LineLittle[3];  //小指曲线

double m_BaseArray[32]; //掌腕关节角度数组
CSeries LineBase;   //掌腕关节曲线

double m_X[32];
unsigned int m_count;
const size_t m_Length = 32;


六个图表关联变量:

CTchart1 CThumb;
CTchart1 CIndex;
CTchart1 CMiddle;
CTchart1 CRing;
CTchart1 CLittle;
CTchart1 CBase;


数组左移函数

//数组左移
void LeftMoveArray(double* ptr, size_t length, double data)
{
for (size_t i = 1; i<length; ++i)
{
ptr[i - 1] = ptr[i];
}
ptr[length - 1] = data;
}


画曲线函数,这里还调用了父窗口的数据写入曲线数据数组。

void CLineChart::drawMoving()
{
HWND hWnd = ::FindWindow(NULL, _T("数据手套数据读取面板"));      //得到对话框的句柄
GloveSampleDlg * dlg = (GloveSampleDlg*)GloveSampleDlg::FromHandle(hWnd); //由句柄得到对话框的对象指针
LeftMoveArray(m_X, m_Length, m_count);

for (int i = 0; i < 3; i++) {
LeftMoveArray(m_ThumbArray[i],m_Length, dlg->angle[i]); //获取大拇指角度
LeftMoveArray(m_IndexArray[i], m_Length, dlg->angle[i+3]);  //获取食指角度
if (i < 2) {
LeftMoveArray(m_MiddleArray[i], m_Length, dlg->angle[i+6]); //获取中指角度
}
LeftMoveArray(m_RingArray[i], m_Length, dlg->angle[i+8]);   //获取无名指角度
LeftMoveArray(m_LittleArray[i], m_Length, dlg->angle[i + 11]);  //获取小指角度
}
LeftMoveArray(m_BaseArray, m_Length, dlg->angle[14]);   //获取掌腕关节角度
for (int i = 0; i < m_Length; i++)
{
for (int j = 0; j < 3; j++) {
LineThumb[j].AddXY(m_X[i], m_ThumbArray[j][i], NULL, NULL);
LineIndex[j].AddXY(m_X[i], m_IndexArray[j][i], NULL, NULL);
if (j < 2) {
LineMiddle[j].AddXY(m_X[i], m_MiddleArray[j][i], NULL, NULL);
}
LineRing[j].AddXY(m_X[i], m_RingArray[j][i], NULL, NULL);
LineLittle[j].AddXY(m_X[i], m_LittleArray[j][i], NULL, NULL);
}
LineBase.AddXY(m_X[i], m_BaseArray[i], NULL, NULL);
}
}


绘制按键消息响应函数

// CLineChart 消息处理程序
void CLineChart::OnBnClickedDrawline()
{
// 点击绘图按钮绘图
for (int i = 0; i < 3; i++) {
LineThumb[i]= (CSeries)CThumb.Series(i);
LineThumb[i].Clear();
ZeroMemory(&m_ThumbArray[i], sizeof(double)*m_Length);

LineIndex[i] = (CSeries)CIndex.Series(i);
LineIndex[i].Clear();
ZeroMemory(&m_IndexArray[i], sizeof(double)*m_Length);
if (i < 2) {
LineMiddle[i] = (CSeries)CMiddle.Series(i);
LineMiddle[i].Clear();
ZeroMemory(&m_MiddleArray[i], sizeof(double)*m_Length);
}
LineRing[i] = (CSeries)CRing.Series(i);
LineRing[i].Clear();
ZeroMemory(&m_RingArray[i], sizeof(double)*m_Length);

LineLittle[i] = (CSeries)CLittle.Series(i);
LineLittle[i].Clear();
ZeroMemory(&m_LittleArray[i], sizeof(double)*m_Length);
}
LineBase = (CSeries)CBase.Series(0);
LineBase.Clear();
ZeroMemory(&m_BaseArray, sizeof(double)*m_Length);
KillTimer(0);
for (size_t i = 0; i<m_Length; ++i)
{
m_X[i] = i;
}
m_count = m_Length;
SetTimer(0, 20, NULL);
}


定时器,隔一段时间调用drawMoving()函数实现动态绘制

void CLineChart::OnTimer(UINT_PTR nIDEvent)
{
if (0 == nIDEvent)
{
++m_count;
drawMoving();
}
CDialogEx::OnTimer(nIDEvent);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: