在WPF中使用Scottplot 实现波形展示

这篇具有很好参考价值的文章主要介绍了在WPF中使用Scottplot 实现波形展示。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

上位机开发过程中,信号数据是最常遇到的,在采集到信号数据后,如果能更好的展示成了难题。刚好最近接手了一个脑电信号数据的采集的项目,需要实时采集脑电信号并以波形展示出来。经过一番调研,网上有不少开源的图形控件用于波形的展示,比如oxyplot,scottplot,livecharts等,在尝试后发现oxyplot采用MVVM设计,非常符合WPF的开发,Scottplot比较符合Winform的开发,而且接口也比较奇怪,livecharts绘图特别漂亮,但有性能问题,比如绘制大数据点时会特别卡。经过详细调研后决定使用Scottplot来实现,理由下面会说。

环境

运行环境:.Net 6
开发环境:VS2022 17.1

为什么选择Scottplot

我们知道波形图由坐标轴来绘制,需要横坐标和纵坐标,像脑电数据,跟采集频率有关,即横坐标是时间递增的,而Scottplot专门为这种横坐标递增的设计了一种波形:Signal Plot(信号图),信号图具有均匀分布的 Y 点。信号图非常快,可以交互显示数百万个数据点。有许多不同类型的可绘制对象,每种都有不同的用途。在实际使用中,只需要将数据以double的数组传进去就行,再设置频率,即可自动生成相应的波形,这对于需要高频采集数据并展示在坐标轴上是非常方便的。

使用

通过NuGet安装
在WPF中使用Scottplot 实现波形展示
Scottplot的使用可能与WPF的MVVM模式不太适应,官方也不推荐使用MVVM的方式来实现,就直接在后端加载就行。最终效果如图(8KHz的实时采集波形):
在WPF中使用Scottplot 实现波形展示
因为上手非常简单,而且官方教程里也有非常多的案例,具体的使用可以参考官方教程及Demo
我这里主要说一下遇到的问题吧:

图例

官方提供的图例非常简单,而且不支持点击某个图例对该波形的显示与隐藏,上图中,我是自己实现的,并不包括在坐标轴内。需要注意的是在初始化的时候,初始化一个ScottPlot.Plottable.SignalPlot代表一条折线。这也是上面说的,SDK接口使用比较奇怪的地方。

ScottPlot.Plottable.SignalPlot signalPlot=this.wpfPlot.Plot.AddSignal(data,freq,color);
//自定义图例控制折线的显示与隐藏
signalPlot.IsVisible=true;
this.wpfPlot.Render();

对,每次对图表更新后记得调用Render(),另外还有一个Refresh()也是可以刷新图表的。

十字线

鼠标移到坐标轴后以十字线显示当前点的坐标,这里需要在MosuMove事件中进行相应的数据处理

ScottPlot.Plottable.Crosshair Crosshair=this.wpfPlot.Plot.AddCrosshair(0, 0);
private void wpfPlot_MouseMove(object sender, MouseEventArgs e)
        {
            int pixelX = (int)e.MouseDevice.GetPosition(wpfPlot).X;
            int pixelY = (int)e.MouseDevice.GetPosition(wpfPlot).Y;

            (double coordinateX, double coordinateY) = wpfPlot.GetMouseCoordinates();

            //XPixelLabel.Content = $"{pixelX:0.000}";
            //YPixelLabel.Content = $"{pixelY:0.000}";

            txtX.Text = $"{wpfPlot.Plot.GetCoordinateX(pixelX):0.00}";
            txtY.Text = $"{wpfPlot.Plot.GetCoordinateY(pixelY):0.00}";

            Crosshair.X = coordinateX;
            Crosshair.Y = coordinateY;

            wpfPlot.Refresh();
        }

这里需要注意的是如果你的横坐标或者纵坐标的值并不是数组中的值 ,而是经过计算过的值时,则需要进行相应的计算后才能显示正确的值。

自动计算坐标轴

在使用过程中为了展示一段指定时间范围内的波形,需要保证整个波形都在坐标轴内,此时需要将这一段时间范围内的最大Y值和最小Y值计算出来,然后划分成若干段显示在Y轴上。如果数据不需要经过计算,可以直接使用下面的方式实现。

this.wpfPlot.Plot.AxisAutoY();

如果经过计算,则需要对坐标轴进行格式化TickLabelFormat

this.wpfPlot.Plot.XAxis.TickLabelFormat(customTickFormatter);

private string customTickFormatter(double position)
        {
            double res;
            if (_currentIndex > _showCount)
                res = (double)(_currentIndex - _showCount + position) /(double)_currentFreq;
            else
                res = position/ (double)_currentFreq;
            return res.ToString("F2");
        }
泛型的问题

这个控件目前只能传入double[]的数组,实时采集过程中是不知道数组的长度的,如果对于未知数组长度最好是使用List,官方说明

List<double> originalData = new List<double>() {5, 2, 7, 4, 9, 5};
double[] myData = originalData.ToArray();
signalPlot.AddSignal(myData );

但此时如果你往originalData 里增加数据,会发现坐标轴并不会变化,因为赋值的过程是将myData数组赋值给signalPlot的Ys属性,Ys属性是一个T[] Ys,这就很尴尬了,一旦将数组赋值后,就无法对其增加长度或者重新赋值了,换句话说:不支持长度可变的数据。

如何解决大数据量的实时采集

