]> Creatis software - CreaPhase.git/blob - octave_packages/m/plot/private/__bar__.m
update packages
[CreaPhase.git] / octave_packages / m / plot / private / __bar__.m
1 ## Copyright (C) 1996-2012 John W. Eaton
2 ##
3 ## This file is part of Octave.
4 ##
5 ## Octave is free software; you can redistribute it and/or modify it
6 ## under the terms of the GNU General Public License as published by
7 ## the Free Software Foundation; either version 3 of the License, or (at
8 ## your option) any later version.
9 ##
10 ## Octave is distributed in the hope that it will be useful, but
11 ## WITHOUT ANY WARRANTY; without even the implied warranty of
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 ## General Public License for more details.
14 ##
15 ## You should have received a copy of the GNU General Public License
16 ## along with Octave; see the file COPYING.  If not, see
17 ## <http://www.gnu.org/licenses/>.
18
19 ## -*- texinfo -*-
20 ## @deftypefn {Function File} {} __bar__ (@var{vertical}, @var{func}, @dots{})
21 ## Undocumented internal function.
22 ## @end deftypefn
23
24 ## Author: jwe
25
26 function varargout = __bar__ (vertical, func, varargin)
27
28   [h, varargin] = __plt_get_axis_arg__ ((nargout > 1), func, varargin{:});
29
30   ## Slightly smaller than 0.8 to avoid clipping issue in gnuplot 4.0
31   width = 0.8 - 10 * eps;
32   group = true;
33   bv = 0;
34
35   if (nargin < 3)
36     print_usage ();
37   endif
38
39   if (nargin > 3 && isnumeric (varargin{2}))
40     x = varargin{1};
41     if (isvector (x))
42       x = x(:);
43     endif
44     y = varargin{2};
45     if (isvector (y))
46       y = y(:);
47     endif
48     if (size (x, 1) != size (y, 1))
49       y = varargin{1};
50       if (isvector (y))
51         y = y(:);
52       endif
53       x = [1:size(y,1)]';
54       idx = 2;
55     else
56       if (! isvector (x))
57         error ("%s: x must be a vector", func);
58       endif
59       idx = 3;
60     endif
61   else
62     y = varargin{1};
63     if (isvector (y))
64       y = y(:);
65     endif
66     x = [1:size(y,1)]';
67     idx = 2;
68   endif
69
70   newargs = {};
71   have_line_spec = false;
72   while (idx <= nargin - 2)
73     if (ischar (varargin{idx}) && strcmpi (varargin{idx}, "grouped"))
74       group = true;
75       idx++;
76     elseif (ischar (varargin{idx}) && strcmpi (varargin{idx}, "stacked"))
77       group = false;
78       idx++;
79     else
80       if ((ischar (varargin{idx}) || iscell (varargin{idx}))
81           && ! have_line_spec)
82         [linespec, valid] = __pltopt__ (func, varargin{idx}, false);
83         if (valid)
84           have_line_spec = true;
85           newargs = [{"facecolor", linespec.color}, newargs]
86           idx++;
87           continue;
88         endif
89       endif
90       if (isscalar(varargin{idx}))
91         width = varargin{idx++};
92       elseif (idx == nargin - 2)
93         newargs = [newargs,varargin(idx++)];
94       elseif (ischar (varargin{idx})
95               && strcmpi (varargin{idx}, "basevalue")
96               && isscalar (varargin{idx+1}))
97         bv = varargin{idx+1};
98         idx += 2;
99       else
100         newargs = [newargs,varargin(idx:idx+1)];
101         idx += 2;
102       endif
103     endif
104   endwhile
105
106   xlen = size (x, 1);
107   ylen = size (y, 1);
108
109   if (xlen != ylen)
110     error ("%s: length of x and y must be equal", func);
111   endif
112   if (any (x(2:end) < x(1:end-1)))
113     error ("%s: x vector values must be in ascending order", func);
114   endif
115
116   ycols = size (y, 2);
117   if (numel (x) > 1)
118     cutoff = min (diff (double(x))) / 2;
119   else
120     cutoff = 1;
121   endif
122   if (group)
123     delta_p = delta_m = repmat (cutoff * width / ycols, size (x));
124   else
125     delta_p = delta_m = repmat (cutoff * width, size (x));
126   endif
127   x1 = (x - delta_m)(:)';
128   x2 = (x + delta_p)(:)';
129   xb = repmat ([x1; x1; x2; x2](:), 1, ycols);
130
131   if (group)
132     offset = ((delta_p + delta_m) * [-(ycols - 1) / 2 : (ycols - 1) / 2]);
133     xb(1:4:4*ylen,:) += offset;
134     xb(2:4:4*ylen,:) += offset;
135     xb(3:4:4*ylen,:) += offset;
136     xb(4:4:4*ylen,:) += offset;
137     y0 = zeros (size (y)) + bv;
138     y1 = y;
139   else
140     y1 = cumsum(y,2);
141     y0 = [zeros(ylen,1)+bv, y1(:,1:end-1)];
142   endif
143
144   yb = zeros (4*ylen, ycols);
145   yb(1:4:4*ylen,:) = y0;
146   yb(2:4:4*ylen,:) = y1;
147   yb(3:4:4*ylen,:) = y1;
148   yb(4:4:4*ylen,:) = y0;
149
150   xb = reshape (xb, [4, numel(xb) / 4 / ycols, ycols]);
151   yb = reshape (yb, [4, numel(yb) / 4 / ycols, ycols]);
152
153   if (nargout < 2)
154     oldh = gca ();
155     unwind_protect
156       axes (h);
157       newplot ();
158
159       tmp = bars (h, vertical, x, y, xb, yb, width, group,
160                   have_line_spec, bv, newargs{:});
161       if (nargout == 1)
162         varargout{1} = tmp;
163       endif
164     unwind_protect_cleanup
165       axes (oldh);
166     end_unwind_protect
167   else
168     if (vertical)
169       varargout{1} = xb;
170       varargout{2} = yb;
171     else
172       varargout{1} = yb;
173       varargout{2} = xb;
174     endif
175   endif
176
177 endfunction
178
179 function tmp = bars (ax, vertical, x, y, xb, yb, width, group, have_color_spec, base_value, varargin)
180
181   ycols = columns (y);
182   clim = get (ax, "clim");
183   tmp = [];
184
185   for i = 1:ycols
186     hg = hggroup ();
187     tmp = [tmp; hg];
188     args = __add_datasource__ ("bar", hg, {"x", "y"}, varargin{:});
189
190     if (vertical)
191       if (! have_color_spec)
192         if (ycols == 1)
193           lev = clim(1);
194         else
195           lev = (i - 1) * (clim(2) - clim(1)) / (ycols - 1) - clim(1);
196         endif
197         h = patch(xb(:,:,i), yb(:,:,i), "FaceColor", "flat",
198                   "cdata", lev, "parent", hg);
199       else
200         h = patch(xb(:,:,i), yb(:,:,i), "parent", hg);
201       endif
202     else
203       if (! have_color_spec)
204         if (ycols == 1)
205           lev = clim(1);
206         else
207           lev = (i - 1) * (clim(2) - clim(1)) / (ycols - 1) - clim(1);
208         endif
209         h = patch(yb(:,:,i), xb(:,:,i), "FaceColor", "flat",
210                   "cdata", lev, "parent", hg);
211       else
212         h = patch(yb(:,:,i), xb(:,:,i), "parent", hg);
213       endif
214     endif
215
216     if (i == 1)
217       x_axis_range = get (ax, "xlim");
218       h_baseline = line (x_axis_range, [0, 0], "color", [0, 0, 0]);
219       set (h_baseline, "handlevisibility", "off");
220       set (h_baseline, "xliminclude", "off");
221       addlistener (ax, "xlim", @update_xlim);
222       addlistener (h_baseline, "ydata", @update_baseline);
223       addlistener (h_baseline, "visible", @update_baseline);
224     endif
225
226     ## Setup the hggroup and listeners
227     addproperty ("showbaseline", hg, "radio", "{on}|off");
228     addproperty ("basevalue", hg, "data", base_value);
229     addproperty ("baseline", hg, "data", h_baseline);
230
231     addlistener (hg, "showbaseline", @show_baseline);
232     addlistener (hg, "basevalue", @move_baseline);
233
234     addproperty ("barwidth", hg, "data", width);
235     if (group)
236       addproperty ("barlayout", hg, "radio", "stacked|{grouped}", "grouped");
237     else
238       addproperty ("barlayout", hg, "radio", "{stacked}|grouped", "stacked");
239     endif
240     if (vertical)
241       addproperty ("horizontal", hg, "radio", "on|{off}", "off");
242     else
243       addproperty ("horizontal", hg, "radio", "{on}|off", "on");
244     endif
245
246     addlistener (hg, "barwidth", @update_group);
247     addlistener (hg, "barlayout", @update_group);
248     addlistener (hg, "horizontal", @update_group);
249
250     addproperty ("edgecolor", hg, "patchedgecolor", get (h, "edgecolor"));
251     addproperty ("linewidth", hg, "patchlinewidth", get (h, "linewidth"));
252     addproperty ("linestyle", hg, "patchlinestyle", get (h, "linestyle"));
253     addproperty ("facecolor", hg, "patchfacecolor", get (h, "facecolor"));
254
255     addlistener (hg, "edgecolor", @update_props);
256     addlistener (hg, "linewidth", @update_props);
257     addlistener (hg, "linestyle", @update_props);
258     addlistener (hg, "facecolor", @update_props);
259
260     if (isvector (x))
261       addproperty ("xdata", hg, "data", x);
262     else
263       addproperty ("xdata", hg, "data", x(:, i));
264     endif
265     addproperty ("ydata", hg, "data", y(:, i));
266
267     addlistener (hg, "xdata", @update_data);
268     addlistener (hg, "ydata", @update_data);
269
270     addproperty ("bargroup", hg, "data");
271     set (tmp, "bargroup", tmp);
272     if (! isempty (args))
273       set (hg, args{:});
274     endif
275     if (i == 1)
276       set (h_baseline, "parent", get (hg, "parent"));
277     endif
278   endfor
279
280   update_xlim (ax, []);
281 endfunction
282
283 function update_xlim (h, d)
284   kids = get (h, "children");
285   xlim = get (h, "xlim");
286
287   for i = 1 : length (kids)
288     obj = get (kids (i));
289     if (strcmp (obj.type, "hggroup") && isfield (obj, "baseline"))
290       if (any (get (obj.baseline, "xdata") != xlim))
291         set (obj.baseline, "xdata", xlim);
292       endif
293     endif
294   endfor
295 endfunction
296
297 function update_baseline (h, d)
298   visible = get (h, "visible");
299   ydata = get (h, "ydata")(1);
300
301   kids = get (get (h, "parent"), "children");
302   for i = 1 : length (kids)
303     obj = get (kids (i));
304     if (strcmp (obj.type, "hggroup") && isfield (obj, "baseline")
305         && obj.baseline == h)
306       ## Only alter if changed to avoid recursion of the listener functions
307       if (! strcmpi (get (kids(i), "showbaseline"), visible))
308         set (kids (i), "showbaseline", visible);
309       endif
310       if (! strcmpi (get (kids(i), "basevalue"), visible))
311         set (kids (i), "basevalue", ydata);
312       endif
313     endif
314   endfor
315 endfunction
316
317 function show_baseline (h, d)
318   persistent recursion = false;
319
320   ## Don't allow recursion
321   if (! recursion)
322     unwind_protect
323       recursion = true;
324       hlist = get (h, "bargroup");
325       showbaseline = get (h, "showbaseline");
326       for hh = hlist(:)'
327         if (hh != h)
328           set (hh, "showbaseline", showbaseline);
329         endif
330       endfor
331       set (get (h, "baseline"), "visible", showbaseline);
332     unwind_protect_cleanup
333       recursion = false;
334     end_unwind_protect
335   endif
336 endfunction
337
338 function move_baseline (h, d)
339   b0 = get (h, "basevalue");
340   bl = get (h, "baseline");
341
342   if (get (bl, "ydata") != [b0, b0])
343     set (bl, "ydata", [b0, b0]);
344   endif
345
346   if (strcmpi (get (h, "barlayout"), "grouped"))
347     update_data (h, d);
348   endif
349 endfunction
350
351 function update_props (h, d)
352   kids = get (h, "children");
353   set (kids, "edgecolor", get (h, "edgecolor"),
354        "linewidth", get (h, "linewidth"),
355        "linestyle", get (h, "linestyle"),
356        "facecolor", get (h, "facecolor"));
357 endfunction
358
359 function update_data (h, d)
360   persistent recursion = false;
361
362   ## Don't allow recursion
363   if (! recursion)
364     unwind_protect
365       recursion = true;
366       hlist = get (h, "bargroup");
367       x = get (h, "xdata");
368       if (!isvector (x))
369         x = x(:);
370       endif
371       y = [];
372       for hh = hlist(:)'
373         ytmp = get (hh, "ydata");
374         y = [y ytmp(:)];
375       endfor
376
377       [xb, yb] = bar (x, y, get (h, "barwidth"), get (h, "barlayout"),
378                       "basevalue", get (h, "basevalue"));
379       ny = columns (y);
380       vert = strcmpi (get (h, "horizontal"), "off");
381
382       for i = 1:ny
383         hp = get (hlist(i), "children");
384         if (vert)
385           set (hp, "xdata", xb(:,:,i), "ydata", yb(:,:,i));
386         else
387           set (hp, "xdata", yb(:,:,i), "ydata", xb(:,:,i));
388         endif
389       endfor
390     unwind_protect_cleanup
391       recursion = false;
392     end_unwind_protect
393   endif
394 endfunction
395
396 function update_group (h, d)
397   persistent recursion = false;
398
399   ## Don't allow recursion
400   if (! recursion)
401     unwind_protect
402       recursion = true;
403       hlist = get (h, "bargroup");
404       barwidth = get(h, "barwidth");
405       barlayout = get (h, "barlayout");
406       horizontal = get (h, "horizontal");
407
408       ## To prevent recursion, only change if modified
409       for hh = hlist(:)'
410         if (hh != h)
411           if (get (hh, "barwidth") != barwidth)
412             set (hh, "barwidth", barwidth);
413           endif
414           if (! strcmpi (get (hh, "barlayout"), barlayout))
415             set (hh, "barlayout", barlayout);
416           endif
417           if (! strcmpi (get (hh, "horizontal"), horizontal))
418             set (hh, "horizontal", horizontal);
419           endif
420         endif
421       endfor
422       update_data (h, d);
423     unwind_protect_cleanup
424       recursion = false;
425     end_unwind_protect
426   endif
427 endfunction