欢迎访问 Lu程序设计

在Lu脚本中绘制普通XY图(折线图)

目  录

1 基础知识 绘制普通XY图的基础知识。
2 绘制多条函数曲线 需要自己双击窗口,或者单击右键,弹出菜单设置曲线的各种属性。
3 绘制多条函数曲线并用代码设置部分属性 多次绘制同一图形时,用代码设置属性是方便的。
4 用键盘动态改变绘图范围 ←:向左移动;→:向右移动;↑:范围扩大;↓:范围缩小;Home:复原。
5 多线程交互动态显示数据 可用于数据的动态采集及显示。
6 由内部计时器控制的动画 可用于动态显示函数图形。
7 设置XY坐标轴范围与数据范围相同 设置X坐标轴或Y坐标轴范围与数据范围相同,不向两端扩展。
8 绘制散点图或者设置曲线点标记 绘制散点图或者设置曲线点标记。
   

1 基础知识

    普通XY图是最常用的2D图形,绘制普通XY图的程序结构如下:

!!!using("win","math");   //使用命名空间win和math。win是必须的,而math是多数情况下要用到的。
init(... ...) =          
//定义初始化函数init,函数参数根据需要设置。
{
  cwAttach(
typeXY),       //函数cwAttach用于设置图像类型,typeXY表示普通XY图。参数typeXY可以缺省,另外函数cwAttach也可以缺省,默认都是普通XY图。
  ... ...                
//添加初始化数据或属性。
};
ChartWnd[@init];         
//显示窗口并调用函数init进行初始化。

    由于图形数据多是数组形式,故需要学习几个来自命名空间math的数学函数 ,这些函数在绘制其他类型图像时也经常用到:

    linspace(a,b,n)或者linspace(a,b,x):该函数产生一个一维数组。a、b、x为实数,n为整数。a和b是数组的第一个和最后一个元素,元素总数是n。或者,a是第一个元素,后面的元素按x递增,最后一个元素不超过b。

    ra1[2, 3.5, -5]:该函数申请一维数组并初始化。

    matrix(m,n:x11,x12,... ...)或者matrix(str):申请m×n矩阵并初始化。

    m,n:矩阵的行和列。初始化数据 x11,x12,...,x1n,x21,x22,...,x2n,... ...,xm1,xm2,...,xmn 可以缺省部分及全部,多余的数据被忽略。
    str:字符串,包含矩阵数据,数据之间可以用空格或逗号分隔。此时,将自动确定矩阵的行和列。例如以下是一个2×3矩阵字符串:

"1    1.2  3,
 2.2  3,   5"

2 绘制多条函数曲线

!!!using("win","math");
init(x,k) =
{
  x=
linspace[-8.0, 8.0, 0.2],
  k=len(x),                    
//函数len可获得x的长度
  cwAddCurve{x, sin(x), k},
  cwAddCurve{x, x-sin(x), k},
  cwAddCurve{x, x.*sin(x), k}
};
ChartWnd[@init];

    作为重要的练习,你可以通过双击窗口,或者单击右键,弹出菜单设置曲线的各种属性如下图的样式:

3 绘制多条函数曲线并用代码设置部分属性

!!!using("win","math");
init(x,k,k1,k2,k3) =
{
  x=
linspace[-8.0, 8.0, 0.2],
  k=len(x),
  k1=cwAddCurve{x, sin(x), k},
             //函数cwAddCurve返回曲线的idData(曲线的唯一标识)
  k2=cwAddCurve{x, x-sin(x), k},
  k3=cwAddCurve{x, x.*sin(x), k},
 
cwSetTitle["自动设置绘图属性的例子"],     //设置主标题。
 
cwSetUseLegend(true),                   //使用图例
  cwSetDataTitle["曲线1",cwGetIndex(k1)],
//函数cwSetDataTitle设置图例,函数cwGetIndex从曲线的idData(曲线的唯一标识)获得曲线的序号nIndex(序号是连续的)
  cwSetDataTitle["曲线2",cwGetIndex(k2)],
  cwSetDataTitle["曲线3",cwGetIndex(k3)],
  cwSetAxisTitle("X轴", 1), cwSetAxisTitle("Y轴", 0),
//设置坐标轴标题
  cwSetGridLine[true,true,true,true]
      //显示网格
};
ChartWnd[@init];

