WPF开发随笔收录-心电图曲线绘制
一、前言
项目中之前涉及到胎儿心率图曲线的绘制,最近项目中还需要添加心电曲线和血样曲线的绘制功能。今天就来分享一下心电曲线的绘制方式;
二、正文
1、胎儿心率曲线的绘制是通过DrawingVisual来实现的,这里的心电曲线我也是采用差不多相同的方式来实现的,只是两者曲线的数据有所区别。心电图的数据服务器端每秒发送至客户端一个数据包,一个数据包钟心电的数据大概一百个左右,看过心电图的应该知道,心电图的效果是匀速绘制出来的,而不是一次性将一百个点绘制出来;项目中是通过将数据存到数据缓冲区,然后通过线程定时推送数据到绘图端,线程里会根据缓冲区现有数据量来动态控制数据的快慢;这里的例子我就直接通过定时推数据来直接演示如何实现;
2、新建个项目,添加一个类继承FrameworkElement,然后加上对应的数据接收和绘制功能,这里直接贴出所有代码,具体细节之前写绘制高性能曲线时写过了,不清楚的可以参考之前的;(实际上绘图部分用Canvas实现也可以,用DrawingVisual其实每次推送了一个数据,整个视图都重新绘制了,我之所以用这个是因为我要支持自动缩放功能)
public class EcgDrawingVisual : FrameworkElement
{
private readonly List<Visual> visuals = new List<Visual>();
private DrawingVisual Layer; private Pen ecg_pen = new Pen(Brushes.Orange, 1.5); private int?[] ecg_points = new int?[2000]; private int currentStart = 0; private double y_offset = 0; private int ecg_max = 60;
private int ecg_min = -25; public EcgDrawingVisual()
{
ecg_pen.Freeze(); Layer = new DrawingVisual();
visuals.Add(Layer);
} public void SetupData(int ecg)
{
ecg_points[currentStart] = ecg;
for (int i = 1; i <= 20; i++)
{
ecg_points[currentStart + i] = null;
} currentStart++;
if (currentStart >= RenderSize.Width / 2)
{
currentStart = 0;
} DrawEcgLine();
InvalidateVisual();
} private void DrawEcgLine()
{
var scale = RenderSize.Height / (ecg_max - ecg_min);
y_offset = ecg_min * -scale; DrawingContext dc = Layer.RenderOpen();
Matrix mat = new Matrix();
mat.ScaleAt(1, -1, 0, RenderSize.Height / 2);
dc.PushTransform(new MatrixTransform(mat)); for (int i = 0, left = 0; left < RenderSize.Width; i++, left += 2)
{
if (ecg_points[i] == null || ecg_points[i + 1] == null) continue;
dc.DrawLine(ecg_pen, new Point(left, ecg_points[i].Value * scale + y_offset), new Point(left + 2, ecg_points[i + 1].Value * scale + y_offset));
} dc.Pop();
dc.Close();
} protected override int VisualChildrenCount => visuals.Count;
protected override Visual GetVisualChild(int index)
{
return visuals[index];
} protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
base.OnRenderSizeChanged(sizeInfo);
} protected override void OnRender(DrawingContext drawingContext)
{
drawingContext.DrawRectangle(Brushes.White, null, new Rect(0, 0, RenderSize.Width, RenderSize.Height));
base.OnRender(drawingContext);
}
}
3、主界面添加这个控件,然后后台添加对应的推送数据的线程,这里我是定时每隔十毫秒推送一个数据给到绘图端。
public partial class MainWindow : Window
{
private List<int> points = new List<int>() { 4, 4, 3, -1, -2, -2, -2, -2, -2, -2, -2, -2, -4, -3, 25, 37, 8, -7, -5, -3, -3, -3, -3, -3, -3, -3, -3, -2, -2, -2, -1, -1, 3, 5, 8, 9, 9, 10, 9, 7, 5, 1, -1, -4, -4, -4, -4, -4, -4, -4, -3, -3, -3, -3, -3, -3, -3, -3, -3, -2, -2, -2, -2, -2, -2, -1, 1, 3 };
private bool flag = true;
private int currentIndex = 0; public MainWindow()
{
InitializeComponent(); new Thread(() =>
{
while (flag)
{
Thread.Sleep(10);
this.Dispatcher.BeginInvoke(new Action(() =>
{
if (currentIndex == points.Count) currentIndex = 0;
ecgDrawingVisual.SetupData(points[currentIndex]);
currentIndex++;
}));
}
}).Start();
} protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
flag = false;
}
}
4、最终实现效果


WPF开发随笔收录-心电图曲线绘制的更多相关文章
- WPF开发随笔收录-WriteableBitmap绘制高性能曲线图
		
一.前言 之前分享过一期关于DrawingVisual来绘制高性能曲线的博客,今天再分享一篇通过另一种方式来绘制高性能曲线的方法,也就是通过WriteableBitmap的方式:具体的一些细节这里就不 ...
 - WPF开发随笔收录-DrawingVisual绘制高性能曲线图
		
一.前言 项目中涉及到了心率监测,而且数据量达到了百万级别,通过WPF实现大数据曲线图时,尝试过最基础的Canvas来实现,但是性能堪忧,而且全部画出来也不实际.同时也尝试过找第三方的开源库,但是因为 ...
 - WPF开发随笔收录-仿安卓Toast
		
