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

22 ビュー (過去 30 日間)
Philipp
Philipp 2024 年 9 月 15 日
編集済み: Adam Danz 2024 年 9 月 19 日
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 件のコメント
dpb
dpb 2024 年 9 月 17 日
編集済み: dpb 2024 年 9 月 17 日
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 2024 年 9 月 17 日
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!

サインインしてコメントする。

採用された回答

Adam Danz
Adam Danz 2024 年 9 月 18 日
編集済み: Adam Danz 2024 年 9 月 19 日
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 件のコメント
Adam Danz
Adam Danz 2024 年 9 月 18 日
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 2024 年 9 月 19 日
That's clever, Adam! :)
I figured if anybody would, it would be you...

サインインしてコメントする。

その他の回答 (0 件)

カテゴリ

Help Center および File ExchangeGraphics Performance についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by