Mercurial > hg > octave-lyh
comparison scripts/plot/subplot.m @ 8744:4142982c66c6
subplot.m: Compatible placement of subplots.
author | Ben Abbott <bpabbott@mac.com> |
---|---|
date | Sun, 15 Feb 2009 19:07:05 -0500 |
parents | 81d6ab3ac93c |
children | 995f8b064b32 |
comparison
equal
deleted
inserted
replaced
8743:1bd918cfb6e2 | 8744:4142982c66c6 |
---|---|
80 tmp = (tmp - index) / 10; | 80 tmp = (tmp - index) / 10; |
81 columns = rem (tmp, 10); | 81 columns = rem (tmp, 10); |
82 tmp = (tmp - columns) / 10; | 82 tmp = (tmp - columns) / 10; |
83 rows = rem (tmp, 10); | 83 rows = rem (tmp, 10); |
84 | 84 |
85 elseif (! (isscalar (columns) && isscalar (rows) && isscalar (index))) | 85 elseif (! (isscalar (columns) && isscalar (rows))) |
86 error ("subplot: columns, rows, and index have to be scalars"); | 86 error ("subplot: columns, and rows must be scalars"); |
87 elseif (any (index < 1) || any (index > rows*columns)) | |
88 error ("subplot: index value must be greater than 1 and less than rows*columns") | |
87 endif | 89 endif |
88 | 90 |
89 columns = round (columns); | 91 columns = round (columns); |
90 rows = round (rows); | 92 rows = round (rows); |
91 index = round (index); | 93 index = round (index); |
96 | 98 |
97 if (columns < 1 || rows < 1 || index < 1) | 99 if (columns < 1 || rows < 1 || index < 1) |
98 error ("subplot: columns,rows,index must be be positive"); | 100 error ("subplot: columns,rows,index must be be positive"); |
99 endif | 101 endif |
100 | 102 |
101 xsize = 1 / columns; | 103 units = get (0, "defaultaxesunits"); |
102 ysize = 1 / rows; | 104 unwind_protect |
103 | 105 set (0, "defaultaxesunits", "normalized") |
104 yp = fix ((index-1)/columns); | 106 pos = subplot_position (rows, columns, index, "outerposition", units); |
105 xp = index - yp*columns - 1; | 107 |
106 | 108 cf = gcf (); |
107 x0 = xp * xsize; | 109 |
108 y0 = (rows - yp - 1) * ysize; | 110 set (cf, "nextplot", "add"); |
109 | 111 |
110 pos = [x0, y0, xsize, ysize]; | 112 found = false; |
111 | 113 kids = get (cf, "children"); |
112 x1 = x0 + xsize; | 114 for child = reshape (kids, 1, numel (kids)) |
113 y1 = y0 + ysize; | 115 ## Check whether this child is still valid; this might not be the |
114 | 116 ## case anymore due to the deletion of previous children (due to |
115 cf = gcf (); | 117 ## "deletefcn" callback or for legends/colorbars that are deleted |
116 | 118 ## with their corresponding axes). |
117 set (cf, "nextplot", "add"); | 119 if (! ishandle (child)) |
118 | |
119 found = false; | |
120 kids = get (cf, "children"); | |
121 for child = reshape (kids, 1, numel (kids)) | |
122 ## Check whether this child is still valid; this might not be the | |
123 ## case anymore due to the deletion of previous children (due to | |
124 ## "deletefcn" callback or for legends/colorbars that are deleted | |
125 ## with their corresponding axes). | |
126 if (! ishandle (child)) | |
127 continue; | |
128 endif | |
129 if (strcmp (get (child, "type"), "axes")) | |
130 ## Skip legend and colorbar objects. | |
131 if (strcmp (get (child, "tag"), "legend") || | |
132 strcmp (get (child, "tag"), "colorbar")) | |
133 continue; | 120 continue; |
134 endif | 121 endif |
135 objpos = get (child, "outerposition"); | 122 if (strcmp (get (child, "type"), "axes")) |
136 if (objpos == pos) | 123 ## Skip legend and colorbar objects. |
137 ## If the new axes are in exactly the same position as an | 124 if (strcmp (get (child, "tag"), "legend") || |
138 ## existing axes object, use the existing axes. | 125 strcmp (get (child, "tag"), "colorbar")) |
139 found = true; | 126 continue; |
140 tmp = child; | 127 endif |
141 else | 128 objpos = get (child, "outerposition"); |
142 ## If the new axes overlap an old axes object, delete the old | 129 if (all (objpos == pos)) |
143 ## axes. | 130 ## If the new axes are in exactly the same position as an |
144 objx0 = objpos(1); | 131 ## existing axes object, use the existing axes. |
145 objx1 = objx0 + objpos(3); | 132 found = true; |
146 objy0 = objpos(2); | 133 tmp = child; |
147 objy1 = objy0 + objpos(4); | 134 else |
148 if (! (x0 >= objx1 || x1 <= objx0 || y0 >= objy1 || y1 <= objy0)) | 135 ## If the new axes overlap an old axes object, delete the old |
149 delete (child); | 136 ## axes. |
150 endif | 137 x0 = pos(1); |
138 x1 = x0 + pos(3); | |
139 y0 = pos(2); | |
140 y1 = y0 + pos(4); | |
141 objx0 = objpos(1); | |
142 objx1 = objx0 + objpos(3); | |
143 objy0 = objpos(2); | |
144 objy1 = objy0 + objpos(4); | |
145 if (! (x0 >= objx1 || x1 <= objx0 || y0 >= objy1 || y1 <= objy0)) | |
146 delete (child); | |
147 endif | |
148 endif | |
151 endif | 149 endif |
152 endif | 150 endfor |
153 endfor | 151 |
154 | 152 if (found) |
155 if (found) | 153 set (cf, "currentaxes", tmp); |
156 set (cf, "currentaxes", tmp); | 154 else |
157 else | 155 pos2 = subplot_position (rows, columns, index, "position", units); |
158 border = [0.130, 0.110, 0.225, 0.185] .* [xsize, ysize, xsize, ysize]; | 156 tmp = axes ("outerposition", pos, "position", pos2); |
159 pos2 = [pos(1:2) + border(1:2), pos(3:4) - border(1:2) - border(3:4)]; | 157 endif |
160 tmp = axes ("outerposition", pos, "position", pos2); | 158 |
161 endif | 159 unwind_protect_cleanup |
160 set (0, "defaultaxesunits", units); | |
161 end_unwind_protect | |
162 | 162 |
163 if (nargout > 0) | 163 if (nargout > 0) |
164 h = tmp; | 164 h = tmp; |
165 endif | 165 endif |
166 | 166 |
167 endfunction | 167 endfunction |
168 | |
169 function pos = subplot_position (rows, columns, index, position_property, units) | |
170 | |
171 ## For 1 row and 1 column return the usual default. | |
172 if (rows == 1 && columns == 1) | |
173 if (strcmpi (position_property, "position")) | |
174 pos = get (0, "defaultaxesposition"); | |
175 else | |
176 pos = get (0, "defaultaxesouterposition"); | |
177 endif | |
178 return | |
179 endif | |
180 | |
181 ## This produces compatible behavior for the "position" property. | |
182 margins.left = 0.130; | |
183 margins.right = 0.095; | |
184 margins.top = 0.075; | |
185 margins.bottom = 0.110; | |
186 pc = 1 ./ [0.1860, (margins.left + margins.right - 1)]; | |
187 margins.column = 1 ./ polyval (pc , columns); | |
188 pr = 1 ./ [0.2282, (margins.top + margins.bottom - 1)]; | |
189 margins.row = 1 ./ polyval (pr , rows); | |
190 | |
191 ## Calculate the width/height of the subplot axes. | |
192 width = 1 - margins.left - margins.right - (columns-1)*margins.column; | |
193 width = width / columns; | |
194 height = 1 - margins.top - margins.bottom - (rows-1)*margins.row; | |
195 height = height / rows; | |
196 | |
197 if (strcmp (position_property, "outerposition") ) | |
198 ## Calculate the outerposition/position inset | |
199 if (rows > 1) | |
200 inset.top = 8/420; | |
201 inset.bottom = max (polyval ([0.1382,-0.0026], width), 16/420); | |
202 else | |
203 inset.bottom = margins.bottom; | |
204 inset.top = margins.top; | |
205 endif | |
206 if (columns > 1) | |
207 if (strcmpi (units, "normalized")) | |
208 inset.right = max (polyval ([0.1200,-0.0014], width), 5/560); | |
209 else | |
210 inset.right = max (polyval ([0.1252,-0.0023], width), 5/560); | |
211 endif | |
212 inset.left = 22/560; | |
213 else | |
214 inset.left = margins.left; | |
215 inset.right = margins.right; | |
216 endif | |
217 ## Apply the inset to the geometries for the "position" property. | |
218 margins.column = margins.column - inset.right - inset.left; | |
219 margins.row = margins.row - inset.top - inset.bottom; | |
220 width = width + inset.right + inset.left; | |
221 height = height + inset.top + inset.bottom; | |
222 endif | |
223 | |
224 yp = fix ((index(:)-1)/columns); | |
225 xp = index(:) - yp*columns - 1; | |
226 yp = (rows - 1) - yp; | |
227 | |
228 x0 = xp .* (width + margins.column) + margins.left; | |
229 y0 = yp .* (height + margins.row) + margins.bottom; | |
230 | |
231 if (numel(x0) > 1) | |
232 x1 = max (x0) + width; | |
233 y1 = max (y0) + height; | |
234 x0 = min (x0); | |
235 y0 = min (y0); | |
236 pos = [x0, y0, x1-x0, y1-y0]; | |
237 else | |
238 pos = [x0, y0, width, height]; | |
239 endif | |
240 | |
241 endfunction | |
242 | |
243 %!demo | |
244 %! clf | |
245 %! r = 3; | |
246 %! c = 3; | |
247 %! fmt = {'horizontalalignment', 'center', 'verticalalignment', 'middle'}; | |
248 %! for n = 1:(r*c) | |
249 %! subplot (r, c, n) | |
250 %! xlabel (sprintf ("xlabel #%d", n)) | |
251 %! ylabel (sprintf ("ylabel #%d", n)) | |
252 %! title (sprintf ("title #%d", n)) | |
253 %! text (0.5, 0.5, sprintf('subplot(%d,%d,%d)', r, c, n), fmt{:}) | |
254 %! axis ([0 1 0 1]) | |
255 %! endfor | |
256 %! subplot (r, c, 1:3) | |
257 %! xlabel (sprintf ("xlabel #%d:%d", 1, 3)) | |
258 %! ylabel (sprintf ("ylabel #%d:%d", 1, 3)) | |
259 %! title (sprintf ("title #%d:%d", 1, 3)) | |
260 %! text (0.5, 0.5, sprintf('subplot(%d,%d,%d:%d)', r, c, 1, 3), fmt{:}) | |
261 %! axis ([0 1 0 1]) | |
262 |