Does surf() Behave as Expected with ndgrid() Inputs?

Define a function
clear
f = @(x,y) x;
Case 1: square mesh, meshgrid, vector inputs to surf
x = 0:5;
y = 100:105;
[Xmesh,Ymesh] = meshgrid(x,y);
Zmesh = f(Xmesh,Ymesh);
figure
surf(x,y,Zmesh)
xlabel('x');ylabel('y')
Case 2: square mesh, ndgrid, vector inputs to surf
[Xnd,Ynd] = ndgrid(x,y);
Znd = f(Xnd,Ynd);
figure
surf(x,y,Znd)
xlabel('x');ylabel('y')
Cases 1 and 2 clearly indicate that the third input to surf should be built in meshgrid format consistent with the examples in the documentation.
What happens if using array inputs to surf?
Case 3: square mesh, meshgrid, array inputs to surf
figure
surf(Xmesh,Ymesh,Zmesh)
xlabel('x');ylabel('y')
Same result as Case 1, as expected
Case 4: square mesh, ndgrid, array inputs to surf
figure
surf(Xnd,Ynd,Znd)
xlabel('x');ylabel('y')
Why isn't Case 4 the same as Case 2?

 采纳的回答

"Why isn't Case 4 the same as Case 2?"
Because Case 2 is erroneous. For vectors X and Y input to surf, matrix Z must be of size numel(Y)-by-numel(X).
Case 2 produces a surface because x and y happen to be the same length, but consider what happens when vectors x and y aren't the same length:
f = @(x,y) x;
x = 0:6;
y = 100:105;
[Xnd,Ynd] = ndgrid(x,y);
Znd = f(Xnd,Ynd);
% Case 2: square mesh, ndgrid, vector inputs to surf
figure
try
surf(x,y,Znd) % Znd is numel(x)-by-numel(y)
catch ME
disp(ME.message);
end
Data dimensions must agree.
xlabel('x');ylabel('y')
% Case 2a (corrected): square mesh, ndgrid, vector inputs to surf
figure
surf(x,y,Znd.') % Znd.' is numel(y)-by-numel(x)
xlabel('x');ylabel('y')
% Case 4: square mesh, ndgrid, array inputs to surf
figure
surf(Xnd,Ynd,Znd)
xlabel('x');ylabel('y')

5 个评论

You've actually illustrated my point better than I did. Case 2 is not erroneous from the standpoint of input dimensions. Given that Z is square, I believe that surf is producing the correct plot for Case 2 given those inputs. But why doesn't Case 4 produce the same plot as Case 2?
To clarify, this question only came up because I saw surf being used incorrectly, so I thought, as in Case 4, but it seemed to be giving the correct plot, which confuses me.
When using vectors X and Y as inputs to surf, each element of X corresponds to a column of Z and each element of Y corresponds to a row of Z (thus size(Z) is numel(Y)-by-numel(X)).
f = @(x,y) x;
x = 0:5;
y = 100:105;
[Xnd,Ynd] = ndgrid(x,y);
Znd = f(Xnd,Ynd);
% Case 2:
figure
surf(x,y,Znd)
xlabel('x');ylabel('y')
x % corresponds to columns of Z
x = 1×6
0 1 2 3 4 5
y % corresponds to rows of Z
y = 1×6
100 101 102 103 104 105
Znd
Znd = 6×6
0 0 0 0 0 0 1 1 1 1 1 1 2 2 2 2 2 2 3 3 3 3 3 3 4 4 4 4 4 4 5 5 5 5 5 5
For instance,
  • Znd(2,3)=1 is plotted at (x,y) = (x(3),y(2)) = (2,101)
  • Znd(3,2)=2 is plotted at (x,y) = (x(2),y(3)) = (1,102)
It is what it is, but it is not a plot of the function z=f(x,y)=x; instead it is a plot of the function z=f(x,y)=y-100, which is not the function used, so in that sense it is erroneous.
By the way (and maybe this is the crux of the matter), surf does not expect any particular format for matrices X and Y - meshgrid, ndgrid, or otherwise. Inputs X, Y and Z (all matrices) can be thought of as merely lists of points in 3d space, with points adjacent to each other in the matrices being connected in the resulting surface. I mean, you can put whatever you want and surf will take it:
Ynd(2,2) = 107.5
Ynd = 6×6
100.0000 101.0000 102.0000 103.0000 104.0000 105.0000 100.0000 107.5000 102.0000 103.0000 104.0000 105.0000 100.0000 101.0000 102.0000 103.0000 104.0000 105.0000 100.0000 101.0000 102.0000 103.0000 104.0000 105.0000 100.0000 101.0000 102.0000 103.0000 104.0000 105.0000 100.0000 101.0000 102.0000 103.0000 104.0000 105.0000
figure
surf(Xnd,Ynd,Znd)
xlabel('x');ylabel('y')
Maybe that illustrates why meshgrid-style and ndgrid-style matrix inputs give the same result.
I agree that Case 2 is erroneous wrt the mathematical function to be represented.
So I guess the upshot is:
if using x,y vector inputs, then Z must be in meshgrid format, which is important to understand if using implicit expansion to create Z instead explicit evaluation over outputs from meshgrid.
if using X,Y matrix inputs, then X/Y/Z can be in either meshgrid or ndgrid format.
Is that correct?
Interesting that surf only mentions and shows examples with meshgrid.
"if using x,y vector inputs, then Z must be in meshgrid format"
I think that's a good way to put it.
"if using X,Y matrix inputs, then X/Y/Z can be in either meshgrid or ndgrid format"
Yes, or any other format.
X and Y need not represent points on a rectangular grid at all, e.g.:
r = linspace(0.5,2.5,5).';
th = linspace(0,2*pi,9);
X = r.*cos(th)
X = 5×9
0.5000 0.3536 0.0000 -0.3536 -0.5000 -0.3536 -0.0000 0.3536 0.5000 1.0000 0.7071 0.0000 -0.7071 -1.0000 -0.7071 -0.0000 0.7071 1.0000 1.5000 1.0607 0.0000 -1.0607 -1.5000 -1.0607 -0.0000 1.0607 1.5000 2.0000 1.4142 0.0000 -1.4142 -2.0000 -1.4142 -0.0000 1.4142 2.0000 2.5000 1.7678 0.0000 -1.7678 -2.5000 -1.7678 -0.0000 1.7678 2.5000
Y = r.*sin(th)
Y = 5×9
0 0.3536 0.5000 0.3536 0.0000 -0.3536 -0.5000 -0.3536 -0.0000 0 0.7071 1.0000 0.7071 0.0000 -0.7071 -1.0000 -0.7071 -0.0000 0 1.0607 1.5000 1.0607 0.0000 -1.0607 -1.5000 -1.0607 -0.0000 0 1.4142 2.0000 1.4142 0.0000 -1.4142 -2.0000 -1.4142 -0.0000 0 1.7678 2.5000 1.7678 0.0000 -1.7678 -2.5000 -1.7678 -0.0000
Z = r.*sqrt(th);
surf(X,Y,Z,'FaceColor','interp')
view([-115 65])
copyobj(gca(),figure())
view(2)
Interesting, all of the examples in the doc use a rectangular grid.

请先登录,再进行评论。

更多回答(0 个)

类别

产品

版本

R2022a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by