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

时间:2017-04-23 20:35:48

标签: algorithm matlab 3d scatter-plot

我要做的是获取分散列表中的点(x,y,z),单个“单元格”的数据(有9个不同的单元格:c = 1,...,9 ),并且t =时间,并由此创建一个散射3,随着位置随时间变化而不断更新。由于散点图上的每个点的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

我需要做的第一件事是修改循环,以便绘制每个散点 - 对于每个c,在时间t绘制其对应的点(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];

1 个答案:

答案 0 :(得分:0)

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

<强>设置

您最初的问题是您的数据全部在行向量中。让我们将xyz变成具有不同c&#34;轨迹的矩阵&#34;在每一行,使用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(:))];

绘制粗略动画 - 在&#34;设置&#34;之后运行代码

% 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

使用跟踪线绘制平滑动画 - 在&#34;设置&#34;之后运行代码

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

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

结果(最后一个情节):

plot

轴限制

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

自动保留它们
axis auto

但是这会让你的动画看起来很神奇!

制作电影

您可能会发现文件交换中的此条目很有用,它演示了使用imwrite生成gif / movie并且看起来非常简单。我没有对此进行测试,请参阅&#34;示例&#34;信息标签:

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