matlab 图例仅影响其中一个链接轴

slwdgvem  于 2023-03-19  发布在  Matlab
关注(0)|答案(2)|浏览(146)

下面的MVCE重现了我在具有多个轴对象的地物中显示图例时遇到的问题。
为了绘制地形的高程剖面图,我使用两个轴:

  • ax(1)表示背景中的天空
  • ax(2)表示前景中的地形

在绘制任务期间,我独立地使用每组轴,在过程结束时,我使用linkaxes(ax, 'xy')链接ax(1)ax(2),以便它们在维度上保持同步。
最后,我在'southoutside'位置添加了legend,但只有前景轴会自动收缩,以便为图例留出空间,背景轴保持不变,从而干扰了预期布局,如下图所示:

使用linkaxes的真正目的就是防止这种不良行为。
如果有人能就如何解决这个问题提供一些启示,我将不胜感激。

更新

作为对gnovice评论的回应:
我之所以使用两个坐标轴是因为我认为这是在同一个图中合并不同颜色Map表的唯一可能的方法,注意,对于天空,我使用sky_map,对于地形,我使用demcmap函数设置不同的颜色Map表。
编号

% Create figure.
figure;

% Create background axes for the sky.
ax(1) = axes;

% Sky data for background.
x_bg = [0, 0, 10, 10];
y_bg = [0, 10, 10, 0];

% Fill sky with color gradient on y-axis.
fill(x_bg, y_bg, y_bg);

% Generate custom sky colormap.
sky_map = interp1([0, 1], [135, 206, 235; 255, 255, 255]./255, linspace(0, 1, 255));

% Apply sky colormap.
colormap(ax(1), sky_map);

% Create foreground axes for the terrain.
ax(2) = axes;

% Terrain data.
x = [0, 0:10, 10];
y = [0, 5*rand(size(0:10)), 0];

% Fill terrain.
fill(x, y, y);

% Sets the colormap and color axis limits based on the elevation data
% limits.
demcmap(y);

% Link x-axis and y-axis of ax(1) and ax(2).
linkaxes(ax, 'xy');

% Hide ax(1).
set(ax(1), 'Visible', 'off');

% Transparent background for ax(2).
set(ax(2), 'Color', 'none');

% Display title.
title('Vertical Profile');

% Display legend underneath.
legend('Terrain', 'Location', 'southoutside');
bweufnob

bweufnob1#

方法1:使用两个轴和linkprop

引用挖掘者的评论:
linkaxes只同步轴限制。您需要将属性(如Position)与linkprop同步
在调用legend之前添加linkprop(ax, 'Position');
结果:

顺便说一句,如果你想了解更多,我建议阅读“Using linkaxes vs. linkprop“从未记录的Matlab,特别是为了解决问题的linkaxes被覆盖对方。
代码:

% Create figure.
figure;

% Create background axes for the sky.
ax(1) = axes;

% Sky data for background.
x_bg = [0, 0, 10, 10];
y_bg = [0, 10, 10, 0];

% Fill sky with color gradient on y-axis.
fill(x_bg, y_bg, y_bg);

% Generate custom sky colormap.
sky_map = interp1([0, 1], [135, 206, 235; 255, 255, 255]./255, linspace(0, 1, 255));

% Apply sky colormap.
colormap(ax(1), sky_map);

% Create foreground axes for the terrain.
ax(2) = axes;

% Terrain data.
x = [0, 0:10, 10];
y = [0, 5*rand(size(0:10)), 0];

% Fill terrain.
fill(x, y, y);

% Sets the colormap and color axis limits based on the elevation data
% limits.
demcmap(y);

% Link x-axis and y-axis limits of ax(1) and ax(2).
linkaxes(ax, 'xy');

% Link Position property of ax(1) and ax(2).
linkprop(ax, 'Position');

% Hide ax(1).
set(ax(1), 'Visible', 'off');

% Transparent background for ax(2).
set(ax(2), 'Color', 'none');

% Display title.
title('Vertical Profile');

% Display legend underneath.
legend('Terrain', 'Location', 'southoutside');

方法二:使用一个轴并修改'FaceVertexCData'

