How do I mark (or) shade the area below the graph of Surface plot in Matlab?
You can add the extra surfaces by building up a new set of matrices to pass to surf
, with a few different options based on how you want the results to look...
Option #1: Fill the sides, one surface object:
If you want to just fill in the sides, you can add a new row and column on each side of your matrices like so:
[R, C] = size(Z);
Xfill = [nan X(1, :) nan; X(:, [1 1:C C]); nan X(R, :) nan];
Yfill = [nan Y(1, :) nan; Y(:, [1 1:C C]); nan Y(R, :) nan];
Zfill = [nan zeros(1, C) nan; zeros(R, 1) Z zeros(R, 1); nan zeros(1, C) nan];
surf(Xfill, Yfill, Zfill);
view(-120, 30);
This allows you to plot the surface and sides with a single call to surf
, with this result:
Option #2: Fill the sides and bottom, one surface object:
If you would also like to fill in the bottom of the shape, you can wrap the surface around and under itself by adding new columns and then add a new row at the top and bottom to close the ends:
[R, C] = size(Z);
Xfill = [X(1, 1:C) nan(1, C+1); ... % Close top
X flip(X, 2) X(:, 1); ... % Flip data and connect to other side
X(R, 1:C) nan(1, C+1)]; % Close bottom
Yfill = [Y(1, 1:C) nan(1, C+1); ...
Y flip(Y, 2) Y(:, 1); ...
Y(R, 1:C) nan(1, C+1)];
Zfill = [zeros(1, C) nan(1, C+1); ...
Z zeros(R, C) Z(:, 1); ...
zeros(1, C) nan(1, C+1)];
surf(Xfill, Yfill, Zfill);
view(-120, -20);
Again, you can plot the entire closed surface with a single call to surf
. Here's the view from the underside, showing the closed bottom:
Option #3: Add a separate surface object for the sides:
When plotting everything as one object, you're limited if you want to render the sides differently than the top. Making the sides separate objects like Ander does (using patch
or a separate call to surf
) will give you more control over how they are colored relative to the top surface. To make a single surface object for all four of your sides, you can extract the entries around the edges of your matrices and replicate them as needed:
[R, C] = size(Z);
Xside = [1; 1]*[X(1, :) ... % Get first row
X(2:R, C).' ... % Get last column, without first row
X(R, (C-1):-1:1) ... % Get last row, without last column, flipped
X((R-1):-1:1, 1).']; % Get first column, without last row, flipped
Yside = [1; 1]*[Y(1, :) ...
Y(2:R, C).' ....
Y(R, (C-1):-1:1) ...
Y((R-1):-1:1, 1).'];
Zside = [Z(1, :) ...
Z(2:R, C).' ...
Z(R, (C-1):-1:1) ...
Z((R-1):-1:1, 1).'; ...
zeros(1, 2*(R+C)-3)];
surf(X, Y, Z); % Plot top surface
hold on;
surf(Xside, Yside, Zside, ... % Plot all four sides...
'EdgeColor', 'none', ... % with no edge coloring (i.e. grid)...
'FaceAlpha', 0.5); % and transparency
view(-120, 30);
And the resulting plot:
The only way I can think is by looping over the edges, and filling them accordingly.
[X,Y] = meshgrid(1:0.5:10,1:20);
Z = X.* sqrt(Y);
figure;
p=parula; % please do not use jet :(
surf(X,Y,Z)
hold on;
%XZ init
for ii=1:size(Z,2)-1
patch([X(1,ii) X(1,ii+1) X(1,ii+1) X(1,ii)],...
[Y(1,1) Y(1,1) Y(1,1) Y(1,1)],...
[0 0 Z(1,ii+1) Z(1,ii) ],[p(1,:)]);
end
%XZ end
for ii=1:size(Z,2)-1
patch([X(end,ii) X(end,ii+1) X(end,ii+1) X(end,ii)],...
[Y(end,1) Y(end,1) Y(end,1) Y(end,1)],...
[0 0 Z(end,ii+1) Z(end,ii) ],[p(1,:)]);
end
%YZ init
for ii=1:size(Z,1)-1
patch([X(1,1) X(1,1) X(1,1) X(1,1)],...
[Y(ii,1) Y(ii+1,1) Y(ii+1,1) Y(ii,1)],...
[0 0 Z(ii+1,1) Z(ii,1) ],[p(1,:)]);
end
%YZ end
for ii=1:size(Z,1)-1
patch([X(1,end) X(1,end) X(1,end) X(1,end)],...
[Y(ii,end) Y(ii+1,end) Y(ii+1,end) Y(ii,end)],...
[0 0 Z(ii+1,end) Z(ii,end) ],[p(1,:)]);
end
colorbar
xlabel('Distance between two spatial points \xi_i & \xi_j (\xi_i - \xi_j)');
ylabel('Density(\rho)');
zlabel('Transmission Delay (t_t)');
There are a lot of style choices you can make now, like removing edges or changing the colors that I will leave to you as they can be found online.
If this is not exactly what you wanted, its still pretty much the way to do it. Using patch
and appropriate coordinates.
Here's another way of using patch
objects.
This solution is very similar to Ander's, but the patch
construction is handled differently, so you don't need to loop and end up with only 4 patch entities to handle.
%% Prepare domain limits
xLim = [1 10] ; xStep = 0.5 ;
yLim = [1 20] ; yStep = 1 ;
x = xLim(1):xStep:xLim(2) ;
y = yLim(1):yStep:yLim(2) ;
%% Your code
[X,Y] = meshgrid(x,y);
Z = X.* sqrt(Y);
figure;
surf(X,Y,Z)
colorbar
xlabel('Distance between two spatial points \xi_i & \xi_j (\xi_i - \xi_j)');
ylabel('Density(\rho)');
zlabel('Transmission Delay (t_t)');
%% prepare patch elements
zLim = [min(Z) max(Z)] ;
pcol = [0.2857,1,0.7143] ;
xface = [ x xLim(2) xLim(1) ] ;
yface = [ y yLim(2) yLim(1) ] ;
xface0 = zeros(size(xface)) ;
yface0 = zeros(size(yface)) ;
xfaceZ = [zeros(size(x)) zLim(1) zLim(1)] ;
yfaceZ = [zeros(size(y)) zLim(1) zLim(1)] ;
%% display the patches
hp(1) = patch( xface , xface0+yLim(1) , xfaceZ ,pcol ) ;
hp(3) = patch( xface , xface0+yLim(2) , xfaceZ ,pcol ) ;
hp(2) = patch( yface0+xLim(1) , yface , yfaceZ ,pcol ) ;
hp(4) = patch( yface0+xLim(2) , yface , yfaceZ ,pcol ) ;
%% update top edge of patches
% to connect to the surface edges
hp(1).ZData(1:end-2) = Z(1,:) ;
hp(2).ZData(1:end-2) = Z(:,1) ;
hp(3).ZData(1:end-2) = Z(end,:) ;
hp(4).ZData(1:end-2) = Z(:,end) ;
%% Color according to preferences
set(hp, 'Facecolor',pcol , 'FaceAlpha',0.5 , 'EdgeColor','none')
Will render: