WPF 实现心电图曲线绘制

本文经原作者授权以原创方式二次分享,欢迎转载、分享。

原文作者:流浪g

原文地址:https://www.cnblogs.com/cong2312/p/16411637.html

一、前言

  • 项目中之前涉及到胎儿心率图曲线的绘制,最近项目中还需要添加心电曲线和血样曲线的绘制功能。今天就来分享一下心电曲线的绘制方式;

二、正文

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)最终实现效果;

7dddfb2d9fd6dd0c4bf2450ec43388e5.gifc3d4510ff340e75ccd6e9735e479c7cc.gif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/285507.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言试题110之利用条件运算符的嵌套来完成此题:学习成绩大于等于90分的同学用 A 表示,60到89 分之间的用 B 表示, 60 分以下的用 C 表示。

✅作者简介:大家好我是码莎拉蒂,CSDN博客专家🥇🥇🥇 📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 1、题目 题目:C语言试题110之利用条件运算符的嵌套来完成此题:学习成绩大于等于90分的同学用 A 表…

如何让 Dapper 支持 DateOnly 类型

前言在上次的文章中&#xff0c;我们让 EF Core 6 支持了 DateOnly 类型。那么&#xff0c;Dapper 是否支持 DateOnly 类型呢&#xff1f;public class User {public int Id { get; set; }public string Name { get; set; }public DateOnly Birthday { get; set; } }using (var…

VB常用内部函数大全一览表(建议收藏)

VB提供了大量的内部函数供用户在编程时调用。内部函数按其功能分为数学运算函数、字符串函数、转换函数、日期与时间函数、判断函数和格式输出函数等。 文章目录 算术函数字符串函数日期和时间函数数据类型转换函数算术函数 字符串函数 日期和时间函数

数据库分类介绍

在当今的互联网中&#xff0c;最常见的数据库模型主要是两种&#xff0c;即“关系型数据库”和“非关系型数据库”。 一、关系型数据库 1、关系型数据库的由来 虽然网状数据库和层次数据库已经很好的解决了数据的集中和共享问题&#xff0c;但是在数据库独立性和抽象级别上扔有…

记一次 .NET 某物管后台服务 卡死分析

一&#xff1a;背景 1. 讲故事这几个月经常被朋友问&#xff0c;为什么不更新这个系列了&#xff0c;哈哈&#xff0c;确实停了好久&#xff0c;主要还是打基础去了&#xff0c;分析 dump 的能力不在于会灵活使用 windbg&#xff0c;而是对底层知识有一个深厚的理解&#xff0c…

C语言试题111之 s=a+aa+aaa+aaaa+aa...a 的值,其中 a 是一个数字。例如 2+22+222+2222+22222(此时 共有 5 个数相加),几个数相加有键盘控制。

