【问题标题】:3D scatterplot that updates with time: MATLAB随时间更新的 3D 散点图:MATLAB
【发布时间】:2017-04-23 20:35:47
【问题描述】:

我想要做的是获取点列表 (x,y,z) 的数据,散点图上的单个“单元格”(有 9 个不同的单元格:c=1,...,9 ) 和 t=time,并由此创建一个 scatter3,随着位置随时间的变化而不断更新。由于散点图上每个点的 t 从 0 开始,因此散点图上应始终有 9 个点。到目前为止,我所写的只是下面的这段代码,它将列表转换为矩阵,并根据 t 的当前值和最后一个值按顺序绘制每个点(不管 c 值如何),并带有暂停。

x=['x axis points'];
y=['y axis points'];
z=['z axis points'];
c=[1,1,1,1,1,2,2,2,2,3,3,3,3....8,8,8,8,8,8,8,9,9,9,9,9,9,9]; %cells
t=[0,1,2,3,4,0,1,2,3,0,1,2,3,,,,0,1,2,3,4,6,7,0,4,6,9,10,12,14]; %time resetting at 0 for each cell

mat=cell2mat({[x;y;z;c;t]}); %Convert cells into a matrix

scatter3(mat(1,2),mat(1,3),mat(1,4),100);
axis tight;

for jj=1:numel(mat(5,:))  %loops through for length of 5th row
scatter3(mat(1,jj),mat(2,jj),...
    mat(3,jj),100);       %plots point at t(x,y,z) w/ no regard to c
drawnow
if(jj>1 && mat(5,jj-1)>0)
    pause(mat(5,jj)-mat(5,jj-1))  %waits for difference in last two times if not 0
else
    pause(1) %otherwise pause a second
end
end

我需要做的第一件事是修改循环,以便绘制每个散点 - 对于时间 t 的每个 c,将其点绘制在对应的 (x,y,z) 处。

  • 算法帮助会很好,我已经多年没有使用 MATLAB,而且我的算法技能已经生疏了:这可以用 for 循环完成吗?我应该根据时间对矩阵进行排序,然后根据 c 进行拆分吗?

接下来我需要想办法随着时间的推移更新点

  • 是否值得尝试计算每个点之间的 3D 距离并让它逐渐向目的地“滑动”,或者这在 MATLAB 中会非常困难吗?另外,如果两个点同时在两个非常不同的地方,这将如何处理边界?该图是否只是在 MATLAB 中自动缩放?

一旦我有一个足够流畅地显示所有点的算法,我就可以使用以下代码将其转换为视频:https://www.youtube.com/watch?v=nnkTSX5U_a4

如果有人在动画这样的数据方面有智慧,请分享提示或有用的代码。我有一些编程背景,但根本不会表示这样的数据,所以我发现简单的东西让我陷入循环,如果这篇文章遇到了非常糟糕的问题,我很抱歉。

示例数据:

 x=[-213.135 -217.261 -220.636  -225.325 -227.763 -232.826 -236.389 -239.577 
-238.827 -242.39];
 y=[92.081  90.955  88.892  86.83   84.767  82.891  84.392  80.453  75.765  
 73.327];
 z=[60 70   70  80  90  90  90  90  90  100];
 c=[1 1 1   1   1   1   1   1   1   1];
 t=[0 1.008566667   2.017133333 3.025716667 4.034283333 5.04285 6.051416667 
 7.059983333    8.068566667 9.077133333];

【问题讨论】:

  • 请包含示例xyz 数据,以便您可以运行现有代码,以便更好地了解您的问题
  • @Wolfie 我从我的数据中添加了前 10 个数字,c=1 表示它是同一个单元格。要一次绘制多个点,只需复制此数据并将 c 值更改为 2,3,4... 并更改 x、y、z 值之一,以便它们不会相互绘制,时间间隔是我刚刚意识到的每个点都一样,因此程序可以同时更新每个点。

标签: algorithm matlab 3d scatter-plot


【解决方案1】:

下面我发布了两种方法的代码,第二种方法建立在第一种方法的基础上,以提供您想要的结果。


设置

您最初的问题是您的数据都在行向量中。让我们将x,yz 制作成每行具有不同c“轨迹”的矩阵,使用reshape

x = reshape(x, [], 9); % Makes x a 9 row matrix, assuming number of elements divisible by 9

另一个让你的时间更容易处理的函数是diff。这只是一个向量中相邻点之间的差异,用它来得到dt

