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));