0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

关于面向对象编程创建专用图表的方法介绍

MATLAB 来源:djl 2019-09-12 14:23 次阅读

开发高级MATLAB可视化效果通常需要管理多个低层的图形对象,包含动态更新图形的应用程序更是如此。这种应用程序可能需要非常耗时的编程。Chart 对象可提供高级应用程序编程接口(API),实现可视化的自定义创建。图表可为最终用户提供方便的可视化 API,无需用户执行低层图形编程。

本文以包含最佳拟合线的散点图为主要示例,通过分步指导展示如何使用 MATLAB 面向对象的编程创建和实现自定义图表,包括:

编写标准图表模板

编写构造方法

使用 private 属性封装图表数据和图形

使用 Dependent 属性创建高级可视化 API

管理图表生命周期

使用继承简化附加图表的开发

图表示例

MATLAB 提供几种图表,包括 heatmap 图和 geobubble 图,前者显示叠放在彩色网格上的矩阵值,后者可快速在地图上绘制离散数据点(图1)。

关于面向对象编程创建专用图表的方法介绍

图1 heatmap图和 geobubble 图

此外,我们还创建几种特定于应用程序的图表(图2)。您可以从File Exchange 中随本文使用的 MATLAB 代码一起,下载这些图表。

关于面向对象编程创建专用图表的方法介绍

图2 可在 File Exchange 中下载自定义图表:

https://ww2.mathworks.cn/matlabcentral/fileexchange/65857-creating-specialized-charts-with-matlab-object-oriented-programming

创建二维散点图:函数或图表?

假设我们要创建包含对应最佳拟合线的二维散点图(图 3)。我们可以使用 scatter 函数显示离散 (x,y) 数据点,并使用 Statisticsand Machine Learning Toolbox 中的 fitlm 函数计算最佳拟合线。

关于面向对象编程创建专用图表的方法介绍

关于面向对象编程创建专用图表的方法介绍

图3 最佳拟合线和底层的分散数据

以上代码可满足静态可视化的需求。但是,如果应用程序要求对数据进行动态修改,我们会遇到几个难题:

如果使用长度与当前 XData 相同的新数组替换 XData 或 Ydata,最佳拟合线不会动态更新(图 4)。

关于面向对象编程创建专用图表的方法介绍

关于面向对象编程创建专用图表的方法介绍

图4 最佳拟合线在更改散点图的 XData 后未更新

如果 Scatter 对象 s 的任一数据属性(XData 或 YData)设置为长度比当前数组长或短的数组,该对象会发出警告且不会执行图形更新。

关于面向对象编程创建专用图表的方法介绍

我们可以通过设计一个图表 ScatterFit 来解决这些难题。

构建图表代码:函数或类?

函数将代码封装为可重用单元,用户无需重复代码即可创建多个图表。

关于面向对象编程创建专用图表的方法介绍

请注意,此函数需要输入两个数据(x 和 y)。您可以指定图形父项 f(例如,图形)作为第一个输入参数

scatterfit(x,y) 指定输入的两个数据

scatterfit(f,x,y) 指定图形父项和数据

在第一种情况下,该函数展示自动生成的行为,即将自动创建图表的图形。

使用函数创建图表具有某些缺点:

图表创建后数据无法修改

要更改图表数据,指定不同的数据输入后,需要再次调用函数重新创建图表

最终用户很难查找可配置的图表参数(如注释和分散/线属性)

用类来实现图表具有代码封装及方法可重用性等好处,同时支持对图表进行修改。

定义图表类

为了与 MATLAB 图形对象保持一致,我们将图表实现为 handle 类,以便在适当位置修改图表。我们支持在图表属性中使用点记法和 get/set 语法。要实现这一目标,我们从预定义 matlab.mixin.SetGet 类(本身是 handle 类)中派生出 ScatterFit 图表。

关于面向对象编程创建专用图表的方法介绍

因此,任何属性都将自动支持表 1 中显示的语法。

关于面向对象编程创建专用图表的方法介绍

表1图表属性的访问和修改语法

编写图表类的构造方法

构造方法是类定义中的一个函数,用于构造图表对象。首先,将代码从 scatterfit 函数复制到我们的图表构造方法之中。随后,进行以下修改支持所需图表行为:

输入参数。我们使用 varargin 支持在所有图表输入参数中使用名称值对。这意味着不需要指定输入参数,所有输入值均可选。