dt = [1, diff(t)];  % The 1 is needed as numel(diff(t)) = numel(t) - 1

现在您可以使用这些来初始化您的数据:

% x,y and z are 10*9=90 element matrices, representing 9 trajectories.
% For real data, don't use REPMAT, use actual matrix. If data is just a 
% 90 element row vector, use RESHAPE to split into 9 rows.
x = repmat([-213 -217 -220 -225 -227 -232 -236 -239 -238 -242], 9, 1);
y = repmat([92.1 91.0 88.9 86.8 84.8 82.9 84.4 80.5 75.8 73.3], 9, 1);
z = repmat([60 70 70 80 90 90 90 90 90 100], 9, 1);
t = [0 1.0085 2.0171 3.0257 4.0342 5.0428 6.0514 7.0599 8.0685 9.0771];
dt = [1, diff(t)];  dt(dt < 0) = 1;  % Initialise dt, setting negative values to 1.

n = size(x,2);
% Offset z by row number. This wouldn't be needed with actual data.
% c is the trajectory number (1 - 9)
c = repmat((1:9)', 1, n); 
z = z - 5*c;
% Get axes limits, so they can be kept constant for the animation
lims = [min(x(:)), max(x(:)), min(y(:)), max(y(:)), min(z(:)), max(z(:))];

绘制粗略动画 - 在“设置”代码之后运行

% Plot actual points
figure;
for jj = 1:n            % Loop through all points in rows
    clf;                % Clear figure and hold on for multiple plots
    for ii = 1:9        % Loop over trajectories (rows)
        hold on;
        plot3(x(ii,jj), y(ii,jj), z(ii,jj), 'o');   % Plots point at x(t), y(t), z(t) 
        drawnow;
        hold off; view(-37.5, 30) % Hold off and set default 3D viewpoint
        axis(lims); grid on;
    end
    pause(dt(jj))    
end

使用跟踪线绘制平滑动画 - 在“设置”代码之后运行

你想让分数“滑动”。最简单的方法是使用interp1 为您插入点,然后像以前一样绘制它们。在这个例子中,我还绘制了“历史”数据线

pts = 100;                                % Number of points (more is smoother)
x = interp1(1:n, x', linspace(1,n,pts))'; % Make x,y,z,t into pts number of points
y = interp1(1:n, y', linspace(1,n,pts))';
z = interp1(1:n, z', linspace(1,n,pts))';
t = interp1(1:n, t, linspace(1,n,pts));
dt = max(1/pts, [1/pts, diff(t)]);        % Set dt as positive time diff

% Plot smooth version, with trajectory lines
% Set up colours matrix so that plots points / lines can be the same colour
clrs = [linspace(0.4,0.8,9)', linspace(0.6,0.1,9)', linspace(0,0.5,9)'];
figure;
for jj = 1:pts            % Loop through all points in rows
    clf;                % Clear figure and hold on for multiple plots
    for ii = 1:9        % Loop over trajectories (rows)
        hold on;
        plot3(x(ii,jj),   y(ii,jj),   z(ii,jj),   'o', 'color', clrs(ii,:)); % Plots point at x(t), y(t), z(t) 
        plot3(x(ii,1:jj), y(ii,1:jj), z(ii,1:jj), '-', 'color', clrs(ii,:)); % Plot lines from T = 0 to T = t
        drawnow;
        hold off; view(-37.5, 30) % Hold off and set default 3D viewpoint
        axis(lims); grid on;
    end
    pause(dt(jj))    
end

结果(最后一个图):


轴限制

在上面,我已经修复了轴限制,以便它们在整个动画中保持不变,并适合所有点。您可以使用

将它们设为自动
axis auto

但这会让你的动画看起来很跳跃!


制作电影

您可能会发现 File Exchange 上的此条目很有用,它演示了使用 imwrite 生成 gif/电影,并且看起来非常简单。我尚未对此进行测试,请参阅“示例”选项卡以获取信息:

https://uk.mathworks.com/matlabcentral/fileexchange/21944-animated-gif

【讨论】:

  • 谢谢!尚未测试,但非常详细的答案无疑会给我很多工作
  • 不用担心@Mike,如果您还有其他问题,请告诉我。干杯
猜你喜欢
  • 2013-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-11
  • 2017-02-11
  • 1970-01-01
  • 2013-08-17
相关资源
最近更新 更多