Multiple Z axes in a 3d plot

100 views (last 30 days)
Debasish Sarker
Debasish Sarker on 26 May 2020
Commented: Vijay Sagar on 4 Feb 2023
Hello,
I have plot the graph using plot3. I would like to plot on the right-side axis as well.
Would you please suggest me how can I do that?
  2 Comments
Adam Danz
Adam Danz on 26 May 2020
Does that mean you want the tick labels to appear on the right and left z-axes or you want a 2nd z=axis that has a different scale than the current z-axis?
Debasish Sarker
Debasish Sarker on 26 May 2020
I want a 2nd z axis that has a different scale.

Sign in to comment.

Accepted Answer

Adam Danz
Adam Danz on 27 May 2020
Edited: Adam Danz on 27 May 2020
Matlab does not have a method of plotting in 3D with two z-axes.
To make the task even more difficult, there is no ZAxisLocation to define which side of the plot the z-axis goes even though we've got XAxisLocation and YAxisLocation.
The demo below takes the following steps.
  1. Plots data on a 3D plot
  2. Creates a 2nd axes that lays on top of the first axes in the same position.
  3. Some properties of the 2 axes are linked. Add more if needed. This will ensure that changes to one of the axes will be applied to both axes.
  4. The z-axis-limits for both axes are set. This is a very important step. You can set the z-limits to any values you want but they must be set and it must happen before setting the ticks.
  5. The z-ticks for axis #2 are computed so they align with the z-ticks from axis #1.
  6. The axis #2 is turned off.
  7. Pseudo axis ticks are created for the 2nd z axis. This uses the text() function so even though they look like real ticks, they aren't and if the axis is rotated or zoomed in, the text objects will move because they are anchored in the plot.
A lot can go wrong with this so troubleshooting will require knowing what's going on in each step. See inline comments for more detail.
ax1 = axes();
[x0,z0] = meshgrid(1:20,logspace(1,2,20));
y0 = x0;
plot3(x0.', y0, z0, '-')
grid on
box on
xlabel('x axis')
ylabel('y axis')
zlabel('z axis')
[x1,z1] = meshgrid(1:2:20,logspace(1,1.2,10));
y1 = x1;
% Define axis limits for current z-axis
% I use the current z-axis limit but it z1Lim can be any [min,max] value.
z1Lim = zlim();
% Define the axis limits for the 2nd z-axis.
% I define the 2nd z-axis limits as a scaled version of the 1st z-axis limits
% given the range of data but you can use any [min,max] value.
z2Lim = [min(z1(:)) - min(z0(:))/range(z1Lim)*range(z1(:)), ...
max(z1(:) + (1-max(z0(:))/range(z1Lim))*range(z1(:)))];
% Create duplicate axes
ax2 = axes('Position', ax1.Position);
% Plot z2 data
plot3( x1.', y1, z1, 'k-o')
% Link x and y axes, set z2 axis to
linkprop([ax1,ax2], {'XLim','YLim','Position','view'}); % Add any other properties you want to link
% Set both z axis limits. **From this point forward you cannot change any of the
% z axis scaling or ranges!
zlim(ax1, z1Lim)
zlim(ax2, z2Lim)
% Compute z2-axis ticks to match the position of z1 axis ticks
z1TickNorm = (ax1.ZTick - ax1.ZTick(1) + z1Lim(1)) ./ range(z1Lim);
z2Tick = range(z2Lim)*z1TickNorm + z2Lim(1);
ax2.ZTick = z2Tick;
% Any axes rotations or zooming must be done before setting the pseudo ticks below.
% Turn off ax2 and set ax1 tick labels to reflect both scales
ax2.Visible = 'off';
text(ax1,repmat(max(xlim(ax1)),size(ax2.ZTick)), ...
repmat(min(ylim(ax1)),size(ax2.ZTick)), ...
ax1.ZTick, strsplit((strtrim(sprintf('%.1f ', ax2.ZTick)))),...
'HorizontalAlignment','left','VerticalAlignment','middle')
% z2 axis label (1.15 factor chosen for these data)
text(ax1,max(xlim(ax1))*1.15, min(ylim(ax1))*1.15, ...
mean(z2Lim), 'Second Z axis label' ,...
'Rotation', 90)
Note that the 2nd z-axis ticks and label are text objects anchored to the plot so movement of the axes and their limits will result in the text objects moving as well:
  4 Comments
Mi Tung
Mi Tung on 11 Nov 2020
Dear guys, I have this question too. But I can't merge two surface in one with two vertical axes. Can you help me this. Below show the code for 2 surface, which I need. Many thanks for your helping.
clear all;
clc;
% the first surface
x1 = [10,11.2,12,10,11.2,12,10,11.2,12,10,11.2,12];
x2 = [60,60,60,70,70,70,82,82,82,90,90,90];
Profit = [287.355, 295.273, 256.703, 298.625, 325.227, 316.948, 338.271, 382.907, 345.791, 266.890, 308.132, 295.042];
xv = 10:0.1:12;
yv =60:1:90;
[X,Y] = ndgrid(xv, yv);
Z = griddata(x1, x2, Profit, X, Y, 'cubic');
figure
surf(X,Y,Z)
grid on
hold on
A=scatter3(x1(8),x2(8),Profit(8),'filled','MarkerFaceColor', 'y')
set(A,'SizeData',90)
x0 = x1([8 2 5 11]);
y0 = x2([8 2 5 11]);
xlabel('Velocity, m/s'), ylabel('Cargo'), zlabel('Profit, 10^3*$')
view(-120,47)
% The second surface
x1 = [10,11,12,10,10.6,12,10,10.4,12,10,11,12];
x2 = [60,60,60,69,69,69,80,80,80,90,90,90];
Profit = [287.355, 295.273, 256.703, 298.625, 325.227, 316.948, 338.271, 382.907, 345.791, 266.890, 308.132, 295.042];
Payback = [4.75, 4.22, 4.75, 3.98, 3.55, 3.86, 4.38, 4.25, 4.32, 5.45, 4.78, 5.15];
xv = 10:0.1:12;
yv =60:1:90;
[X,Y] = ndgrid(xv, yv);
Z = griddata(x1, x2, Payback, X, Y, 'cubic');
surf(X,Y,Z)
grid on
hold on
% scatter3(x1,x2,Payback,'filled')
A=scatter3(x1(5),x2(5),Payback(5),'filled','MarkerFaceColor', 'y')
xlabel('Velocity, m/s'), ylabel('Cargo, t'), zlabel('Payback, years')
set(A,'SizeData',90)
x0 = x1([8 2 5 11]);
y0 = x2([8 2 5 11]);
xlabel('Velocity, m/s'), ylabel('Cargo, ton'), zlabel('Payback, year')
view(-120,47)
Vijay Sagar
Vijay Sagar on 4 Feb 2023
@Mi Tung, it is always preferable to ask your question as a new question rather than in the comment section. This way the community may help you fast.

Sign in to comment.

More Answers (0)

Community Treasure Hunt

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

Start Hunting!