随时间更新的 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) 处。
- 算法帮助会很好,我多年没有使用 MATLAB 并且我的算法技能生疏:这可以用 for 循环完成吗,我应该根据时间对矩阵进行排序然后根据 c 拆分吗?
接下来我需要想办法随着时间的推移更新点数
- 尝试计算每个点之间的 3D 距离并使其 'slide' 逐渐朝向目的地是否值得,或者这在 MATLAB 中会非常困难吗?如果两个点同时位于两个非常不同的地方,这将如何处理边界?该图是否在 MATLAB 中自动缩放?
一旦我有一个足够流畅地显示所有点的算法,我就可以使用以下代码将其转换为视频: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
将 x
、y
和 z
制作成每行具有不同 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
我想要做的是获取点列表 (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) 处。
- 算法帮助会很好,我多年没有使用 MATLAB 并且我的算法技能生疏:这可以用 for 循环完成吗,我应该根据时间对矩阵进行排序然后根据 c 拆分吗?
接下来我需要想办法随着时间的推移更新点数
- 尝试计算每个点之间的 3D 距离并使其 'slide' 逐渐朝向目的地是否值得,或者这在 MATLAB 中会非常困难吗?如果两个点同时位于两个非常不同的地方,这将如何处理边界?该图是否在 MATLAB 中自动缩放?
一旦我有一个足够流畅地显示所有点的算法,我就可以使用以下代码将其转换为视频: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
x
、y
和 z
制作成每行具有不同 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