vs2010实现绘制曲线_vs2010mfc界面开发的空间b样条曲线插补算法 文件包含的是空间B样条曲线...

vs2010mfc界面开发的空间b样条曲线插补算法。 vs2010mfc界面开发的空间b样条曲线插补算法。 文件包含的是空间B样条曲线插补,里面可以实现刀轨的生成调节刀轨的速度,曲线的空间旋转和平移,以及加工过程的G代码和步长的生成和设置,可以手动输入数据点,或者生成随机的数据点,然后内部可以反求控制点进而绘制出曲线

ID:8330593526697884幽灵bosssss

点击下载 最新有坐标放大功能工程。

坐标为每10s传感器采集的数据 代码:

using System;

using System.Collections;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.IO;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using System.Runtime.InteropServices;

using System.Drawing.Drawing2D;

namespace TEST

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}

private Point mouseOffset;

int times = 10;//每10s采集一次数据

int drawflag=0;

private int height = 350;

private int width = 800;

private Bitmap bitmap;

private Graphics graphics;

private float Tension = 0.5f;

//要画曲线的点y坐标值,x值为10s采集一次数据

private float[] curvebuf = new float[] { 20.0f, 30.0f, 40.0f, 35.4f, 21.6f, 32.8f,5.2f,9.9f,30f,35.3f,25.3f,21.2f,30.2f,22.8f,40.5f,5.6f,20.6f };

private void DrawCurve(float [] buf)

{

//创建位图

bitmap = new Bitmap(width, height);

//创建Graphics类对象

graphics = Graphics.FromImage(bitmap);

//清空图片背景色

//graphics.Clear(Color.White);

Font font = new System.Drawing.Font("Arial", 9, FontStyle.Regular);

//填充背景

graphics.FillRectangle(Brushes.SeaGreen, 0, 0, width, height);

Brush brush1 = new SolidBrush(Color.Blue);

Brush brush2 = new SolidBrush(Color.SaddleBrown);

Brush brushPoint = new SolidBrush(Color.Red);

//画图片的边框线

Pen mypenBlack = new Pen(Color.Black, 1);

graphics.DrawRectangle(mypenBlack, 40, 40, 720, 270);//矩形

graphics.DrawRectangle(mypenBlack, 40, 35, 720, 275); //矩形

Pen mypenBlue = new Pen(Color.Blue, 1);//线条

Pen mypenRed = new Pen(Color.Red, 1);

Pen mypenYellow = new Pen(Color.Yellow,1);//点颜色

//绘制线条

//绘制纵向线条

int x = 80;

for (int i = 0; i < 17; i++)

{

graphics.DrawLine(mypenBlue, x, 40, x, 310);

x = x + 40;

}

//绘制横向线条

int y = 70;

for (int i = 0; i < 8; i++)

{

graphics.DrawLine(mypenBlue, 40, y, 760, y);

y = y + 30;

}

//x轴上对应的标记

String[] n = { " 10", " 20", " 30", " 40", " 50", " 60", " 70",

" 80", " 90", " 100", "110", "120", "130", "140", "150", "160", "170"};

x = 70;

for (int i = 0; i < 17; i++)

{

graphics.DrawString(n[i].ToString(), font, Brushes.Red, x, 315); //设置文字内容及输出位置

x = x + 40;

}

//y轴上对应的标记

String[] m = {"40", "35", "30", "25", "20", "15", "10", " 5"};

y = 60;

for (int i = 0; i < 8; i++)

{

graphics.DrawString(m[i].ToString(), font, Brushes.Red, 16, y); //设置文字内容及输出位置

y = y + 30;

}

//画曲线

if (drawflag == 1)

{

int len = buf.Length;

PointF[] CurvePointF = new PointF[len];//坐标点

float pointX = 0;

float pointY = 0;

for (int i = 0; i < len; i++)

{

pointX = i * times * 4 + 80; //坐标系(0,0)实际位置为(70,310)实际工程坐标左上角为原点。

pointY = 310 - 60 * (buf[i] / 10);

CurvePointF[i] = new PointF(pointX, pointY);

graphics.FillEllipse(brushPoint, pointX-4, pointY-4, 8, 8);//画点,是以圆心为切点画的圆,所以减去半径

}

graphics.DrawCurve(mypenYellow, CurvePointF, Tension);//画曲线

label2.Text = Convert.ToString("输出点个数:"+len);

}

graphics.Dispose();

this.pictureBox1.Image = bitmap;

}

