Why is my legend position changing to normalized entries?

2 views (last 30 days)
I have a figure created with a 3x1 tiledlayout, and I want to move the legend of each plot closer to the edge. For that I change the Legend Units to centimeters and increment the X and Y coordinates. Here is an example:
t = (0:30:(2880-1)*30)./3600;
errPos = 0.2*randn(2880,3);
h_fig = figure;
tiledlayout(3,1, 'Padding', 'compact', 'TileSpacing', 'none');
nexttile;
plot(t,errPos(:,1),'-','LineWidth',0.9); grid on; axis([-inf inf -1 1]); hold on;
h_leg_1 = legend(['RMSE = ' num2str(rms(errPos(:,1))*100,3) ' [cm]']); legend('boxoff');
ylabel('\Delta r_R [m]');
h_axis_1 = gca;
nexttile;
plot(t,errPos(:,2),'-','LineWidth',0.9); grid on; axis([-inf inf -1 1]); hold on;
h_leg_2 = legend(['RMSE = ' num2str(rms(errPos(:,2))*100,3) ' [cm]']); legend('boxoff');
ylabel('\Delta r_T [m]');
h_axis_2 = gca;
nexttile;
plot(t,errPos(:,3),'-','LineWidth',0.9); grid on; axis([-inf inf -1 1]); hold on;
h_leg_3 = legend(['RMSE = ' num2str(rms(errPos(:,3))*100,3) ' [cm]']); legend('boxoff');
ylabel('\Delta r_N [m]');
xlabel('Time [h]');
h_axis_3 = gca;
h_fig.Units = 'centimeters';
h_fig.InnerPosition = [10.05 10.05 8.2 9.9];
h_fig.OuterPosition = [10 10 8.4 10];
h_fig.PaperPositionMode = 'manual';
h_fig.PaperPosition = [10 10 8.4 10];
h_fig.PaperSize = [8.4 9];
h_axis_1.FontSize = 10;
h_axis_2.FontSize = 10;
h_axis_3.FontSize = 10;
h_axis_1.XAxis.TickLabels = [];
h_axis_2.XAxis.TickLabels = [];
h_axis_1.YLabel.VerticalAlignment = 'baseline';
h_axis_2.YLabel.VerticalAlignment = 'baseline';
h_axis_3.YLabel.VerticalAlignment = 'baseline';
oldPos1_norm = h_axis_1.Legend.Position;
h_axis_1.Legend.Units = 'centimeters';
oldPos1 = h_axis_1.Legend.Position;
h_axis_1.Legend.Position = oldPos1 + [0.3 0.3 0 0];
% h_axis_1.Legend.Position = oldPos1 + [0.3 0.3 0 0]; % See below the explanation for the duplicate
oldPos2_norm = h_axis_2.Legend.Position;
h_axis_2.Legend.Units = 'centimeters';
oldPos2 = h_axis_2.Legend.Position;
h_axis_2.Legend.Position = oldPos2 + [0.3 0.3 0 0];
% h_axis_2.Legend.Position = oldPos2 + [0.3 0.3 0 0];
oldPos3_norm = h_axis_3.Legend.Position;
h_axis_3.Legend.Units = 'centimeters';
oldPos3 = h_axis_3.Legend.Position;
h_axis_3.Legend.Position = oldPos3 + [0.3 0.3 0 0];
% h_axis_3.Legend.Position = oldPos3 + [0.3 0.3 0 0];
The problem is that when I look at the 4 new entries of the Position I see a "mix" of units, where the X,Y coordinates are in centimeters, but the width and height entries are the ones that it had first when the Legend Units were in 'normalized'. However, Units is currently set in 'centimeters', so the legend is "trying" to be super small.
Inspecting the variables I see:
oldPos1_norm =
0.4220 0.8687 0.4950 0.0702
oldPos1 =
3.3612 6.3632 3.9423 0.5292
h_axis_1.Legend.Position =
3.6612 6.6632 0.4950 0.0702
Which is even more strange is that the behavior is different when I try to execute the script with a breakpoint before the changes, and steping one line at a time. In that case, if I uncomment the duplicated lines, the first one gives the legend that we got before, but the second one gives the intended result, h_axis_1.Legend.Position is equal to oldPos1 + [0.3 0.3 0 0]. However, this is not the case if I run the script all at once with the duplicated lines uncommented. Executing that line in the command window twice also gives the same result.
I can get the intended result manually executing that, but I would like to have this as part of the script for a large amount of figures and I don't know if I am missing something.
Thanks in advance!
  1 Comment
Adam Danz
Adam Danz on 17 Jan 2022
The documentation states that the legend position property has no effect when the parent container is a TiledChartLayout object but I don't know whether this only pertains to legends assigned to a tile such as leg.Layout.Tile='north' or all legends in any tile including axes like in your example. Legends assigned to axes in tiledlayout also have a TiledChartLayout parent.
Either way, there appears to be a bug. Either 1) the documentation is correct and the position assignment should have no effect at all in your example, or 2) the documentation isn't precise and we should be able to adjust legend positions in some cases using tiledlayout but it's not working as expected, or 3) both 1 and 2 are bugs. Note that legend behave oddly outside of tiledlayout when their widths or heights become too small.
I suggest contacting tech support to report this issue - feel free to point to this thread.
axes()
plot(0:.1:1,0:.1:1)
xline(.5)
yline(.5)
leg = legend();
% Show original legend position with annotation box
an = annotation('textbox',leg.Position,'String','Original','EdgeColor','r');
% Update legend size
leg.Position(3:4) = [0.01, 0.01];

Sign in to comment.

Answers (0)

Products


Release

R2020b

Community Treasure Hunt

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

Start Hunting!