虽然官方说可以展示百万数据点,但实际测试发现,超过100万点的时候就会变得非常卡了,这个跟计算机的性能有关,毕竟100万点实际就是一个100万长度的数组中的数据渲染在坐标轴上。而且实时采集过程是需要让信号波在坐标轴上动态展示,比如向屏幕左侧偏移,这里需要解决的是数据实时加载到数组里,同时将波形往左偏移指定数据长度。有两种方案实现:
1、先定义一个非常长的数组,坐标轴上只显示10000个数据点,然后采集过程中,数据实时填充到坐标轴中,通过控制X轴的最小值和最大值来平移坐标轴

signalPlot.MinRenderIndex=min;
signalPlot.MaxRenderIndex=max;

这个方案有一个问题就是,在一开始采集的时候,并不知道具体的数组长度,而且并不支持泛型List,所以为了下标不越界,需要定义一个特别大的数组。
2、先定义一个固定长度的数组,比如10000,坐标轴上也只显示10000个数据点,采集过程中将新的数据点填充到数组里,超过10000之后将数组整体前移一位,同时将新的数据点赋值给数组最后一位

            Array.Copy(liveData, 1, liveData, 0, liveData.Length - 1);
            liveData[liveData.Length - 1] = nextValue;

这个方案可以非常好的控制对计算机资源的占用,而且能做到不卡顿,非常稳定的采集数据,我选用的是这个方案。

结论

以上就是目前使用该图形控件遇到的若干问题,希望能帮助各位读者,而且这个控件在国内使用的较少,很难找到比较全的资料。在实际使用中,测试该控件还是非常稳健的,大量数据点都能较好的显示,而且性能方面也较好,以上就是我个人对Scottplot的使用心得,如果有不正确的还望指出。
另外,官方目前已经有V5预览版本了,据说该版本有较大的升级。文章来源地址https://www.toymoban.com/news/detail-412511.html

到了这里,关于在WPF中使用Scottplot 实现波形展示的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • WPF上位机7——MySql

    db操作、表操作 字段的数据类型 修改表 表的数据操作 数据查询和去重查询 条件查询 模糊查询 聚合查询 分组查询 排序查询 分页查询 字符串处理函数 数值函数 日期函数 流程函数 外键约束 内连接 外连接 自连接 子查询 列子查询 行子查询 表子查询

    2024年02月14日
    浏览(37)
  • python pyaudio实时读取音频数据并展示波形图

    下面代码可以驱动电脑接受声音数据,并实时展示音波图:

    2024年02月19日
    浏览(37)
  • C# WPF上位机开发(键盘绘图控制)

    【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】         在软件开发中,如果存在canvas图像的话,一般有几种控制方法。一种是鼠标控制;一种是键盘控制;还有一种是定时器控制。定时器控制,多常见动画、游戏、3d视频当中。而鼠标控制

    2024年02月02日
    浏览(41)
  • 工业上位机开发实战 WPF + MVVM 框架

    上一篇博客介绍了上位机实现MVVM 框架的步骤 MVVMtoolkit 学习_叮当说的博客-CSDN博客 下面我们继续来讲解下实现上位机中会遇到的一些小问题: 回顾: 之前的程序中我们已经知道了 ,当数据改变的时候,可以使用通知的方法来来告知其他的模块这样便可以实现多个界面的通

    2024年02月04日
    浏览(42)
  • WPF上位机9——Lambda和Linq

    2024年02月14日
    浏览(35)
  • C# WPF上位机开发(Web API联调)

    【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】         很多时候,客户需要开发的不仅仅是一个上位机系统,它还有其他很多配套的系统或设备,比如物流小车、立库、数字孪生等一整套系统。这个时候,上位机系统就需要和各个子系统

    2024年01月20日
    浏览(42)
  • C#+WPF上位机开发(模块化+反应式)

    在上位机开发领域中,C#与C++两种语言是应用最多的两种开发语言,在C++语言中,与之搭配的前端框架通常以QT最为常用,而C#语言中,与之搭配的前端框架是Winform和WPF两种框架。今天我们主要讨论一下C#和WPF这一对组合在上位机开发过程中的实际应用。 一、模块化概念 开发

    2024年02月14日
    浏览(35)
  • C#上位机与欧姆龙PLC的通信12----【再爆肝】上位机应用开发(WPF版)

    继上节完成winform版的应用后,今天再爆肝wpf版的,看看看。 可以看到,wpf的确实还是漂亮很多,现在人都喜欢漂亮的,颜值高的,现在是看脸时代,作为软件来说,是交给用户使用的,UI自然是要讲究,可以看出,wpf比winform漂亮多了,因为wpf使用样式css来美化界面,虽然这

    2024年01月16日
    浏览(46)
  • C# winform使用scottplot图表控件快速入门设置XY轴缩放

    Hello大家好我是开箱测评小汪,在C#项目开发中使用图表控件,有时候我们希望放大或缩小图表控件来看数据细节和整体数据情况。所有本期课程将带介绍Scottplot图表控件如何来实现这个功能。   本期课程的要达到的目的: 设置鼠标管轮缩放进行缩放 设置鼠标右键长按进行拖

    2024年02月15日
    浏览(51)
  • WPF应用开发之控件动态内容展示

    在我们开发一些复杂信息的时候,由于需要动态展示一些相关信息,因此我们需要考虑一些控件内容的动态展示,可以通过动态构建控件的方式进行显示,如动态选项卡展示不同的信息,或者动态展示一个自定义控件的内容等等,目的就是能够减少一些硬编码的处理方式,以

    2024年02月05日
    浏览(60)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包