private void Form1_Load(object sender, EventArgs e)

{

label1.Visible = false;

label1.Parent = pictureBox1;

DrawCurve(curvebuf);

}

private void Form1_FormClosed(object sender, FormClosedEventArgs e)

{

}

private void 关于ToolStripMenuItem_Click(object sender, EventArgs e)

{

Form2 f=new Form2();

f.Show();

}

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)

{

int ex = e.X;

int ey = e.Y;

mouseOffset.X= (e.X-40)/4;

mouseOffset.Y=(310- e.Y)/6;

if ((ex > 40 && ex < 760) && (ey > 40 && ey < 310))

{

label1.BackColor = Color.FromArgb(80, Color.White);

label1.Visible = true;

label1.Text = ("坐标值:" + "\n" + "x=" + mouseOffset.X + "\n" + "y=" + mouseOffset.Y);

label1.Location = new Point(ex+20, ey+10);

}

else

{

label1.Visible = false;

}

}

private void buttonDraw_Click(object sender, EventArgs e)

{

int lens = curvebuf.Length;

if (lens <= 1)

{

drawflag = 0;

MessageBox.Show("数据小于2!", "错误",

MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

}

else

{

drawflag = 1;

DrawCurve(curvebuf);

}

}

private void buttonClear_Click(object sender, EventArgs e)

{

drawflag = 0;

label2.Text = Convert.ToString("输出点个数:");

DrawCurve(curvebuf);

}

}

}

1.前期准备

?详细可见VS2010 使用TeeChart画图控件 - 之中的一个?控件和类的导入

1. 1 加入TeeChart控件,给控件加入变量m_TeeChart

?

加入TeeChart控件,右击控件,选择加入变量,vs会自己主动给我们引入CTchart1这个类,可是仅仅有这个类,我们是远远不够的,须要加入teechart其它相关的类,加入方法在之前已经讲过,不再反复。

1.2. 引入必要的头文件

事实上之前的方法比較麻烦,更简单就是通过类向导,导入类型库的类

如图进入类向导,选择加入类button的下拉菜单,选择类型库中的MFC类

选择teechart5就可以

临时引入 #include "CSeries.h"? #include "CAxis.h" #include "CAxes.h" #include "CLegend.h"

须要还能够继续在之后引入

--------------------------------------------------------------------------------------------------------------------------------

2. teechart 绘图 - 折线图

TeeChart 画图步骤通常是先获得图线序列CSeries,再给Series加入点;加入点能够用函数AddXY,或者AddArray。AddArray要比AddXY的效率高出非常多,其比較可见 TeeChart画图控件 - 之三 - 提高画图的效率

2.1 清除图形

在画线之前把图形清除一下,否则会覆盖,清除可用CSeries的函数Clear(); 可是当加入多个Series后要对全部Series都clear,这是非常蛋疼的,由于你有时都不知道有多少个Series,这样能够先获得Series的总数在clear 代码例如以下

? ??

for(

long?i?

=?

0;i

++)?

????{

????????((CSeries)m_TeeChart.Series(i)).Clear();

????}

?

通过CTchart 的get_SeriesCount函数获得所有图像序列,再所有清除,这个函数经经常使用到,可用定义为类成员函数,这里是个对话框CTChartDlg

?

void?CTChartDlg

::ClearAllSeries(

void)?

{

????

for(

long?i?

=?

0;i

++)

????{

????????((CSeries)m_TeeChart.Series(i)).Clear();

????}

}

?

好了如今開始说说怎么画折线图

2.2 普通连线图

一般我们画的图都属于这样的,就是把点连接起来,选择fast line 的 Normal,就是普通连线图

在须要绘图的地方先要获得曲线序列Series,然后通过绘图函数AddXY,或者AddArray作图。

2.2.1 普通线图 - AddXY

以下演示AddXY的方法

AddXY就是一个一个增加点,在点数不多,且须要动态显示的时候是不错的选择。点数多的情况下嘛,那就还是用AddArray了

先看看AddXY

?

? ??

const?

UINT?nDATALENGTH

=?

100;?

????

double?dData[nDATALENGTH];

????

for?(

int?i

=

0;i

++)

????{

????????dData[i]?

=?100 * sin((

float)i)

*cos((

float)

4

*i);

????}

????

//

ClearAllSeries();????CSeries lineSeries?

=?(CSeries)m_TeeChart.Series(

0);

????lineSeries.Clear();

