changelog shortlog tags changeset files revisions annotate raw

scripts/plot/subplot.m

changeset 10289: 4b124317dc38
parent:eb63fbe60fab
author: John W. Eaton <jwe@octave.org>
date: Tue Feb 09 20:58:55 2010 -0500 (54 minutes ago)
permissions: -rw-r--r--
description: base_properties::set_children: account for hidden children
1## Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2005,
2## 2006, 2007, 2008, 2009 John W. Eaton
3##
4## This file is part of Octave.
5##
6## Octave is free software; you can redistribute it and/or modify it
7## under the terms of the GNU General Public License as published by
8## the Free Software Foundation; either version 3 of the License, or (at
9## your option) any later version.
10##
11## Octave is distributed in the hope that it will be useful, but
12## WITHOUT ANY WARRANTY; without even the implied warranty of
13## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14## General Public License for more details.
15##
16## You should have received a copy of the GNU General Public License
17## along with Octave; see the file COPYING. If not, see
18## <http://www.gnu.org/licenses/>.
19
20## -*- texinfo -*-
21## @deftypefn {Function File} {} subplot (@var{rows}, @var{cols}, @var{index})
22## @deftypefnx {Function File} {} subplot (@var{rcn})
23## Set up a plot grid with @var{cols} by @var{rows} subwindows and plot
24## in location given by @var{index}.
25##
26## If only one argument is supplied, then it must be a three digit value
27## specifying the location in digits 1 (rows) and 2 (columns) and the plot
28## index in digit 3.
29##
30## The plot index runs row-wise. First all the columns in a row are filled
31## and then the next row is filled.
32##
33## For example, a plot with 2 by 3 grid will have plot indices running as
34## follows:
35## @tex
36## \vskip 10pt
37## \hfil\vbox{\offinterlineskip\hrule
38## \halign{\vrule#&&\qquad\hfil#\hfil\qquad\vrule\cr
39## height13pt&1&2&3\cr height12pt&&&\cr\noalign{\hrule}
40## height13pt&4&5&6\cr height12pt&&&\cr\noalign{\hrule}}}
41## \hfil
42## \vskip 10pt
43## @end tex
44## @ifnottex
45## @display
46## @example
47## @group
48##
49## +-----+-----+-----+
50## | 1 | 2 | 3 |
51## +-----+-----+-----+
52## | 4 | 5 | 6 |
53## +-----+-----+-----+
54## @end group
55## @end example
56## @end display
57## @end ifnottex
58## @seealso{plot}
59## @end deftypefn
60
61## Author: Vinayak Dutt <Dutt.Vinayak@mayo.EDU>
62## Adapted-By: jwe
63
64function h = subplot (rows, columns, index)
65
66 if (nargin != 3 && nargin != 1)
67 print_usage ();
68 endif
69
70 if (nargin == 1)
71
72 if (! (isscalar (rows) && rows >= 0))
73 error ("subplot: input rcn has to be a positive scalar");
74 endif
75
76 tmp = rows;
77 index = rem (tmp, 10);
78 tmp = (tmp - index) / 10;
79 columns = rem (tmp, 10);
80 tmp = (tmp - columns) / 10;
81 rows = rem (tmp, 10);
82
83 elseif (! (isscalar (columns) && isscalar (rows)))
84 error ("subplot: columns, and rows must be scalars");
85 elseif (any (index < 1) || any (index > rows*columns))
86 error ("subplot: index value must be greater than 1 and less than rows*columns")
87 endif
88
89 columns = round (columns);
90 rows = round (rows);
91 index = round (index);
92
93 if (index > columns*rows)
94 error ("subplot: index must be less than columns*rows");
95 endif
96
97 if (columns < 1 || rows < 1 || index < 1)
98 error ("subplot: columns,rows,index must be be positive");
99 endif
100
101 units = get (0, "defaultaxesunits");
102 unwind_protect
103 set (0, "defaultaxesunits", "normalized")
104 pos = subplot_position (rows, columns, index, "position", units);
105
106 cf = gcf ();
107
108 set (cf, "nextplot", "add");
109
110 found = false;
111 kids = get (cf, "children");
112 for child = reshape (kids, 1, numel (kids))
113 ## Check whether this child is still valid; this might not be the
114 ## case anymore due to the deletion of previous children (due to
115 ## "deletefcn" callback or for legends/colorbars that are deleted
116 ## with their corresponding axes).
117 if (! ishandle (child))
118 continue;
119 endif
120 if (strcmp (get (child, "type"), "axes"))
121 ## Skip legend and colorbar objects.
122 if (strcmp (get (child, "tag"), "legend") ||
123 strcmp (get (child, "tag"), "colorbar"))
124 continue;
125 endif
126 objpos = get (child, "position");
127 if (all (objpos == pos))
128 ## If the new axes are in exactly the same position as an
129 ## existing axes object, use the existing axes.
130 found = true;
131 tmp = child;
132 else
133 ## If the new axes overlap an old axes object, delete the old
134 ## axes.
135 x0 = pos(1);
136 x1 = x0 + pos(3);
137 y0 = pos(2);
138 y1 = y0 + pos(4);
139 objx0 = objpos(1);
140 objx1 = objx0 + objpos(3);
141 objy0 = objpos(2);
142 objy1 = objy0 + objpos(4);
143 if (! (x0 >= objx1 || x1 <= objx0 || y0 >= objy1 || y1 <= objy0))
144 delete (child);
145 endif
146 endif
147 endif
148 endfor
149
150 if (found)
151 set (cf, "currentaxes", tmp);
152 else
153 pos = subplot_position (rows, columns, index, "outerposition", units);
154 pos2 = subplot_position (rows, columns, index, "position", units);
155 tmp = axes ("outerposition", pos, "position", pos2);
156 endif
157
158 unwind_protect_cleanup
159 set (0, "defaultaxesunits", units);
160 end_unwind_protect
161
162 if (nargout > 0)
163 h = tmp;
164 endif
165
166endfunction
167
168function pos = subplot_position (rows, columns, index, position_property, units)
169
170 ## For 1 row and 1 column return the usual default.
171 if (rows == 1 && columns == 1)
172 if (strcmpi (position_property, "position"))
173 pos = get (0, "defaultaxesposition");
174 else
175 pos = get (0, "defaultaxesouterposition");
176 endif
177 return
178 endif
179
180 ## This produces compatible behavior for the "position" property.
181 margins.left = 0.130;
182 margins.right = 0.095;
183 margins.top = 0.075;
184 margins.bottom = 0.110;
185 pc = 1 ./ [0.1860, (margins.left + margins.right - 1)];
186 margins.column = 1 ./ polyval (pc , columns);
187 pr = 1 ./ [0.2282, (margins.top + margins.bottom - 1)];
188 margins.row = 1 ./ polyval (pr , rows);
189
190 ## Calculate the width/height of the subplot axes.
191 width = 1 - margins.left - margins.right - (columns-1)*margins.column;
192 width = width / columns;
193 height = 1 - margins.top - margins.bottom - (rows-1)*margins.row;
194 height = height / rows;
195
196 if (strcmp (position_property, "outerposition") )
197 ## Calculate the outerposition/position inset
198 if (rows > 1)
199 inset.top = 8/420;
200 inset.bottom = max (polyval ([0.1382,-0.0026], height), 16/420);
201 else
202 inset.bottom = margins.bottom;
203 inset.top = margins.top;
204 endif
205 if (columns > 1)
206 if (strcmpi (units, "normalized"))
207 inset.right = max (polyval ([0.1200,-0.0014], width), 5/560);
208 else
209 inset.right = max (polyval ([0.1252,-0.0023], width), 5/560);
210 endif
211 inset.left = 22/560;
212 else
213 inset.left = margins.left;
214 inset.right = margins.right;
215 endif
216 ## Apply the inset to the geometries for the "position" property.
217 margins.column = margins.column - inset.right - inset.left;
218 margins.row = margins.row - inset.top - inset.bottom;
219 width = width + inset.right + inset.left;
220 height = height + inset.top + inset.bottom;
221 endif
222
223 yp = fix ((index(:)-1)/columns);
224 xp = index(:) - yp*columns - 1;
225 yp = (rows - 1) - yp;
226
227 x0 = xp .* (width + margins.column) + margins.left;
228 y0 = yp .* (height + margins.row) + margins.bottom;
229
230 if (strcmp (position_property, "outerposition") )
231 x0 = x0 - inset.left;
232 y0 = y0 - inset.bottom;
233 endif
234
235 if (numel(x0) > 1)
236 x1 = max (x0) + width;
237 y1 = max (y0) + height;
238 x0 = min (x0);
239 y0 = min (y0);
240 pos = [x0, y0, x1-x0, y1-y0];
241 else
242 pos = [x0, y0, width, height];
243 endif
244
245endfunction
246
247%!demo
248%! clf
249%! r = 3;
250%! c = 3;
251%! fmt = {'horizontalalignment', 'center', 'verticalalignment', 'middle'};
252%! for n = 1:(r*c)
253%! subplot (r, c, n)
254%! xlabel (sprintf ("xlabel #%d", n))
255%! ylabel (sprintf ("ylabel #%d", n))
256%! title (sprintf ("title #%d", n))
257%! text (0.5, 0.5, sprintf('subplot(%d,%d,%d)', r, c, n), fmt{:})
258%! axis ([0 1 0 1])
259%! endfor
260%! subplot (r, c, 1:3)
261%! xlabel (sprintf ("xlabel #%d:%d", 1, 3))
262%! ylabel (sprintf ("ylabel #%d:%d", 1, 3))
263%! title (sprintf ("title #%d:%d", 1, 3))
264%! text (0.5, 0.5, sprintf('subplot(%d,%d,%d:%d)', r, c, 1, 3), fmt{:})
265%! axis ([0 1 0 1])
266