引用gnovice的评论1和2:
我不得不问...为什么你要用两个坐标轴?你不能在同一个坐标轴上绘制两个填充多边形,然后修改每个面片的ZData属性以确保它们正确分层吗?
多个对象需要自己的色彩Map表是很棘手的,但是你通常可以通过定义对象颜色来解决这个问题,使它们成为RGB颜色而不是色彩Map表索引。例如,你使用的fill命令实际上只是创建patch对象,所以对于天空背景你可以直接创建一个面片对象。特别注意你如何定义C输入参数。天空可以不用颜色Map表,所以地形可以使用它。
对于天空部分,将fill替换为patch并设置hold on,然后使用真彩色RGB值数组修改'FaceVertexCData'属性(请参见Patch Properties)。
在下面的代码中,真彩色数组称为CData,定义如下:

% True color array.
CData = [sky_map(1, :); sky_map(end, :); sky_map(end, :); sky_map(1, :)];

看起来像这样

CData =

    0.5294    0.8078    0.9216
    1.0000    1.0000    1.0000
    1.0000    1.0000    1.0000
    0.5294    0.8078    0.9216

然后使用带有修补程序句柄h1set

% Apply sky colormap to 'FaceVertexCData' property.
set(h1, 'FaceVertexCData', CData);

结果:

代码:

% Create figure.
figure;

% Sky data for background.
x_bg = [0, 0, 10, 10];
y_bg = [0, 10, 10, 0];

% Sky indexed colors.
c_bg = [0, 1, 1, 0];

% Patch sky using default colormap (parula).
h1 = patch(x_bg, y_bg, c_bg);

% Generate custom sky colormap.
sky_map = interp1([0, 1], [135, 206, 235; 255, 255, 255]./255, linspace(0, 1, 255));

% True color array.
CData = [sky_map(1, :); sky_map(end, :); sky_map(end, :); sky_map(1, :)];

% Apply sky colormap to 'FaceVertexCData' property.
set(h1, 'FaceVertexCData', CData);

% Retain sky patch in the current axes.
hold on;

% Terrain data.
x = [0, 0:10, 10];
y = [0, 5*rand(size(0:10)), 0];

% Fill terrain.
h2 = fill(x, y, y);

% Sets the colormap and color axis limits based on the elevation data
% limits.
demcmap(y);

% Display title.
title('Vertical Profile');

% Display legend underneath.
legend(h2, 'Terrain', 'Location', 'southoutside');

差异

请注意,方法1和方法2生成的结果非常相似,但并不相同:
方法一:

  • 稍小的数字。
  • 刻度线可见。
  • 图例背景为灰色。

方法二:

  • 体型稍大。
  • 刻度线不可见。
  • 图例背景为白色。
dxpyg8gm

dxpyg8gm2#

可以在同一个图上使用2个色彩Map表,解决方法如下。主要思想是将所有要使用的色彩Map表连接在一个色彩Map表中,然后选择要使用的色彩Map表部分:

maxHight = 5;
xmax = 10;
% Sky data for background:
x_bg = [0, 0, 1, 1];
y_bg = [0, 1, 1, 0];

% Terrain data:
x = [0 0:xmax xmax];
y = [0 maxHight*rand(size(x(2:end-1))) 0];

% Custom sky colormap:
sky_map = interp1([0, 1], [135, 206, 235; 255, 255, 255]./255, linspace(0, 1, 255));

% Terrain colormap:
tmap = demcmap(y);

% concat both colormaps:
cmap = [tmap;sky_map];

% use the new colormap on the figure:
colormap(cmap);

% Create background axes for the sky:
ax(1) = axes;

% plot the sky as a patch:
patch(x_bg,y_bg,y_bg,'LineStyle','none')

% define the part of the colormap to use:
ax(1).CLim = [-(size(sky_map)/size(cmap)) 1];

% Create foreground axes for the terrain:
ax(2) = axes;

% plot the terrain as a patch:
patch(ax(2),x,y,y)

% define the part of the colormap to use:
ax(2).CLim = [0 max(y)*(size(cmap)/size(tmap))];

% set the limits and axes visibility:
ylim([1 2*maxHight])
ax(1).Visible = 'off';
ax(2).Color = 'none';
linkprop(ax,'position');

% Display title.
title('Vertical Profile');

% Display legend underneath.
legend('Terrain', 'Location', 'southoutside');

它会给予你这个数字:

相关问题