关于面向对象编程创建专用图表的方法介绍

父图形。不同于函数,如果已指定图形构造中没有输入 Parent,则无法为图表自动创建该输入。我们使用空 Parent 创建 axes 对象。

关于面向对象编程创建专用图表的方法介绍

请注意,此行为与 plot 和 scatter 等便捷函数的行为不同,后两者可以自动生成输入。如果用户将 Parent 指定为输入参数,则随后将在构造方法中对其进行设置。

图表图形。我们可创建和存储图形所需的任何图形对象。大多数图表需要 axes 对象以及线或贴片对象等 axes 内容。在 ScatterFit 图表中,我们需要 Scatter 对象和 Line 对象。

关于面向对象编程创建专用图表的方法介绍

图形配置。我们可通过设置任何所需属性配置图表图形。例如,我创建标签或标题等注释、设置 axes 的特定视图、添加网格,或者调整颜色、样式或线宽。

用户指定的输入。我们可设置最终用户提供的任何名称值对参数。由于图表派生自 matlab.mixin.SetGet,实现这一点非常容易:

关于面向对象编程创建专用图表的方法介绍

如果用户已作为名称值对输入参数提供数据属性,在此处设置这些数据(XData 和 YData)。我们还注意到,此编码方法可确保用户在指定名称值对时出现的任何错误都将被图表的属性 set 方法发现和解决(稍后讨论)。

如可行,我们将使用基元对象创建图表图形,因为高级便捷函数在调用时将重置多个现有 axes 属性(图2)。但是,这条原则存在例外情况:在 ScatterFit 内部,我们将使用 scatter 函数创建 Scatter 图形对象,因为它支持对个别标记的尺寸和颜色进行后续更改。

关于面向对象编程创建专用图表的方法介绍

表2 基元和高级图形函数的示例

封装图表数据和图形

在大多数图表中,底层图形包含至少一个 axes 对象及其内容(例如线或面对象)或多个对等的 axes 对象(例如,图例或彩条)。这些图表还包含内部数据属性,以确保公共属性之间保持一致。我们存储底层图形和内部数据为专有图表属性。例如,ScatterFit 图表会维护以下专有属性:

关于面向对象编程创建专用图表的方法介绍

我们使用命名约定 XData_ 指示该版本是图表数据的专有内部版本。用户可见的对应公共数据属性将命名为 XData。

使用 private 属性主要有三个目的:

限制底层图形的可见性,隐藏实现细节,减少 API 中的视觉混乱

限制对底层图形的访问,减少绕过 API 的几率

轻松同步图表数据(例如,我们需要对 ScatterFit 的 XData 和 YData 属性进行关联)

提供可视化API

设计图表的一个主要原因是提供方便、直观的 API。我们使用与现有图形对象属性一致的名称为 ScatterFit 图表提供容易识别的属性(图 5)。

关于面向对象编程创建专用图表的方法介绍

图5 ScatterFit 图表API

用户可使用表 1 中所示的语法访问或修改这些属性。关联的图表图形会动态更新,以响应属性的修改。例如,更改图表的 LineWidth 属性会更新最佳拟合线的 LineWidth。

我们使用 Dependent 类属性实现图表 API。Dependent 属性的值未进行显式存储,而是获取自类中的其他属性。在图表中,Dependent 属性依赖于低级别图形等专有属性或内部数据属性。

要定义 Dependent 属性,我们首先使用属性 Dependent 在 properties 块中声明其名称。这表明该属性的值依赖于类中的其他属性。

关于面向对象编程创建专用图表的方法介绍

通过编写对应的 get 方法,我们还可以指定依赖于其他属性的属性。此方法会返回单个输出参数,即 Dependent 属性的值。在 ScatterFit 图表中,XData 属性(图表公共接口的一部分)就是底层 XData_ 属性,它作为图表的 private 属性存储在内部。

关于面向对象编程创建专用图表的方法介绍

我们为每个可配置的图表属性编写 set 方法。此方法将用户指定的值分配到正确的内部图表属性,以在必要时触发图形更新。

对于 ScatterFit 图表,我们支持对数据属性(XData 和 YData)进行动态修改(包括长度更改)。当用户设置图表的(公共)XData 时,我们将根据比较新数据矢量与现有数据的长短,填充或截断相对的(专有)数据属性 YData_。请记住,如果用户在创建图表时已指定 XData,此 set 方法将被构造方法调用。

