You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
233 lines
7.5 KiB
233 lines
7.5 KiB
3 years ago
|
function hfig = tightfig(hfig)
|
||
|
% tightfig: Alters a figure so that it has the minimum size necessary to
|
||
|
% enclose all axes in the figure without excess space around them.
|
||
|
%
|
||
|
% Note that tightfig will expand the figure to completely encompass all
|
||
|
% axes if necessary. If any 3D axes are present which have been zoomed,
|
||
|
% tightfig will produce an error, as these cannot easily be dealt with.
|
||
|
%
|
||
|
% Input
|
||
|
%
|
||
|
% hfig - handle to figure, if not supplied, the current figure will be used
|
||
|
% instead.
|
||
|
%
|
||
|
%
|
||
|
|
||
|
if nargin == 0
|
||
|
hfig = gcf;
|
||
|
end
|
||
|
|
||
|
% There can be an issue with tightfig when the user has been modifying
|
||
|
% the contnts manually, the code below is an attempt to resolve this,
|
||
|
% but it has not yet been satisfactorily fixed
|
||
|
% origwindowstyle = get(hfig, 'WindowStyle');
|
||
|
set(hfig, 'WindowStyle', 'normal');
|
||
|
|
||
|
% 1 point is 0.3528 mm for future use
|
||
|
|
||
|
% get all the axes handles note this will also fetch legends and
|
||
|
% colorbars as well
|
||
|
hax = findall(hfig, 'type', 'axes');
|
||
|
% TODO: fix for modern matlab, colorbars and legends are no longer axes
|
||
|
hcbar = findall(hfig, 'type', 'colorbar');
|
||
|
hleg = findall(hfig, 'type', 'legend');
|
||
|
|
||
|
% get the original axes units, so we can change and reset these again
|
||
|
% later
|
||
|
origaxunits = get(hax, 'Units');
|
||
|
|
||
|
% change the axes units to cm
|
||
|
set(hax, 'Units', 'centimeters');
|
||
|
|
||
|
pos = [];
|
||
|
ti = [];
|
||
|
|
||
|
% get various position parameters of the axes
|
||
|
if numel(hax) > 1
|
||
|
% fsize = cell2mat(get(hax, 'FontSize'));
|
||
|
ti = cell2mat(get(hax,'TightInset'));
|
||
|
pos = [pos; cell2mat(get(hax, 'Position')) ];
|
||
|
else
|
||
|
% fsize = get(hax, 'FontSize');
|
||
|
ti = get(hax,'TightInset');
|
||
|
pos = [pos; get(hax, 'Position') ];
|
||
|
end
|
||
|
|
||
|
if ~isempty (hcbar)
|
||
|
|
||
|
set(hcbar, 'Units', 'centimeters');
|
||
|
|
||
|
% colorbars do not have tightinset property
|
||
|
for cbind = 1:numel(hcbar)
|
||
|
% fsize = cell2mat(get(hax, 'FontSize'));
|
||
|
[cbarpos, cbarti] = colorbarpos (hcbar);
|
||
|
|
||
|
pos = [pos; cbarpos];
|
||
|
ti = [ti; cbarti];
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if ~isempty (hleg)
|
||
|
|
||
|
set(hleg, 'Units', 'centimeters');
|
||
|
|
||
|
% legends do not have tightinset property
|
||
|
if numel(hleg) > 1
|
||
|
% fsize = cell2mat(get(hax, 'FontSize'));
|
||
|
pos = [pos; cell2mat(get(hleg, 'Position')) ];
|
||
|
else
|
||
|
% fsize = get(hax, 'FontSize');
|
||
|
pos = [pos; get(hleg, 'Position') ];
|
||
|
end
|
||
|
ti = [ti; repmat([0,0,0,0], numel(hleg), 1); ];
|
||
|
end
|
||
|
|
||
|
% ensure very tiny border so outer box always appears
|
||
|
ti(ti < 0.1) = 0.15;
|
||
|
|
||
|
% we will check if any 3d axes are zoomed, to do this we will check if
|
||
|
% they are not being viewed in any of the 2d directions
|
||
|
views2d = [0,90; 0,0; 90,0];
|
||
|
|
||
|
for i = 1:numel(hax)
|
||
|
|
||
|
set(hax(i), 'LooseInset', ti(i,:));
|
||
|
% set(hax(i), 'LooseInset', [0,0,0,0]);
|
||
|
|
||
|
% get the current viewing angle of the axes
|
||
|
[az,el] = view(hax(i));
|
||
|
|
||
|
% determine if the axes are zoomed
|
||
|
iszoomed = strcmp(get(hax(i), 'CameraViewAngleMode'), 'manual');
|
||
|
|
||
|
% test if we are viewing in 2d mode or a 3d view
|
||
|
is2d = all(bsxfun(@eq, [az,el], views2d), 2);
|
||
|
|
||
|
if iszoomed && ~any(is2d)
|
||
|
error('TIGHTFIG:haszoomed3d', 'Cannot make figures containing zoomed 3D axes tight.')
|
||
|
end
|
||
|
|
||
|
end
|
||
|
|
||
|
% we will move all the axes down and to the left by the amount
|
||
|
% necessary to just show the bottom and leftmost axes and labels etc.
|
||
|
moveleft = min(pos(:,1) - ti(:,1));
|
||
|
|
||
|
movedown = min(pos(:,2) - ti(:,2));
|
||
|
|
||
|
% we will also alter the height and width of the figure to just
|
||
|
% encompass the topmost and rightmost axes and lables
|
||
|
figwidth = max(pos(:,1) + pos(:,3) + ti(:,3) - moveleft);
|
||
|
|
||
|
figheight = max(pos(:,2) + pos(:,4) + ti(:,4) - movedown);
|
||
|
|
||
|
% move all the axes
|
||
|
for i = 1:numel(hax)
|
||
|
|
||
|
set(hax(i), 'Position', [pos(i,1:2) - [moveleft,movedown], pos(i,3:4)]);
|
||
|
|
||
|
end
|
||
|
|
||
|
for i = 1:numel(hcbar)
|
||
|
|
||
|
set(hcbar(i), 'Position', [pos(i+numel(hax),1:2) - [moveleft,movedown], pos(i+numel(hax),3:4)]);
|
||
|
|
||
|
end
|
||
|
|
||
|
for i = 1:numel(hleg)
|
||
|
|
||
|
set(hleg(i), 'Position', [pos(i+numel(hax)+numel(hcbar),1:2) - [moveleft,movedown], pos(i+numel(hax)+numel(hcbar),3:4)]);
|
||
|
|
||
|
end
|
||
|
|
||
|
origfigunits = get(hfig, 'Units');
|
||
|
|
||
|
set(hfig, 'Units', 'centimeters');
|
||
|
|
||
|
% change the size of the figure
|
||
|
figpos = get(hfig, 'Position');
|
||
|
|
||
|
set(hfig, 'Position', [figpos(1), figpos(2), figwidth, figheight]);
|
||
|
|
||
|
% change the size of the paper
|
||
|
set(hfig, 'PaperUnits','centimeters');
|
||
|
set(hfig, 'PaperSize', [figwidth, figheight]);
|
||
|
set(hfig, 'PaperPositionMode', 'manual');
|
||
|
set(hfig, 'PaperPosition',[0 0 figwidth figheight]);
|
||
|
|
||
|
% reset to original units for axes and figure
|
||
|
if ~iscell(origaxunits)
|
||
|
origaxunits = {origaxunits};
|
||
|
end
|
||
|
|
||
|
for i = 1:numel(hax)
|
||
|
set(hax(i), 'Units', origaxunits{i});
|
||
|
end
|
||
|
|
||
|
set(hfig, 'Units', origfigunits);
|
||
|
|
||
|
% set(hfig, 'WindowStyle', origwindowstyle);
|
||
|
|
||
|
end
|
||
|
|
||
|
|
||
|
function [pos, ti] = colorbarpos (hcbar)
|
||
|
|
||
|
% 1 point is 0.3528 mm
|
||
|
|
||
|
pos = hcbar.Position;
|
||
|
ti = [0,0,0,0];
|
||
|
|
||
|
if ~isempty (strfind (hcbar.Location, 'outside'))
|
||
|
|
||
|
if strcmp (hcbar.AxisLocation, 'out')
|
||
|
|
||
|
tlabels = hcbar.TickLabels;
|
||
|
|
||
|
fsize = hcbar.FontSize;
|
||
|
|
||
|
switch hcbar.Location
|
||
|
|
||
|
case 'northoutside'
|
||
|
|
||
|
% make exta space a little more than the font size/height
|
||
|
ticklablespace_cm = 1.1 * (0.3528/10) * fsize;
|
||
|
|
||
|
ti(4) = ti(4) + ticklablespace_cm;
|
||
|
|
||
|
case 'eastoutside'
|
||
|
|
||
|
maxlabellen = max ( cellfun (@numel, tlabels, 'UniformOutput', true) );
|
||
|
|
||
|
% 0.62 factor is arbitrary and added because we don't
|
||
|
% know the width of every character in the label, the
|
||
|
% fsize refers to the height of the font
|
||
|
ticklablespace_cm = (0.3528/10) * fsize * maxlabellen * 0.62;
|
||
|
|
||
|
ti(3) = ti(3) + ticklablespace_cm;
|
||
|
|
||
|
case 'southoutside'
|
||
|
|
||
|
% make exta space a little more than the font size/height
|
||
|
ticklablespace_cm = 1.1 * (0.3528/10) * fsize;
|
||
|
|
||
|
ti(2) = ti(2) + ticklablespace_cm;
|
||
|
|
||
|
case 'westoutside'
|
||
|
|
||
|
maxlabellen = max ( cellfun (@numel, tlabels, 'UniformOutput', true) );
|
||
|
|
||
|
% 0.62 factor is arbitrary and added because we don't
|
||
|
% know the width of every character in the label, the
|
||
|
% fsize refers to the height of the font
|
||
|
ticklablespace_cm = (0.3528/10) * fsize * maxlabellen * 0.62;
|
||
|
|
||
|
ti(1) = ti(1) + ticklablespace_cm;
|
||
|
|
||
|
end
|
||
|
|
||
|
end
|
||
|
|
||
|
end
|
||
|
|
||
|
end
|