✅作者简介:大家好我是码莎拉蒂,CSDN博客专家🥇🥇🥇 📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 1、题目 题目: s=a+aa+aaa+aaaa+aa…a 的值,其中 a 是一个数字。例如 2+22+222+2222+22222(此时 共…

MathType插入带序号公式的两种方法

方法一&#xff1a; 由于我之前使用表格15% 70% 15%来布局的&#xff0c;所以最开始相的就是如何录入公示后插入公式序号&#xff0c;如下图所示 先设置序号格式 录好公式后点“Insert Number”就好了&#xff0c;这样的话需要紧挨着公式&#xff0c;用空格把他空到最右侧就好了…

【系统设计】邻近服务

在本文中&#xff0c;我们将设计一个邻近服务&#xff0c;用来发现用户附近的地方&#xff0c;比如餐馆&#xff0c;酒店&#xff0c;商场等。设计要求 从一个小明去面试的故事开始。面试官&#xff1a;你好&#xff0c;我想考察一下你的设计能力&#xff0c;如果让你设计一个…

[转]Redis持久化存储(AOF与RDB两种模式)

Redis中数据存储模式有2种&#xff1a;cache-only,persistence; cache-only即只做为“缓存”服务&#xff0c;不持久数据&#xff0c;数据在服务终止后将消失&#xff0c;此模式下也将不存在“数据恢复”的手段&#xff0c;是一种安全性低/效率高/容易扩展的方式&#xff1b;pe…

C语言试题112之一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如 6=1+2+3.编程 找出 1000 以内的所有完数。

✅作者简介:大家好我是码莎拉蒂,CSDN博客专家🥇🥇🥇 📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 1、题目 题目:一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如 6=1+2+3.编程 找出 …

关于jstl.jar引用问题及解决方法

在前文SSM说到因为从MyEclipse换成了Eclipse。有些架包自动缺失。 造成&#xff1a;"org.apache.jasper.JasperException: This absolute uri (http://java.sun.com/jsp/jstl/core ) cannot be resolved in either web.xml or the jar files deployed with this applicati…

网络技术基础与计算思维实验教程_2.3_单交换机VLAN配置实验

2.3.1 实验内容 2.3.2实验目的 实验的目的一是验证交换机 VLAN 配置过程; 二是验证属于同一 VLAN的终端之间的通信过程; 三是验证每一个 VLAN 为独立的广播域; 四是验证属于不同 VLAN的两个终端之间不能通信; 五是验证转发项和 VLAN的对应关系。 2.3.3实验原理 默认情况下,交换…

dotnet-exec 0.5.0 released

dotnet-exec 0.5.0 releasedIntrodotnet-exec 是一个 C# 程序的小工具&#xff0c;可以用来运行一些简单的 C# 程序而无需创建项目文件&#xff0c;而且可以自定义项目的入口方法&#xff0c;支持但不限于 Main 方法Install/Updatedotnet-exec 是一个 dotnet tool&#xff0c;可…

C语言试题113之一球从 100 米高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在 第 10 次落地时,共经过多少米?第 10 次反弹多高?

📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 题目:一球从 100 米高度自由落下,…

超酷的 Vim 搜索技巧

尽管目前我们已经涉及[1] Vim 的多种特性&#xff0c;但此编辑器的特性集如此庞大&#xff0c;不管我们学习多少&#xff0c;似乎仍然远远不足。承接我们的 Vim 教程系列&#xff0c;本文我们将讨论 Vim 提供的多种搜索技术。 不过在此之前&#xff0c;请注意文中涉及到的所有…

对面的00后萌新看过来:浅析计算机编程在高等职业GIS专业中的重要性

文章目录什么是传说中的GIS&#xff1f;GIS必修哪些课程&#xff1f;学GIS到底何去何从&#xff1f;什么是计算机编程&#xff1f;编程在GIS中的地位如何&#xff1f;高等职业GIS如何教学&#xff1f;专科生怎样学好GIS&#xff1f;什么是传说中的GIS&#xff1f; GIS是“3S”之…

SQLServer Agent执行[分发清除: distribution] 无法删除快照文件

由于之前创建的发布订阅造成严重的性能压力&#xff0c;症状表现为发布订阅表查询产生CMEMTHREAD suspend等待&#xff0c;由于开发配置每隔十分钟会产生大量的SQLCOMMAND&#xff08;create table&#xff0c;create index大量的命令&#xff09;发布订阅 复制监视器 有Memor…

C语言试题114之猴子吃桃问题

📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 题目:猴子吃桃问题:猴子第一天摘…

.NET 7 的 JWT 配置太方便了!

微软宣布 .NET 7 preview5 有一些较大的改进&#xff0c; 包括 JWT 身份验证的简化和自动配置。我安装了 preview 5 尝试了新的 JWT 身份配置。如果您想把现有的项目更新到 .Net 7 preview 5, 下面是一个快速更新的命令。Update all Microsoft.AspNetCore.* package references…

[转]面试官,不要再问我三次握手和四次挥手

文章目录 1. 三次握手 1.1 为什么需要三次握手&#xff0c;两次不行吗&#xff1f;1.2 什么是半连接队列&#xff1f;1.3 ISN(Initial Sequence Number)是固定的吗&#xff1f;1.4 三次握手过程中可以携带数据吗&#xff1f;1.5 SYN攻击是什么&#xff1f;2. 四次挥手 2.1 挥手…