4 用键盘动态改变绘图范围

!!!using("win","math");
//设置一些初值:x0Min和x0Max为X轴范围的原始值;xMin和xMax为X轴范围的当前值;kMax是绘图点数;inc是X轴范围发生变化时的增量。这些参数都是模块变量。
初值(::x0Min, x0Max, xMin, xMax, kMax, inc)= x0Min=-8.0, x0Max=8.0, xMin=x0Min, xMax=x0Max, kMax=100, inc=0.5;
f(x)=sin(x);   
//定义一元函数
g(x)=x-sin(x); 
//定义一元函数
h(x)=x.*sin(x);
//定义一元函数
home(x::x0Min, x0Max, xMin, xMax, kMax) =
//用户按Home键时调用的函数
{
 
cwAttach(typeXY), cwClearData(), //函数cwClearData用于重置数据为默认值
  xMin=x0Min, xMax=x0Max,
  x=
linspace[xMin, xMax, kMax],
  cwAddCurve{x, f(x), kMax}, cwAddCurve{x, g(x), kMax}, cwAddCurve{x, h(x), kMax}
};
left(x::xMin, xMax, kMax, inc) =
   //用户按←键时调用的函数
{
  cwAttach(
typeXY), cwClearData(),
  xMin=xMin-inc, xMax=xMax-inc,
  x=
linspace[xMin, xMax, kMax],
  cwAddCurve{x, f(x), kMax}, cwAddCurve{x, g(x), kMax}, cwAddCurve{x, h(x), kMax}
};
right(x::xMin, xMax, kMax, inc) =
  //用户按→键时调用的函数
{
  cwAttach(
typeXY), cwClearData(),
  xMin=xMin+inc, xMax=xMax+inc,
  x=
linspace[xMin, xMax, kMax],
  cwAddCurve{x, f(x), kMax}, cwAddCurve{x, g(x), kMax}, cwAddCurve{x, h(x), kMax}
};
up(x::xMin, xMax, kMax, inc) =
    //用户按↑键时调用的函数
{
  cwAttach(
typeXY), cwClearData(),
  xMin=xMin-inc, xMax=xMax+inc,
  x=
linspace[xMin, xMax, kMax],
  cwAddCurve{x, f(x), kMax}, cwAddCurve{x, g(x), kMax}, cwAddCurve{x, h(x), kMax}
};
down(x::xMin, xMax, kMax, inc) =
   //用户按↓键时调用的函数
{
  cwAttach(
typeXY), cwClearData(),
  xMin=xMin+inc, xMax=xMax-inc,
  which{xMin>xMax : [x=xMin, xMin=xMax, xMax=x], xMin==xMax : [xMin=-inc, xMax=inc], 0},
//which语句保证了参数xMin和xMax的合理性
  x=
linspace[xMin, xMax, kMax],
  cwAddCurve{x, f(x), kMax}, cwAddCurve{x, g(x), kMax}, cwAddCurve{x, h(x), kMax}
};
init(x)=
  cwSetVKFor[
VK_HOME, @home], //cwSetVKFor用于设置虚拟键调用函数。本例中,用户按Home键时调用函数home,@表示取函数的地址。下同。
  cwSetVKFor[
VK_LEFT, @left], cwSetVKFor[VK_RIGHT, @right], cwSetVKFor[VK_UP, @up], cwSetVKFor[VK_DOWN, @down],
  home[0];
                    //初始化时先调用一次函数home,参数0实际上可为任意值。
ChartWnd[@init];

    下图是连续按←、→、↓、↑、Home时获得的图形:

5 多线程交互动态显示数据

    在OpenLu代码窗口,粘贴以下代码,然后执行 菜单->计算->编译为临时模块并执行。该临时模块可通过 菜单->工具->模块管理->模块类型->临时模块:在主窗口中编译的临时模块 查看。