一.前言 在项目中,经常需要用到消息提醒功能,在以前接触安卓开发那会使用过Toast,于是打算在WPF上也来模仿一个,话不多说,撸起袖子干起来! 二.正文 1.首先新建一个工程,工程的目录如下 2.编 ...
 - WPF开发随笔收录-ScrollViewer滑块太小解决方案
		
一.前言 在WPF开发过程中,ScrollViewer是一个很常使用到的控件,在自己工作的项目中,收到一个反馈就是当ScrollViewer里面的内容太长时,滚动条的滑块就会变得很小,然后导致点击起来 ...
 - WPF开发随笔收录-唯一标识符GUID
		
一.前言 该系列博客用于记录本人在WPF开发过程中遇到的各种知识点 二.正文 1.在工作的项目中,软件需要用到在线升级功能,由于第一次弄,在下载服务端的文件到本地时,文件的名称我选择直接生成为固定的格 ...
 - WPF开发随笔收录-获取软件当前目录的坑
		
一.唠唠叨叨 软件开发过程中,经常需要使用到获取exe当前目录这个功能,前同事在实现这个需求时使用的是Directory.GetCurrentDirectory()这个方法,但再最近的测试中,突然发现 ...
 - WPF开发随笔收录-DataAnnotations实现数据校验(MVVM架构下)
		
一.前言 在自己的项目中挺多地方需要涉及到数据验证的,初期的实现方式都是通过点击确定后再逐个验证数据是否符合要求,但这种方式会让后台代码变得很多很乱.于是就开始在网上需求好的解决方式,刚好看到了一个大 ...
 - WPF开发随笔收录-报警闪烁效果实现
		
一.前言 工作中目前经手的项目是医疗相关的监护软件,所以会涉及到一些报警效果的实现,今天在这里就简单分享一下实现方式 二.正文 1.实现的方式比较的简单,就是通过一个Border控件,然后搭配Data ...
 - WPF开发随笔收录-带递增递减按钮TextBox
		
一.前言 今天分享一下如何实现带递增递减按钮的TextBox控件 二.正文 1.之前的博客分享了一篇自定义XamlIcon控件的文章,这次就直接在那个项目的基础上实现今天这个自定义控件 2.首先添加两 ...
 
随机推荐
- Java 从零开始实现一个画图板、以及图像处理功能,代码可复现
			
Java 从零开始实现一个画图板.以及图像处理功能,代码可复现 这是一个学习分享博客,带你从零开始实现一个画图板.图像处理的小项目,为了降低阅读难度,本博客将画图板的一步步迭代优化过程展示给读者,篇幅 ...
 - 【原创】记一次DouPHP站点的RCE实战之旅
			
声明 本次实践是在合法授权情况下进行,数据已经全部脱敏,主要是提供思路交流学习,请勿用于任何非法活动,否则后果自负. 实战记录 信息收集 1,踩点站点 通过fofa 查到目标DouPHP框架该站点(也 ...
 - Java语言学习day03--6月30日
			
今日内容介绍 1.变量 2.运算符 ###01变量概述 * A: 什么是变量? * a: 变量是一个内存中的小盒子(小容器),容器是什么?生活中也有很多容器,例如水杯是容器,用 ...
 - java高级用法之:JNA类型映射应该注意的问题
			
目录 简介 String Buffers,Memory,数组和Pointer 可变参数 总结 简介 JNA提供JAVA类型和native类型的映射关系,但是这一种映射关系只是一个大概的映射,我们在实际 ...
 - node.js - mysql
			
今天结束的挺早,因为今天的内容还可以不是很难,今天全程是学了一些关于mysql数据库和sql查询语句的内容包括在node终端里面怎么来连接数据库.经过今天的一个学习,我感觉离那个地步越来越近了,就是那 ...
 - XCTF练习题---MISC---3-11
			
XCTF练习题---MISC---3-11 flag:FLAG{LSB_i5_SO_EASY} 解题思路: 1.观察题目,下载附件 2.下载后是一张图片,根据习惯直接Stegsolve打开查看 3.通 ...
 - vue  列表过滤和排序
			
<body> <div id="root"> <h1>员工列表</h1> <input type="text&quo ...
 - 使用 Ansible 快速部署 HBase 集群
			
背景 出于数据安全的考虑,自研了一个低成本的时序数据存储系统,用于存储历史行情数据. 系统借鉴了 InfluxDB 的列存与压缩策略,并基于 HBase 实现了海量存储能力. 由于运维同事缺乏 Had ...
 - 「BUAA OO Unit 2 HW8」第二单元总结
			
「BUAA OO Unit 2 HW8」第二单元总结 目录 「BUAA OO Unit 2 HW8」第二单元总结 Part 0 前言 Part 1 第五次作业 1.1 作业要求 1.2 架构设计 1. ...
 - java基础4.18
			
1.java的"一次编写,处处运行"如何实现?: 答:java之所有能实现一次编译,到处运行,是因为java在每个系统平台上都有java虚拟机(jvm),java编译的中间文件cl ...