我有一个.csv文件,其中每行的数据格式为(x,y,z,t,f)
,其中f
是(x,y,z)
位置t
处某个函数的值(x,y,z,t)
。因此,.csv中的每个新行都会提供一组新的坐标f
,并附带值imagesc
。 .csv没有排序。
我希望随着时间的推移,使用xy
在imagesc
- 平面中创建此数据的视频。我这样做的方法是将M重新格式化为M = csvread('file.csv');
uniqueX = unique(M(:,1));
uniqueY = unique(M(:,2));
uniqueT = unique(M(:,4));
M_reformatted = zeros(length(uniqueX), length(uniqueY), length(uniqueT));
for i = 1:length(uniqueX)
for j = 1:length(uniqueY)
for k = 1:length(uniqueT)
M_reformatted(i,j,k) = M( ...
M(:,1)==uniqueX(i) & ...
M(:,2)==uniqueY(j) & ...
M(:,4)==uniqueT(k), ...
5 ...
);
end
end
end
更容易使用的内容。我正在做三个嵌套循环,大致类似于
M_reformatted
我有k
后,我可以循环执行时间步imagesc
并在M_reformatted(:,:,k)
上使用//******************************/
// Aiming Controls
//******************************/
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Left))
{
float sin = sinf(-m_fRotationSpeed*elapsedTime);
float cos = cosf(-m_fRotationSpeed*elapsedTime);
sf::Vector2f newDirection;
newDirection.x = (cos*m_vAimDirection.x) - (sin * m_vAimDirection.y);
newDirection.y = (sin*m_vAimDirection.x) + (cos*m_vAimDirection.y);
//Update sprite rotation
// Find angle of rotation by acos(v1dotv2)
float rotationAngle = acosf(1 * m_vAimDirection.y);
// Check to make sure we get the right direction!
if (m_vAimDirection.x < 0)
rotationAngle = (b2_pi*2.0f) - rotationAngle;
// convert to degrees
rotationAngle *= 180.0f / b2_pi;
// HERE IS WHERE I CHECK THE BOUNDS
if (rotationAngle > 88.0f && rotationAngle < 272.0f)
rotationAngle = 88.0f;
else
m_vAimDirection = newDirection;
//apply new rotation
m_sCannon.setRotation(rotationAngle);
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Right))
{
float sin = sinf(m_fRotationSpeed*elapsedTime);
float cos = cosf(m_fRotationSpeed*elapsedTime);
sf::Vector2f newDirection;
newDirection.x = (cos*m_vAimDirection.x) - (sin * m_vAimDirection.y);
newDirection.y = (sin*m_vAimDirection.x) + (cos*m_vAimDirection.y);
//Update sprite rotation
// Find angle of rotation by acos(v1dotv2)
float rotationAngle = acosf(1 * m_vAimDirection.y);
// Check to make sure we get the right direction!
if (m_vAimDirection.x < 0)
rotationAngle = (b2_pi*2.0f) - rotationAngle;
// convert to degrees
rotationAngle *= 180.0f / b2_pi;
// HERE IS WHERE I CHECK THE BOUNDS
if (rotationAngle < 272.0f && rotationAngle > 88.0f)
rotationAngle = 272.0f;
else
m_vAimDirection = newDirection;
//apply new rotation
m_sCannon.setRotation(rotationAngle);
}
。但是执行上面的嵌套循环非常慢。是否可以对上述进行矢量化?如果是这样,该方法的大纲将非常有用。
编辑:如下面的答案/评论中所述,我犯了一个错误,因为有几个可能的z值,我没有考虑到。如果只有一个z值,上面就可以了。
答案 0 :(得分:3)
我认为你不需要矢量化。我想你改变了你的算法。
您只需要一个循环来逐步浏览CSV文件的行。对于每一行,您都有(x,y,z,t,f),因此只需将其存储在M_reformatted
所属的位置即可。像这样:
M_reformatted = zeros(max(M(:,1)), max(M(:,2)), max(M(:,4)));
for line = 1:size(M,2)
z = M(line, 3);
if z ~= 0, continue; end;
x = M(line, 1);
y = M(line, 2);
t = M(line, 4);
f = M(line, 5);
M_reformatted(x, y, t) = f;
end
另请注意,预分配M_reformatted
是一个非常好的主意,但您的代码可能已经错误(取决于数据)。我认为像我一样使用max
将会做正确的事。
答案 1 :(得分:3)
此向量化解决方案允许x
和y
的负值,并且比非向量化解决方案快许多倍(对于底部的测试用例,接近20倍)。
我们的想法是使用x
按字典顺序对y
,t
和sortrows
值进行排序,然后使用reshape
构建时间片M_reformatted
。
代码:
idx = find(M(:,3)==0); %// find rows where z==0
M2 = M(idx,:); %// M2 has only the rows where z==0
M2(:,3) = []; %// delete z coordinate in M2
M2(:,[1 2 3]) = M2(:,[3 1 2]); %// change from (x,y,t,f) to (t,x,y,f)
M2 = sortrows(M2); %// sort rows by t, then x, then y
numT = numel(unique(M2(:,1))); %// number of unique t values
numX = numel(unique(M2(:,2))); %// number of unique x values
numY = numel(unique(M2(:,3))); %// number of unique y values
%// fill the time slice matrix with data
M_reformatted = reshape(M2(:,4), numY, numX, numT);
注意:我假设y
指的是图片的列,而x
指的是行。如果您希望这些翻转,请在代码末尾使用M_reformatted = permute(M_reformatted,[2 1 3])
。
我用于M
的测试用例(将结果与其他解决方案进行比较)的NxNxN
空间为T
次切片:
N = 10;
T = 10;
[x,y,z] = meshgrid(-N:N,-N:N,-N:N);
numPoints = numel(x);
x=x(:); y=y(:); z=z(:);
s = repmat([x,y,z],T,1);
t = repmat(1:T,numPoints,1);
M = [s, t(:), rand(numPoints*T,1)];
M = M( randperm(size(M,1)), : );