How to add a 2D plot to an existing 3D plot by sharing the same axes?
22 views (last 30 days)
Show older comments
Dear Matlab Community,
I am wondering how to replicate a plot that I have seen in a journal paper. The 3D plot can be created using various functions (mesh, contour3, surf etc.) but I am unable to add another plot in a way that they both use the same axes? Has anyone come across a solution for this?
5 Comments
dpb
on 17 Sep 2024
Edited: dpb
on 17 Sep 2024
One can (at least also superficially) make the 2D surface look as though it is only thing there with a zero height in the projection by
hF=figure;
hF.Color=0.94*hF.Color; % so will show up from default white
hAx=subplot(1,2,1);
hAx.CameraPosition=[-45.6571 -59.5015 86.6025]; % match default orthographic projection
hAx.ZAxis.Visible='off';
hold on
x=[0 1 1 0]; y=[0 0 1 1]; o=ones(size(x)); % patch coordinates to mask verticals
patch(x,o,y,hF.Color,'edgecolor','none')
patch(o,x,y,hF.Color,'edgecolor','none')
[X,Y] = meshgrid(-5:.5:5);
Z = Y.*sin(X) - X.*cos(Y);
hAx(2)=subplot(1,2,2);
hS=surf(X,Y,Z,'FaceAlpha',0.5);
pos={hAx.Position}.';
pos{1}(4)=pos{1}(4)/2;pos{2}(4)=pos{1}(4); % reduce each height by half
pos{2}(2)=pos{1}(2)+pos{1}(4); % set the bottom of RH to top of LH
set(hAx,{'Position'},pos)
As before, still don't know if one can manage to move those pieces around to get them aligned well enough to create the desired illusion or not...the background color patches to hide the other grid lines are probably going to be in the way preventing being able to see the RH axes in its entirety once the LH one is where it needs to be...
All in all, it's still going to be a lot of trial and error...MATLAB simply doesn't have such facilities and while it's an interesting intellectual challenge to see if one can make such plots, it is certainly a way to use up a lot of time that could be generally used in more productive manner...
I do not know what was used to create the figure from the paper; does it provide any hints to the tools used? I also do not know if TecPlot has such as a builtin, I let the license lapse when quit the active consulting gig while still using 32-bit OS and it won't run on this machine now to try with old version...and, that's about all the time I've got that I should spend here at the moment...
Accepted Answer
Adam Danz
on 18 Sep 2024
Edited: Adam Danz
on 19 Sep 2024
This is challenging. The reason it's challenging is because camera properties are set relative to a point in an axes, not relative to a figure. As @dpb points out, when there are multiple axes in a figure, there's no way to rotate a camera to view the tiled arrangments from a certain perspective.
Your only hope that I can imagine to do this in MATLAB is to put the content on the same axes.
Here's a quick and sloppy demo that touches upon the start of a solution. Where it falls short is drawing a 2nd y axis and a 2nd z axis. It's also sensitive to the figure size and other properties so it needs tweaked.
% Generate ridgeline
ridgelineData = nan(300,200);
x = linspace(-1,1,200);
sigma = 0.16; % width of the pulse
gaus = exp(-x.^2/(2*sigma.^2));
for i = 1:height(ridgelineData)
n = rand(size(gaus));
offset = 0.33; % to allow variation near y=0
ridgelineData(i,:) = smoothdata((gaus+offset).*n,'gaussian',16)-offset;
end
xdata = linspace(9,35,width(ridgelineData));
ydata = 1:height(ridgelineData);
vertOffsets = (height(ridgelineData)-1)*5 : -5 : 0;
% Generate the flat 2D data
flatData = ridgelineData;
ax = axes();
view(3)
hold on
for i = 1:height(ridgelineData)
yvec = vertOffsets(i) .* ones(width(ridgelineData),1);
patch(xdata', yvec, ridgelineData(i,:)', [0.066 0.443 0.745],EdgeColor='none')
plot3(xdata',yvec,ridgelineData(i,:),'w-')
end
xlim(ax,"tight")
ylim(ax,"tight")
zlim(ax,"tight")
minX = ax.XLim(1);
minZ = ax.ZLim(1); % this is where the 2D image will go
ax.ZLim(2) = 10; % To mimick the image in the question
% make room for a flat 2D surface on XY next to the existing content
% Xlim is set to tight so xlim can be used to get the extent of the data.
% How wide should the strip be (in x-data units)
stripWidth = 7;
% How wide should the gap be between the strip and the main data (in x-data units)
stripGap = 3;
% Set the new xlim that makes room for the strip.
ax.XLim(1) = ax.XLim(1) - stripWidth - stripGap;
% Plot the flat surface
xExtent = ax.XLim(1) + [0,stripWidth];
yExtent = ax.YLim; % when axes are tight
S = surf(linspace(xExtent(1),xExtent(2),width(flatData)), ...
linspace(yExtent(1),yExtent(2),height(flatData)), ...
zeros(size(flatData))+minZ, ...a
flatData, ...
'EdgeColor', 'none', ...
'Clipping','off'); % Needed so it doesn't disappear when xlim changes
% Cosmetics
ax.Color = 'none';
ax.XLim(1) = minX;
% You may need to shrink the axes if anything is extending beyond the
% figure
ax.OuterPosition = [.05 .05 .9 .9];
3 Comments
Adam Danz
on 18 Sep 2024
If you create two axes and then combine them in an image editor outside of MATLAB, here are some tips to get both axes to look right.
- Set TickDir to out in the 2D axes so the ticks look the same as the 3D axes
- Use the same yticks and limits for the shared axes (y, I think)
- Set the same view and, probably, camera properties
- the plotbox and data aspect ratios should probably match between the two axes
More Answers (0)
See Also
Categories
Find more on Graphics Performance in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!