如何使函数使用不同大小的网格/线性空间输入

How to make a function work with different sized meshgrid/linspace inputs

提问人:teeeeee 提问时间:10/18/2023 更新时间:10/19/2023 访问量:48

问:

我有一个名为函数的函数,它将网格向量作为输入,并计算在这些网格点上评估的一些输出。总共有网格点。[U,V,W] = my_function(x,y,z)N

问题是我希望我的函数能够容忍不同大小的输入。例如

THIS:
[Y,Z] = meshgrid(0:10,-10:20); X = 6.3;

OR THIS:
[X,Y,Z] = meshgrid(0:10,-10:20,-2:2);

OR THIS:
Z = linspace(-1,1,10); X = 4.2; Y = 1;
etc

但是在函数内部,我需要将 x y z 变量转换为 3 x 数组,如下所示:N

r = [X(:) Y(:) Z(:)]

(这是因为我需要应用一些旋转矩阵,然后对旋转的坐标进行一些进一步的操作)。如果 X、Y 和 Z 的大小不同,则这不起作用。

我试图制作一个预处理坐标的辅助函数,如下面的 MWE 所示,但它非常混乱。我想知道是否有更简洁/更干净/更标准的方法来实现这一目标?

x = linspace(-10,10,100);
Y = 3;
z = linspace(-12,12,80);
[X,Z] = meshgrid(x,z);

[U,V,W] = my_function(X,Y,Z);




%%% MAIN FUNCTION %%%
function [U,V,W] = my_function(X,Y,Z)

[X,Y,Z] = preprocess_gridvectors(X,Y,Z);  % Make sure grid vectors are all same size
N1 = size(X,1); N2 = size(X,2); N3 = size(X,3);
X = X(:); Y = Y(:); Z = Z(:);

%%% Do some transformation and processing here (rotate coordinates and use them)
R = [cos(pi) -sin(pi) 0;sin(pi) cos(pi) 0;0 0 1]; rotXYZ = R*[X Y Z].';
U = rotXYZ(1,:); V = rotXYZ(2,:); W = rotXYZ(3,:);
%%%

% Put the outputs back into the same shape as the original inputs
U = reshape(U, N1,N2,N3);
V = reshape(V, N1,N2,N3);
W = reshape(W, N1,N2,N3);
end



%%% HELPER FUNCTION %%%
function [X,Y,Z] = preprocess_gridvectors(X,Y,Z)

unique_array_sizes = unique([size(X) size(Y) size(Z)]);  % Determine dimensions to use
unique_array_sizes(unique_array_sizes==1) = [];          % Disregard scalar dimension
N_expected = prod(unique_array_sizes);                   % Total number of unique grid points expected

sizes = zeros(3,3);
if numel(X)==N_expected     % X already has the right dimensions
    sizes(1,1) = size(X,1); % Get the dimensions of X
    sizes(1,2) = size(X,2);
    sizes(1,3) = size(X,3);
end

if numel(Y)==N_expected    % Y already has the right dimensions
    sizes(2,1) = size(Y,1);
    sizes(2,2) = size(Y,2);
    sizes(2,3) = size(Y,3);
end

if numel(Z)==N_expected    % Z already has the right dimensions
    sizes(3,1) = size(Z,1);
    sizes(3,2) = size(Z,2);
    sizes(3,3) = size(Z,3);
end

inds = sizes~=0; % Anything which is non-zero has correct dimensions already
ind_dir = find(inds(:,1),1); % Choose the first axis that has good dimensions

% These should be the correct final dimensions now
N1 = sizes(ind_dir,1);
N2 = sizes(ind_dir,2);
N3 = sizes(ind_dir,3);

if ~any(sizes(1,:)) % X direction needs replicating
    X = repmat(X,[N1 N2 N3]);
end
if ~any(sizes(2,:)) % Y direction needs replicating
    Y = repmat(Y,[N1 N2 N3]);
end
if ~any(sizes(3,:)) % Z direction needs replicating
    Z = repmat(Z,[N1 N2 N3]);
end

end
数组 MATLAB 多维数组 维度

评论

0赞 Luis Mendo 10/19/2023
我们是否可以假设在每个维度中,所有输入的大小要么相同,要么为 1?除此之外,输入的数量是固定的(3)还是可以动态变化?
0赞 teeeeee 10/19/2023
@LuisMendo 输入的数量始终固定为 3(必须始终提供 x、y 和 z),我对如何自己捕获这些错误感到满意。
0赞 Luis Mendo 10/19/2023
例如,我的第一个问题是:我们是否可以假设这不是一个可能的输入?(因为是和不是X = ones(10,20,30); Y = ones(10,1,30); Z = ones(1,20,40)size(Z,3)4030)
0赞 teeeeee 10/19/2023
@LuisMendo 例如,如果其中一个输入的维度是 2D 数组(即 N1 x N2 x 1),那么至少应该有另一个输入也具有相同的大小(因为它们应该是用 meshgrid 生成的)。
0赞 teeeeee 10/19/2023
@LuisMendo 是的,我认为你举的例子不应该被允许。

答:

2赞 Luis Mendo 10/19/2023 #1

您可以获得隐式扩展来为您完成工作:

X = X + 0*Y + 0*Z;
Y = 0*X + Y + 0*Z;
Z = 0*X + 0*Y + Z; 

这使用了一些不必要的算术运算(即乘以 0 然后相加),但所需的计算时间可能可以忽略不计。

评论

1赞 teeeeee 10/19/2023
不得不说,看到这个答案,我居然笑出声来。贪婪。谢谢!
0赞 Luis Mendo 10/19/2023
我也玩得很开心,好问题!