matlab - 如何在 MATLAB 中加速非常慢的动画绘图
问题描述
我正在尝试创建一个动画情节,但我的代码很慢,也许我使用的方法太天真了。在下面的示例中,我有 4 个子图,每个子图有 3 行,我在“时间”循环中更新。
clc;clear;close all;
state = {'$x-Position$','$x-Velocity$','$y-Position$','$y-Velocity$'};
ylabels = {'$x$','$\dot{x}$','$y$','$\dot{y}$'};
options1 = {'interpreter','latex'};
options2 = {'interpreter','latex','fontsize',20};
maxT = 300;
for pp = 1:4
hh1(pp)=subplot(2,2,pp);
xlabel('$t$',options2{:});
ylabel(ylabels{pp},options2{:});
title(state{pp},options1{:})
xlim([0 maxT])
hold on
end
x = randn(4,300);
z = randn(4,300);
x_est = randn(4,300);
for k = 2:maxT
for p = 1:4
plot(hh1(p),k-1:k,x(p,k-1:k),'b','linewidth',2)
plot(hh1(p),k-1:k,z(p,k-1:k),'m')
plot(hh1(p),k-1:k,x_est(p,k-1:k),':k','linewidth',2)
end
drawnow;
end
从分析器输出中可以看出,这drawnow
是在消磨时间。有什么方法可以让我更有效地创建这个动画吗?
解决方案
drawnow
因为你想要一个动画,所以除了使用更新帧之外别无选择。但是,并不是drawnow
特别是在减慢您的速度-分析器可能会产生误导...drawnow
只需更新自上次重新绘制以来的所有图形更改,在您的情况下是十几个新图!
你会发现hold
速度很慢。例如,如果您对自己的持有更明智,请删除现有的hold on
并仅在实际绘图时持有
% ... above code the same but without 'hold on'
for p = 1:4
hold(hh1(p), 'on');
% plots
hold(hh1(p), 'off');
end
这在我的 PC 上节省了约 10% 的时间(从 12.3 秒降至 11.3 秒)。
真正的加速来自于hold
完全删除以及所有单独的plot
调用!此方法也不会触及有助于提高速度的行格式。在此处查看有关更新绘图数据的先前问题。
只需更新绘图数据而不是添加绘图。这给了我约 68% 的加速(从 12.3 秒降至 4.0 秒)。
% ... your same setup
% Initialise plot data
x = randn(4,300);
z = randn(4,300);
x_est = randn(4,300);
plts = cell(4,3);
hh1 = cell(4,1);
% Loop over subplots and initialise plot lines
for p = 1:4
hh1{p}=subplot(2,2,p);
xlabel('$t$',options2{:});
ylabel(ylabels{p},options2{:});
title(state{p},options1{:})
xlim([0 maxT])
% Hold on to make 3 plots. Create initial points and set line styles.
% Store the plots in a cell array for later reference.
hold on
plts{p,1} = plot(hh1{p},1:2,x(p,1:2),'b','linewidth',2);
plts{p,2} = plot(hh1{p},1:2,z(p,1:2),'m');
plts{p,3} = plot(hh1{p},1:2,x_est(p,1:2),':k','linewidth',2);
hold off
end
% March through time. No replotting required, just update XData and YData
for k = 2:maxT
for p = 1:4
set(plts{p,1}, 'XData', 1:k, 'YData', x(p,1:k) );
set(plts{p,2}, 'XData', 1:k, 'YData', z(p,1:k) );
set(plts{p,3}, 'XData', 1:k, 'YData', x_est(p,1:k) );
end
drawnow;
end
现在绘图非常优化。如果您希望动画更快,则只需绘制每个第 2、3、...、第 n 个时间步,而不是使用for k = 2:n:maxT
.
推荐阅读
- php - SOAP 客户端 TypeScript
- javascript - 从对象内部的对象创建一个新数组
- c# - 反序列化时将 Json 信息传递给对象构造函数
- microsoft-graph-api - Excel 是否可以与 Microsoft Graph 共同创作?
- c - 我的过滤器应用程序使用以下代码行对图像产生模糊效果在 C 中给出运行时错误
- powershell - 计算每个文件的字符出现次数(仅限第一行)
- laravel - Laravel 与 Percona DB 冲突,因为表没有主键
- postgresql - 如何在 POSTGREQL 9.6 中创建递归函数?
- javascript - 将方法作为参数传递给类内的另一个方法时出错
- laravel - Laravel 5.8 Multiple middlewares using guards and specific options for each guard