//在最前面加上ClearAllSeries(ClearAllSeries是自己写的函数)就不用了

????

for(

int?i

=

0;i

++)

????{

????????lineSeries.AddXY((

double)i,dData[i],NULL,

0);

????}

因为在TeeChart里,仅仅加了一个FastLine,所以Series(0)就算Fast Line,代码首先获得图像序列m_TeeChart.Series(0);

然后再调用这个序列来作图,作图前先清空图像,用ClearAllSeries()也能够

然后就是一个点一个点的往里加了

做出来的效果:

AddXY的第一个參数是x点坐标,第二个是y点坐标,第三个參数是为了使x坐标特殊显示,这是会替换掉x坐标的显示内容,如我想显示“点xx“能够这样

?

????CString?str;? ????for(int?i=0;i

?

第四个參数在线图里不起作用,在柱状图里能够设置颜色

2.2.2 普通线图 - AddArray

?

在数据量特别大时,强烈建议使用AddArray函数

AddArray的函数声明例如以下

void AddArray(long ArraySize, VARIANT& YArray, VARIANT& XArray);

x,y是两个VARIANT的数据类型,VARIANT有个类型是VT_ARRAY

能够给VARIANT赋一个数组进去

详细操作例如以下:

方法1:

?

const?

UINT

?nDATALENGTH?

=?

100

;?

double

?dData[nDATALENGTH];

for

?(

int

?i

=

0

;i

<

nDATALENGTH;i

++

)

{

?????dData[i]?

=?

100

*

sin((

float

)i)

*

cos((

float

)

4

*

i);

}

//声明例如以下数据:

VARIANT vAX,vAY;

SAFEARRAY*?psax;

SAFEARRAY

*?

psay;

SAFEARRAYBOUND rgsabound;

//初始化

rgsabound.cElements

=

nDATALENGTH;?

rgsabound.lLbound

=

0

;

psax

=

SafeArrayCreate(VT_R8,

1

,

&

rgsabound);

//分配空间

psay

=

SafeArrayCreate(VT_R8,

1

,

&

rgsabound);

vAX.vt

=

VT_ARRAY

|

VT_R8;

//设置为double型数组,VT_R8就是指double

vAX.parray

=

psax;

//把内容增加VARIANT中

vAY.vt

=

VT_ARRAY

|

VT_R8;

vAY.parray

=

psay;

//这时VARIANT 就能够增加数据了

double

?dtemp;

//用来暂时存放x坐标

?

for

(

long

?i

=

0

;i

<

nDATALENGTH;i

++

)

{

????dtemp?

=

?i;

????SafeArrayPutElement(psax,

&

i,

&

dtemp);

????dtemp?

=

?dData[i];

????SafeArrayPutElement(psay,

&

i,

&

dtemp);

????

//更简单写法

????

//SafeArrayPutElement(psay,&i,dData+i);

}

//開始绘图

CSeries lineSeries?

=

?(CSeries)m_TeeChart.Series(

0

);?

lineSeries.Clear();

lineSeries.AddArray(nDATALENGTH,vAY,vAX);

?

?

方法2:

这时我看TeeChart官方实例找到的方法,相对简单点

????COleSafeArray XValues;????

????COleSafeArray YValues;????

????

DWORD?numElements[]?

=?{nDATALENGTH};????

????

// 创建安全数组???

????XValues.Create(VT_R8,?

1, numElements);????

????YValues.Create(VT_R8,?

1, numElements);????

????

// 初始化?

????

long?i;????

????

double?dval;

????

for(i

=

0; i

++)?

????{???????

????????dval?

=?i;

????????XValues.PutElement(

&i,?

&dval);

????????dval?

=?dData[i];

????????YValues.PutElement(

&i,?

&dval);

????????

//YValues.PutElement(&i, dData+i);

????};

????CSeries lineSeries?

=?(CSeries)m_TeeChart.Series(

0);

????lineSeries.Clear();

????lineSeries.AddArray(nDATALENGTH,YValues,XValues);

?

2.3 去除/显示legend

假设不想要右边那一栏数据显示,能够通过代码去除

CLegend是用来控制这个显示的

?

CLegend legend?

=?(CLegend)m_TeeChart.get_Legend();?????

legend.put_Visible(FALSE);

?

能够用一个check控件控制器显示状态

加入单选控件?? ,id为IDC_CHECK_ShowLegend,

单击响应

void?CTChartDlg

::OnBnClickedCheck_ShowLegend()?

{

????CLegend legend?

=?(CLegend)m_TeeChart.get_Legend();

????

if(BST_CHECKED?

==?((

CButton

*)GetDlgItem(IDC_CHECK_ShowLegend))

-

>GetCheck())

????{

????????legend.put_Visible(TRUE);

????}

????

else

????{

????????legend.put_Visible(FALSE);

????}

}

?

效果:

不用代码的话能够通过设置控件属性

明显,这没有代码灵活

?

2.4 改变线图颜色

?

默认设置是红,我要设置成其它颜色能够用put_Colour

?

如上代码的lineSeries最后加一个,就会变成RGB(255,0,255)的颜色了

?

lineSeries.put_Color(RGB(

255,

0,

255));

?

效果:

3. teechart 绘图 - ?柱状图

?

3.1 ?加入柱状图

这时会多一个图形

注意这里默认是绿色的,等下会发现画出来的不一样

3.2 AddXY

?

方法和线图没什么差别,直接上码:

?

????

const?

UINT?nDATALENGTH?

=?

20;?

????

double?dData[nDATALENGTH];

????

for?(

int?i

=

0;i

++)

????{

????????dData[i]?

=?abs(

100

*sin((

float)i));

????}

????

//

????ClearAllSeries();

????CSeries barSeries?

=?(CSeries)m_TeeChart.Series(

1);

????

for(

int?i

=

0;i

++)

????{

?????????????barSeries.AddXY((

double)i,dData[i],NULL,

0);

????}

?

注意不是Series(0)了

我擦~那效果

?

加个abs,好看非常多~~

3.3 改变柱状图的颜色

?

为啥是黑色的?设置了绿色的,我一開始也以为坑爹的设置没实用,后来研究了一下发现时AddXY的第四个參数起作用的

?

上面的图我们是这样加的

barSeries.AddXY((double)i,dData[i],NULL,0);

?

第四个參数0就相当于RGB(0,0,0),这第四个參数就是设置颜色的了

?

把程序稍作改动

?

????

for(

int?i

=

0;i

++)?

????{

????????i

%

2

==?

0

????????????

??barSeries.AddXY((

double)i,dData[i],NULL,RGB(

255,

255,

0))

????????????

:?barSeries.AddXY((

double)i,dData[i],NULL,RGB(

0,

255,

255));

????}

牛x

3.4 去除/显示 数据标示

?

好吧又遇到问题了,去掉上面的标示

ok,那个标示是用CMarks管理的,增加这个类即可了,用类向导,增加CMarks

#include "CMarks.h"

加入单选控件??IDC_CHECK_Marks

?

void?CTChartDlg

::OnBnClickedCheckMarks()?

{

????CSeries barSeries?

=?(CSeries)m_TeeChart.Series(

1);

????CMarks SeriesMarks?

=?(CMarks)barSeries.get_Marks();

????

if(BST_CHECKED?

==?((

CButton

*)GetDlgItem(IDC_CHECK_Marks))

-

>GetCheck())

????{

????????SeriesMarks.put_Visible(TRUE);

????}

????

else

????{

????????SeriesMarks.put_Visible(FALSE);

????}

}

?

效果:

3.5 AddArray 给柱状图加入数据

和line一样

????

const?

UINT?nDATALENGTH?

=?

20;?

????

double?dData[nDATALENGTH];

????

for?(

int?i

=

0;i

++)

????{

????????dData[i]?

=?abs(

100

*sin((

float)i));

????}

????COleSafeArray XValues;????

????COleSafeArray YValues;????

????

DWORD?numElements[]?

=?{nDATALENGTH};????

????

// 创建安全数组???

????XValues.Create(VT_R8,?

1, numElements);????

????YValues.Create(VT_R8,?

1, numElements);????

????

// 初始化?

????

long?i;????

????

double?dval;

????

for(i

=

0; i

++)?

????{???????

????????dval?

=?i;

????????XValues.PutElement(

&i,?

&dval);

????????dval?

=?dData[i];

????????YValues.PutElement(

&i,?

&dval);

????????

//YValues.PutElement(&i, dData+i);

????};

????

//

????ClearAllSeries();

????CSeries lineSeries?

=?(CSeries)m_TeeChart.Series(

1);

????lineSeries.AddArray(nDATALENGTH,YValues,XValues);

?

这时出现的图像就是默认的颜色了

想改颜色!没问题,还是用put_Color

?

barSeries.put_Color(RGB(

255,

0,

0));

返回顶部