通过绕一个轴旋转2d平面来生成圆柱对称3D数据

时间:2016-10-18 18:25:16

标签: matlab 3d interpolation

在问到previous question之后,我想创建一个3d体积,即e f(x,y,z),从2D矩阵I(x,y)开始而不仅仅是曲线。

例如,假设I=peaks(10),我如何围绕其中一个轴(比如y轴)旋转它以获得3D矩阵?如果我改为I(r,theta),会更容易吗?  我可以在3D中旋转平面,但这不是3D矩阵的一部分,只是新的x,y,z坐标。

1 个答案:

答案 0 :(得分:4)

我认为检查预期的3d数组的索引非常简单,几何上找到它们对应的I(x,y)值(是的,基本上是笛卡尔到圆柱变换),然后根据需要填充每个值。

这是我的意思的最小版本。假设大小为[N,N]的输入数组对应于x中的坐标y0:N-1。假设输入数组沿xz平面定向,并围绕z轴旋转,以生成输出数组V。因此,V的维度对应于-(N-1):N-1x上的y以及0:N-1上的z。因此V的维度为[2*N-1, 2*N-1, N]

演示两种方法(分别使用griddatainterp2),完成绘制重现性:

% size of the problem
N = 10;

% input data
I = peaks(N);

% two sets of output V for two methods
V1 = zeros(2*N-1,2*N-1,N);
V2 = zeros(2*N-1,2*N-1,N);    
[i1,i2,i3] = ndgrid(1:2*N-1,1:2*N-1,1:N);
% [i1(:), i2(:), i3(:)] are the contiguous indices of V
% z dimension is the same as of I: rotate around z axis

% it will be assumed that input 1:N span elements from 0 to N-1
% output V spans -(N-1):N-1 along x and y
x = i1-N; % -(N-1):N-1
y = i2-N; % -(N-1):N-1
z = i3-1; %      0:N-1
% input array I is in xz plane, rotated along z axis, geometrically speaking

% identify the cylindrical coordinates of each voxel [i1,i2,i3]
[~,r_out,z_out] = cart2pol(x,y,z); % theta is redundant; z_out===z

% identify the coordinates of each input pixel with the above
[j1,j2] = meshgrid(1:N,1:N);
r_in = j1-1; % Cartesian input x <-> cylindrical output r
z_in = j2-1; % Cartesian input y <-> cylindrical output z
% note that j1 and j2 are swapped with respect to x and y
% but this is what interp2 will expect later

% interpolate each voxel based on r and z
method = 'nearest'; %probably the least biased
%method = 'cubic'; %probably the prettiest

V1(:) = griddata(r_in,z_in,I,...
        r_out(:),z_out(:),method);

V2(:) = interp2(r_in,z_in,I,...
        r_out(:),z_out(:),method,...
        0); % extrapolation value, otherwise NaNs appear outside


% plot two slices: xz plane and general rotated one
figure;
% generate rotated versions of the xz plane by rotating with phi around z
for phi=[0, -25, -90]/180*pi
    [xp0,zp] = meshgrid(-(N-1):0.1:N-1,0:0.1:N-1);
    xp = xp0*cos(phi);
    yp = xp0*sin(phi);

    subplot(121);
    slice(y,x,z,V1,xp,yp,zp);
    title('griddata nearest');
    shading flat;
    axis equal vis3d;
    hold on;

    subplot(122);
    slice(y,x,z,V2,xp,yp,zp);
    title('interp2 nearest, extrap 0');
    shading flat;
    axis equal vis3d;
    hold on;
end

result

如您所见,slice直接在V中绘制数据,因此这是生成的3d数组的准确表示。

作为参考,这里是输入I = peaks(10)的单个样本:

input shape