%% New in MATLAB R2021a: Auto rotation of axis tick labels
% Matlab Central Community Highlight
% Author: Adam Danz
% 20 May 2021
% Table of Contents
% Auto rotation of axis tick labels
%     Demo: varying tick density and length of tick labels
%     Demo: Changes to axis view angle and rotation
% What if I don't want auto-rotation?
%% Auto rotation of axis tick labels
%
% Starting in MATLAB R2021a axis tick labels will auto-rotate to avoid overlap when the user manually specifies ticks or tick labels (release notes).  In custom visualization functions, the tick label density or tick label lengths may be variable and unknown.  The new auto-rotation feature removes the burden of detecting the need to rotate manually-set labels and eliminates the need to manually rotate them.
% Many properties and combinations of properties can cause tick labels to overlap if they are not rotated.
% Length of tick labels
% Number of tick labels
% Interval between tick labels
% Font size
% Font name
% Figure size
% Axes size
% Viewing angle of the axes
% MathWorks gnomes
%% Demo: varying tick density and length of tick labels
% These 9 axes vary by the number of x-ticks and length of x-tick-labels.  MATLAB auto-rotates the labels when needed.

rng('default')
fig = figure('Units','pixels'); 
fig.Position(3:4) = [710 575]; 
movegui(fig)
tlo = tiledlayout(fig,3,3);
nTicks = [3,4,10].*ones(3,1); 
nChar = [2;4;9].*ones(1,3); 
ax = gobjects(size(nTicks)); 
rotTxt = ax; 
asc = [65:90, 97:122]; 
genChars = @(m,n)string(char(asc(randi(numel(asc), m, n))));  
for i = 1:9
    ax(i) = nexttile(tlo); 
    set(ax(i), 'XLim', [0,1], ...
        'YLim', [0,1],...
        'XTick', linspace(0,1,nTicks(i)), ...
        'XTickLabel', genChars(nTicks(i),nChar(i)),...
        'TickDir','out',...
        'YTick',[],...
        'FontName','fixedwidth', ...
        'FontWeight','bold');
    text(ax(i), .5, .995, ...
        sprintf('%d ticks\n%d chars', nTicks(i), nChar(i)), ...
        'HorizontalAlignment', 'Center', 'VerticalAlignment', 'Top',...
        'FontSize', 9)
    rotTxt(i) = text(ax(i), .5, 0.05, '', ...
        'HorizontalAlignment', 'Center', 'VerticalAlignment', 'Bottom',...
        'FontSize', 9);
end
xlabel(tlo, 'Number of characters','FontSize',16,'FontWeight','bold')
ylabel(tlo, 'Number of labels','FontSize',16,'FontWeight','bold')
title(tlo, 'Auto tick label rotation','FontSize',18,'FontWeight','bold')
grid(ax,'on') % <-- also new in 21a
box(ax,'on') % <-- also new in 21a
fig.SizeChangedFcn = @(~,~)updateRotationTextFcn(ax,rotTxt);
updateRotationTextFcn(ax,rotTxt);

%

function updateRotationTextFcn(ax,rotTxt)
% SizeChangedFcn for figure; called when figure size is changed. 
% Updates text labels (rotTxt) in each axes (ax) showing x-label-rotation angle. 
for i = 1:numel(rotTxt)
    rotTxt(i).String = sprintf('Angle: %.0f',ax(i).XTickLabelRotation); 
end
end

%% Demo: Changes to axis view angle and rotation
% The auto-rotation feature updates the label angles as the axes change programmatically or during user interaction.
%
%% What if I don't want auto-rotation?
% Auto-rotation mode is on by default for each X|Y|Z axis.  When the tick label rotation angle is manually set from the X|Y|ZTickLabelRotation property of axes or by using xtickangle | ytickangle | ztickangle, auto-rotation is turned off.  Auto-rotation can also be turned off by setting the X|Y|ZTickLabelRotationMode axis property to manual but it's important to also hold the axis properties so that the rotation mode does not revert to the default value, auto.
% If you're looking for a broader method of reverting to older behavior you can set the default label rotation mode to manual at the start of a function that produces multiple plots and then revert to the factory default rotation mode at the end of the file (consider using onCleanup).
% set(groot,'defaultAxesXTickLabelRotationMode','manual')
% set(groot,'defaultAxesYTickLabelRotationMode','manual')
% set(groot,'defaultAxesZTickLabelRotationMode','manual')
%
% % Revert to factory-default
% set(groot,'defaultAxesXTickLabelRotationMode','remove')
% set(groot,'defaultAxesYTickLabelRotationMode','remove')
% set(groot,'defaultAxesZTickLabelRotationMode','remove')
%