关于面向对象编程创建专用图表的方法介绍

我们通过调用不同的 update 方法刷新图表图形。此方法包含在 Scatter 对象中设置新数据、重新计算最佳拟合线,以及在对应的 Line 对象中设置新数据所需的代码。

关于面向对象编程创建专用图表的方法介绍

我们以相同方式为 YData 实现 set 方法,以切换 X/YData 属性的角色。还会从 set 方法中为YData调用 update 方法。

要创建适用于最终用户的丰富 API,我们会实现一组广泛的 Dependent 属性。建议在每个图表中至少包含表 3 中所示的属性。

关于面向对象编程创建专用图表的方法介绍

表3. 建议的 Dependent 属性

请注意,在大多数情况下,这些属性将直接映射到底层图表 axes。例如,Parent 属性的 get 和 set 方法将图表对象的 Parent 映射到 axes 的 Parent。

关于面向对象编程创建专用图表的方法介绍

我们通过定义额外公共接口属性启用对可视化设置的控制,其中每个属性映射到图表维护的特定低级别图形对象。在此类别中,ScatterFit 图表支持各种线相关属性,如最佳拟合线相关 LineStyle、LineWidth 和 LineColor。例如,图表对象的 LineColor 属性会映射到线对象的 Color 属性。

关于面向对象编程创建专用图表的方法介绍

此类别中的典型图表属性包括:

视图相关属性——例如,axes 的 View、XLim 和 Ylim

注释——例如,axes 的 Xlabel、Ylabel 和 Title

装饰性属性——例如,颜色、线宽,样式、网格、透明效果和明暗度

管理图表的生命周期

ScatterFit 图表与其底层 axes 对象密切关联,该对象作为图表的 private 属性之一存储。要正确管理图表的生命周期,我们需要确保两种行为:

删除 axes(例如,通过关闭主图形窗口)即删除图表。如果不能保证这一点,一旦修改图表的数据属性,将导致 MATLAB 尝试更新删除的图形对象,从而引发错误

删除图表(例如,在其超出范围时或当其句柄显式删除时)即删除 axes。如果做不到这一点,则在删除图表后,仍会残留其静态图形

MATLAB 中的每个图形对象都具有 DeleteFcn 属性——一种在图形对象超出范围后被自动调用的回调函数。因此,在图表构造方法中设置 axes 的 DeleteFcn 满足第一个要求。

关于面向对象编程创建专用图表的方法介绍

此处,onAxesDeleted 是 private 类方法,仅充当图表析构方法周围的包装程序。如前所述,每个 handle 类在创建时都包含可自定义析构方法。当对象超过范围后,析构方法将被调用。

关于面向对象编程创建专用图表的方法介绍

通过编写自定义图表类的析构方法,我们可满足第二个要求。在图表析构时,我们将删除图表的axes。

关于面向对象编程创建专用图表的方法介绍

实现这两个要求后,图表对象与其底层 axes 将具有相同的生命周期(图 6)。

关于面向对象编程创建专用图表的方法介绍

图6管理图表和 axes 生命周期

简化附加表格的开发

在编写几个图表后,我们能够轻松识别相似性和重复的代码段。通过在超类中集中放置通用代码,我们可以加速编写额外图表的进程。每个新图表可派生自此超类,这可使我们专注于实现该特定图表的细节,减少重复编码的需求。

我们的超类(即 Chart)具有以下结构:

Chart 派生自 matlab.mixin.SetGet。

Chart 将实现六个核心 Dependent 属性 Parent、Position、Units、OuterPosition、ActivePositionProperty 和 Visible。

Chart 具有 protected 属性 Axes(底层对等图形)。

Chart 构造方法将创建对等的 axes 对象并将 axes 的 DeleteFcn 设置为 protected 方法 onAxesDeleted。此方法进而将删除图表对象。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据
    +关注

    关注

    8

    文章

    6515

    浏览量

    87617
  • 函数
    +关注

    关注

    3

    文章

    3911

    浏览量

    61313
  • 图表
    +关注

    关注

    0

    文章

    24

    浏览量

    8821
