How to add a 2D plot to an existing 3D plot by sharing the same axes?

23 visualizzazioni (ultimi 30 giorni)
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 Commenti
dpb
dpb il 17 Set 2024
Modificato: dpb il 17 Set 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...
Philipp
Philipp il 17 Set 2024
Dear @dpb This has already been helpful! I will see to tighten the space betwee plots or else superimpose these plots so as to align them closely. I will fiddle my way around! I may plot my answer in the coming days depending on being successful or not!

Accedi per commentare.

Risposta accettata

Adam Danz
Adam Danz il 18 Set 2024
Modificato: Adam Danz il 19 Set 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 Commenti
Adam Danz
Adam Danz il 18 Set 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
dpb
dpb il 19 Set 2024
That's clever, Adam! :)
I figured if anybody would, it would be you...

Accedi per commentare.

Più risposte (0)

Categorie

Scopri di più su Graphics Performance in Help Center e File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by