!!!using("win","math");
//定义全局函数AddPlot,用于设置向曲线k添加数据点(x,y)。该函数可在其他线程中调用。
:::AddPlot(x,y,k::xx,yy,kk)= xx=x, yy=y, kk=k, cwSetExeMsg(); //函数cwSetExeMsg用于发送执行消息。
ShowAdd(::xx,yy,kk)= cwAddPoint2D(xx,yy,kk);
//函数cwAddPoint2D用于向曲线kk添加数据点(xx,yy)。
init() = cwSetExe[@ShowAdd];                
//cwSetExe设置了函数ShowAdd,该函数可通过cwSetExeMsg发送消息执行。
ChartWnd[@init];

    此时,我们看到打开了一个空窗口ChartWnd,里面什么也没有,如下图:

    在OpenLu代码窗口,粘贴以下代码并运行:

AddPlot[0.0, 1.0, 0]; //使用我们自定义的全局函数AddPlot向曲线0发送一个数据点(0.0, 1.0)。

    观察窗口ChartWnd里发生了什么?然后仍在OpenLu代码窗口,粘贴以下代码并运行:

AddPlot[1.0, 1.5, 0]; //使用我们自定义的全局函数AddPlot向曲线0发送一个数据点(1.0, 1.5)。

    我们再用函数AddPlot依次发送以下数据,每次发送注意观察窗口ChartWnd里发生的变化:

[1.5, 2.5, 0]、[2.0, 2.0, 0]、[2.5, -1.0, 0]、[3.0, 1.0, 0]  //曲线0的数据
[1.5, -.5, 1]、[2.0, 2.0, 1]、[2.5,  1.0, 1]、[3.0, 1.5, 1]
 //曲线1的数据

    最终的图形如下图:

    好了,这有什么用呢?假如Lu系统中有一个数据采集线程(例如串口采集模块),它每采集一组数据,就可以通过函数AddPlot发送到ChartWnd窗口进行显示。嗯,以后Lu系统中必将加入这样的数据采集模块!

6 由内部计时器控制的动画

!!!using("win","math");
f(x : max, static, k)=
     //关键字static指出后面的k是一个静态变量,静态变量总是初始化为0。
{
  max=500,
  x=linspace[-9.0, 9.0, max],
  cwClearData(), cwAddCurve[x.*sin(x), x.*cos(x).^2.0, ++k%(max+1)]
  //++k%(max+1)中的运算符%表示求模
};
//函数cwSetTimer设置了一个通过计时器触发调用的函数f;每隔100毫秒调用一次;true表示立即启动定时器,否则要通过 菜单->设置->计时器设置 来启动。
init(x)= cwSetTimer[@f, 100, true];

ChartWnd[@init];

7 设置XY坐标轴范围与数据范围相同

!!!using("win","math");
init(x,k) =
{
  x=
linspace[-8.0, 8.0, 0.2],
  k=len(x),
  cwAddCurve{x, sin(x), k},
  cwAddCurve{x, x-sin(x), k},
  cwAddCurve{x, x.*sin(x), k},
  cwSetExactXRange[true],
      //设置X坐标轴范围与数据范围相同,不向两端扩展。
  cwSetExactYRange[true]
      //设置Y坐标轴范围与数据范围相同,不向两端扩展。
};
ChartWnd[@init];

    比较一下下面的图与前面的图有什么不同:

8 绘制散点图或者设置曲线点标记

!!!using("win","math");
init(x,k,k1,k2) =
{
  x=linspace[-8.0, 8.0, 0.5],
  k=len(x),
  k1=cwAddCurve{x, sin(x), k},
  cwSetScatter[cwGetIndex(k1)],
          //绘制k1曲线为散点图
  k2=cwAddCurve{x, x-sin(x), k},
  cwSetMarkerShow[true,cwGetIndex(k2)],
  //显示k2曲线的标记
  cwSetMarkerFreq[1,cwGetIndex(k2)],
     //设置k2曲线的标记频率为1,即对每个点都进行标记
  cwAddCurve{x, x.*sin(x), k}
};
ChartWnd[@init];

 

 


版权所有© Lu程序设计 2002-2013,保留所有权利
E-mail: forcal@sina.com
  QQ:630715621
最近更新: 2014年02月15日