收藏 人收藏

    评论

    相关推荐

    vb运行时错误429不能创建对象

    在系统中已经安装了对象所依赖的组件或库。如果缺少这些组件或库,就会导致不能创建对象的错误。解决这个问题的方法是安装所需的组件或库。 对象的类
    的头像 发表于 01-09 11:07 729次阅读

    浅谈C语言面向对象编程思想

    C语言是一种面向过程的语言,但是也可以用结构体和函数指针来模拟面向对象的特性,比如封装、继承和多态。
    发表于 11-02 12:27 263次阅读

    MCU上面可以实现面向对象编程吗?

    为什么都是用的面向过程编程
    发表于 10-24 07:39

    基于面向对象的热流体系统建模方法及应用研究

    以多领域统一面向对象建模语言 Modelica 为例,详细分析了面向对象建模仿真的原理及技术特征,结合热流体系统本身的特点,探索了基于面向
    发表于 10-11 15:29 0次下载

    面向对象思想封装IIC、AT24C64驱动

    使用面向对象编程思想封装IIC驱动,将IIC的属性和操作封装成一个库,在需要创建一个IIC设备时只需要实例化一个IIC对象即可,本文是基于
    的头像 发表于 10-08 15:35 508次阅读

    Python的面向对象编程详解

    一般编程可分为面向过程编程,和面向对象编程。Python的
    发表于 09-04 16:35 269次阅读
    Python的<b class='flag-5'>面向</b><b class='flag-5'>对象</b><b class='flag-5'>编程</b>详解

    Linux内核中面向对象编程的实现

    面向对象编程(OOP),是一种设计思想或者架构风格。OO语言之父Alan Kay,Smalltalk的发明人,在谈到OOP时是这样说的。
    发表于 07-21 14:51 315次阅读

    什么是面向对象编程(OOP)?面向对象的程序设计

    编程领域,面向对象编程 (OOP) 是一种强大的范例,使开发人员能够构建复杂且可扩展的应用程序。
    的头像 发表于 07-19 14:57 793次阅读

    状态机编程实例-面向对象的状态设计模式

    本编介绍了状态机编程的第3种方法——面向对象的状态设计模式,通过C++的继承特性,以及类指针,实现炸弹拆除小游戏中的状态机功能。
    的头像 发表于 06-28 09:04 927次阅读
    状态机<b class='flag-5'>编程</b>实例-<b class='flag-5'>面向</b><b class='flag-5'>对象</b>的状态设计模式

    基于STM32和HAL库创建一个IIC设备

    使用面向对象编程思想封装IIC驱动,将IIC的属性和操作封装成一个库,在需要创建一个IIC设备时只需要实例化一个IIC对象即可,本文是基于
    的头像 发表于 06-26 17:15 1257次阅读

    python创建文件对象

    2.1. 创建文件对象 **open() 函数用于创建文件对象,基本语法格式如下:** open(文件名[,打开方式]) 注意: 如果只是文件名,代表在当前目录下的文件. 文件名可以录
    的头像 发表于 06-21 17:19 1088次阅读
    python<b class='flag-5'>创建</b>文件<b class='flag-5'>对象</b>

    多态性实现原理及其在面向对象编程中的应用

    面向对象编程中,多态性是一个非常重要的概念。
    的头像 发表于 06-08 14:19 410次阅读

    Java反射技术实现对象创建

    一. 基础概念 Java中,一般我们创建一个对象可能会选择new一下个实例。但是随着我们技术的不断提升,我们也学习到了,可以通过反射技术实现对象创建。 可是,你有没有想一下,什么时候
    的头像 发表于 05-22 14:25 1610次阅读
    Java反射技术实现<b class='flag-5'>对象</b>的<b class='flag-5'>创建</b>

    Python面向对象深化(下)

    __call__  方法和可调用对象 凡是可以将 () 直接应用到自身并执行, 都称为可调用对象. 注意: 可调用对象包括自定义的函数、Python 内置函数、以及本节所讲的实例
    的头像 发表于 05-11 17:52 473次阅读

    Python面向对象深化(上)

    , 在城堡的最顶端可以眺望到天空之海. 直到格兰之森那场大火的发生,使得围绕在它周围的魔法阵力量减弱,人们才终于重新看到天空之城的真实模样. 当时,关于天界的传闻甚至比天上的繁星还多,但是却没有一个人能够证明它真实存在。 实例对象和类
    的头像 发表于 05-11 17:51 408次阅读
    Python<b class='flag-5'>面向</b><b class='flag-5'>对象</b>深化(上)