xticklabel_rotate.m
10.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
function hText = xticklabel_rotate(XTick,rot,varargin)
%hText = xticklabel_rotate(XTick,rot,XTickLabel,varargin) Rotate XTickLabel
%
% Syntax: xticklabel_rotate
%
% Input:
% {opt} XTick - vector array of XTick positions & values (numeric)
% uses current XTick values or XTickLabel cell array by
% default (if empty)
% {opt} rot - angle of rotation in degrees, 90° by default
% {opt} XTickLabel - cell array of label strings
% {opt} [var] - "Property-value" pairs passed to text generator
% ex: 'interpreter','none'
% 'Color','m','Fontweight','bold'
%
% Output: hText - handle vector to text labels
%
% Example 1: Rotate existing XTickLabels at their current position by 90°
% xticklabel_rotate
%
% Example 2: Rotate existing XTickLabels at their current position by 45° and change
% font size
% xticklabel_rotate([],45,[],'Fontsize',14)
%
% Example 3: Set the positions of the XTicks and rotate them 90°
% figure; plot([1960:2004],randn(45,1)); xlim([1960 2004]);
% xticklabel_rotate([1960:2:2004]);
%
% Example 4: Use text labels at XTick positions rotated 45° without tex interpreter
% xticklabel_rotate(XTick,45,NameFields,'interpreter','none');
%
% Example 5: Use text labels rotated 90° at current positions
% xticklabel_rotate([],90,NameFields);
%
% Example 6: Multiline labels
% figure;plot([1:4],[1:4])
% axis([0.5 4.5 1 4])
% xticklabel_rotate([1:4],45,{{'aaa' 'AA'};{'bbb' 'AA'};{'ccc' 'BB'};{'ddd' 'BB'}})
%
% Note : you can not RE-RUN xticklabel_rotate on the same graph.
%
% This is a modified version of xticklabel_rotate90 by Denis Gilbert
% Modifications include Text labels (in the form of cell array)
% Arbitrary angle rotation
% Output of text handles
% Resizing of axes and title/xlabel/ylabel positions to maintain same overall size
% and keep text on plot
% (handles small window resizing after, but not well due to proportional placement with
% fixed font size. To fix this would require a serious resize function)
% Uses current XTick by default
% Uses current XTickLabel is different from XTick values (meaning has been already defined)
% Brian FG Katz
% bfgkatz@hotmail.com
% 23-05-03
% Modified 03-11-06 after user comment
% Allow for exisiting XTickLabel cell array
% Modified 03-03-2006
% Allow for labels top located (after user comment)
% Allow case for single XTickLabelName (after user comment)
% Reduced the degree of resizing
% Modified 11-jun-2010
% Response to numerous suggestions on MatlabCentral to improve certain
% errors.
% Modified 23-sep-2014
% Allow for mutliline labels
% Other m-files required: cell2mat
% Subfunctions: none
% MAT-files required: none
%
% See also: xticklabel_rotate90, TEXT, SET
% Based on xticklabel_rotate90
% Author: Denis Gilbert, Ph.D., physical oceanography
% Maurice Lamontagne Institute, Dept. of Fisheries and Oceans Canada
% email: gilbertd@dfo-mpo.gc.ca Web: http://www.qc.dfo-mpo.gc.ca/iml/
% February 1998; Last revision: 24-Mar-2003
% check to see if xticklabel_rotate has already been here (no other reason for this to happen)
if isempty(get(gca,'XTickLabel')),
error('xticklabel_rotate : can not process, either xticklabel_rotate has already been run or XTickLabel field has been erased') ;
end
% if no XTickLabel AND no XTick are defined use the current XTickLabel
%if nargin < 3 & (~exist('XTick') | isempty(XTick)),
% Modified with forum comment by "Nathan Pust" allow the current text labels to be used and property value pairs to be changed for those labels
if (nargin < 3 || isempty(varargin{1})) & (~exist('XTick') | isempty(XTick)),
xTickLabels = get(gca,'XTickLabel') ; % use current XTickLabel
if ~iscell(xTickLabels)
% remove trailing spaces if exist (typical with auto generated XTickLabel)
temp1 = num2cell(xTickLabels,2) ;
for loop = 1:length(temp1),
temp1{loop} = deblank(temp1{loop}) ;
end
xTickLabels = temp1 ;
end
varargin = varargin(2:length(varargin));
end
% if no XTick is defined use the current XTick
if (~exist('XTick') | isempty(XTick)),
XTick = get(gca,'XTick') ; % use current XTick
end
%Make XTick a column vector
XTick = XTick(:);
if ~exist('xTickLabels'),
% Define the xtickLabels
% If XtickLabel is passed as a cell array then use the text
if (length(varargin)>0) & (iscell(varargin{1})),
xTickLabels = varargin{1};
varargin = varargin(2:length(varargin));
else
xTickLabels = num2str(XTick);
end
end
if length(XTick) ~= length(xTickLabels),
error('xticklabel_rotate : must have same number of elements in "XTick" and "XTickLabel"') ;
end
%Set the Xtick locations and set XTicklabel to an empty string
set(gca,'XTick',XTick,'XTickLabel','')
if nargin < 2,
rot = 90 ;
end
% Determine the location of the labels based on the position
% of the xlabel
hxLabel = get(gca,'XLabel'); % Handle to xlabel
xLabelString = get(hxLabel,'String');
% if ~isempty(xLabelString)
% warning('You may need to manually reset the XLABEL vertical position')
% end
set(hxLabel,'Units','data');
xLabelPosition = get(hxLabel,'Position');
y = xLabelPosition(2);
%CODE below was modified following suggestions from Urs Schwarz
y=repmat(y,size(XTick,1),1);
% retrieve current axis' fontsize
fs = get(gca,'fontsize');
if ~iscell(xTickLabels)
% Place the new xTickLabels by creating TEXT objects
hText = text(XTick, y, xTickLabels,'fontsize',fs);
else
% Place multi-line text approximately where tick labels belong
for cnt=1:length(XTick),
hText(cnt) = text(XTick(cnt),y(cnt),xTickLabels{cnt},...
'VerticalAlignment','top', 'UserData','xtick');
end
end
% Rotate the text objects by ROT degrees
%set(hText,'Rotation',rot,'HorizontalAlignment','right',varargin{:})
% Modified with modified forum comment by "Korey Y" to deal with labels at top
% Further edits added for axis position
xAxisLocation = get(gca, 'XAxisLocation');
if strcmp(xAxisLocation,'bottom')
set(hText,'Rotation',rot,'HorizontalAlignment','right',varargin{:})
else
set(hText,'Rotation',rot,'HorizontalAlignment','left',varargin{:})
end
% Adjust the size of the axis to accomodate for longest label (like if they are text ones)
% This approach keeps the top of the graph at the same place and tries to keep xlabel at the same place
% This approach keeps the right side of the graph at the same place
set(get(gca,'xlabel'),'units','data') ;
labxorigpos_data = get(get(gca,'xlabel'),'position') ;
set(get(gca,'ylabel'),'units','data') ;
labyorigpos_data = get(get(gca,'ylabel'),'position') ;
set(get(gca,'title'),'units','data') ;
labtorigpos_data = get(get(gca,'title'),'position') ;
set(gca,'units','pixel') ;
set(hText,'units','pixel') ;
set(get(gca,'xlabel'),'units','pixel') ;
set(get(gca,'ylabel'),'units','pixel') ;
% set(gca,'units','normalized') ;
% set(hText,'units','normalized') ;
% set(get(gca,'xlabel'),'units','normalized') ;
% set(get(gca,'ylabel'),'units','normalized') ;
origpos = get(gca,'position') ;
% textsizes = cell2mat(get(hText,'extent')) ;
% Modified with forum comment from "Peter Pan" to deal with case when only one XTickLabelName is given.
x = get( hText, 'extent' );
if iscell( x ) == true
textsizes = cell2mat( x ) ;
else
textsizes = x;
end
largest = max(textsizes(:,3)) ;
longest = max(textsizes(:,4)) ;
laborigext = get(get(gca,'xlabel'),'extent') ;
laborigpos = get(get(gca,'xlabel'),'position') ;
labyorigext = get(get(gca,'ylabel'),'extent') ;
labyorigpos = get(get(gca,'ylabel'),'position') ;
leftlabdist = labyorigpos(1) + labyorigext(1) ;
% assume first entry is the farthest left
leftpos = get(hText(1),'position') ;
leftext = get(hText(1),'extent') ;
leftdist = leftpos(1) + leftext(1) ;
if leftdist > 0, leftdist = 0 ; end % only correct for off screen problems
% botdist = origpos(2) + laborigpos(2) ;
% newpos = [origpos(1)-leftdist longest+botdist origpos(3)+leftdist origpos(4)-longest+origpos(2)-botdist]
%
% Modified to allow for top axis labels and to minimize axis resizing
if strcmp(xAxisLocation,'bottom')
newpos = [origpos(1)-(min(leftdist,labyorigpos(1)))+labyorigpos(1) ...
origpos(2)+((longest+laborigpos(2))-get(gca,'FontSize')) ...
origpos(3)-(min(leftdist,labyorigpos(1)))+labyorigpos(1)-largest ...
origpos(4)-((longest+laborigpos(2))-get(gca,'FontSize'))] ;
else
newpos = [origpos(1)-(min(leftdist,labyorigpos(1)))+labyorigpos(1) ...
origpos(2) ...
origpos(3)-(min(leftdist,labyorigpos(1)))+labyorigpos(1)-largest ...
origpos(4)-(longest)+get(gca,'FontSize')] ;
end
set(gca,'position',newpos) ;
% readjust position of text labels after resize of plot
set(hText,'units','data') ;
for loop= 1:length(hText),
set(hText(loop),'position',[XTick(loop), y(loop)]) ;
end
% adjust position of xlabel and ylabel
laborigpos = get(get(gca,'xlabel'),'position') ;
set(get(gca,'xlabel'),'position',[laborigpos(1) laborigpos(2)-longest 0]) ;
% switch to data coord and fix it all
set(get(gca,'ylabel'),'units','data') ;
set(get(gca,'ylabel'),'position',labyorigpos_data) ;
set(get(gca,'title'),'position',labtorigpos_data) ;
set(get(gca,'xlabel'),'units','data') ;
labxorigpos_data_new = get(get(gca,'xlabel'),'position') ;
set(get(gca,'xlabel'),'position',[labxorigpos_data(1) labxorigpos_data_new(2)]) ;
% Reset all units to normalized to allow future resizing
set(get(gca,'xlabel'),'units','normalized') ;
set(get(gca,'ylabel'),'units','normalized') ;
set(get(gca,'title'),'units','normalized') ;
set(hText,'units','normalized') ;
set(gca,'units','normalized') ;
if nargout < 1,
clear hText
end