随时间更新的 3D 散点图:MATLAB

3D scatterplot that updates with time: MATLAB

我想要做的是获取点列表 (x,y,z) 的数据,单个 "cells" 散点图(有 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) 处。

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

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

如果有人在制作这样的动画数据方面有智慧,请分享技巧或有用的代码。我有一些编程背景,但根本不会像这样表示数据,所以我发现简单的东西让我陷入循环,对不起,如果这个 post 遇到非常 n00bish。

示例数据:

 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];

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


设置

您最初的问题是您的数据全部在行向量中。让我们使用 reshape

xyz 制作成每行具有不同 c "trajectory" 的矩阵
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(:))];

绘制粗动画 - 运行 在 "Setup" 代码之后

% 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

在 "Setup" 代码

之后绘制带有轨迹线的平滑动画 - 运行

您想获得积分"slide"。最简单的方法是使用 interp1 为您插入点,然后像以前一样绘制它们。在这个例子中,我还绘制了 "historic" 数据线

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

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


拍电影

您可能会发现文件交换上的这个条目很有用,它演示了使用 imwrite 生成 gif/movie 并且看起来非常简单。我还没有对此进行测试,请参阅 "Examples" 选项卡以获取信息:

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