Mercurial > hg > octave-lojdl
changeset 8101:86955a1559c5
improve speed of cell2mat
* * *
trivial fix for previous cell2mat change
author | David Bateman <dbateman@free.fr> |
---|---|
date | Thu, 11 Sep 2008 16:57:12 -0400 |
parents | da2fbd22d672 |
children | c066714ee5d5 |
files | scripts/ChangeLog scripts/general/cell2mat.m scripts/image/__img__.m scripts/plot/__go_draw_axes__.m scripts/plot/__go_draw_figure__.m scripts/plot/colorbar.m scripts/plot/legend.m scripts/plot/newplot.m scripts/plot/pareto.m scripts/plot/plotyy.m scripts/plot/subplot.m src/ChangeLog src/graphics.cc src/graphics.h.in |
diffstat | 14 files changed, 567 insertions(+), 232 deletions(-) [+] |
line wrap: on
line diff
--- a/scripts/ChangeLog +++ b/scripts/ChangeLog @@ -1,3 +1,29 @@ +2008-09-11 David Bateman <dbateman@free.fr> + + * image/__img__.m: Manually set the limits of th eimage + * plot/__go_draw_axes__.m: Base window position in the axis + position property and not the outerposition property. Remove + colorbar code based on the gnuplot colorbox. Allow images to be a + vector to support image based colorbars. Also check labelmode for + manual tics. + * plot/__go_draw_figure__.m: Remove gnuplot colorbox based + colorbar code. + * plot/colorbar.m: Rewrite to use an image and callbacks to link + it to the principal axis. + * plot/legend.m: Support an axis handle as the first + argument. Support hggroups. + * plot/pareto.m: Don't support an axis handle as the first + argument as the plotyy command in fact needs two axis handles. + * plot/plotyy.m: Rewrite to use listeners and callbacks to + synchronize the two axes. + * plot/subplot.m: Also skip axes that are tagged as being a + colorbar. Don't break in search of overlapping axes to delete. Set + both the position and the outerposition. + +2008-09-09 David Bateman <dbateman@free.fr> + + * general/cell2mat.m: Improve the speed.. + 2008-09-09 John W. Eaton <jwe@octave.org> * time/datestr.m: Convert format and use strftime to do most of
--- a/scripts/general/cell2mat.m +++ b/scripts/general/cell2mat.m @@ -48,20 +48,46 @@ else error ("cell2mat: all elements of cell array must be numeric, logical or char"); endif + elseif (ndims (c) == 2) + nr = rows (c); + c1 = cell (nr, 1); + for i = 1 : nr + c1{i} = [c{i : nr : end}]; + endfor + ## This is faster than "c = cat(1, c{:})" + m = [cellfun(@(x) x.', c1, "UniformOutput", false){:}].'; else - ## n dimensions case - for k = ndims (c):-1:2, + nd = ndims (c); + for k = nd : -1 : 2 sz = size (c); + if (k > ndims (c) || sz(end) == 1) + continue; + endif sz(end) = 1; c1 = cell (sz); - for i = 1:(prod (sz)) - c1{i} = cat (k, c{i:(prod (sz)):end}); - endfor + sz = prod (sz); + if (k == 2) + for i = 1 : sz + c1{i} = [c{i : sz : end}]; + endfor + else + ## This is faster than + ## for i = 1:sz, c1{i} = cat (k, c{i:(prod (sz)):end}); endfor + idx = [1, k, (3 : (k - 1)), 2, ((k + 1): nd)]; + c = cellfun(@(x) permute (x, idx), c, "UniformOutput", false); + for i = 1: sz + c1{i} = ipermute ([c{i : sz : end}], idx); + endfor + endif c = c1; endfor - m = cat (1, c1{:}); + if (numel (c) > 1) + idx = [2, 1, 3 : nd]; + m = ipermute([cellfun(@(x) permute (x, idx), c, "UniformOutput", false){:}], idx); + else + m = c{1}; + endif endif - endfunction ## Tests
--- a/scripts/image/__img__.m +++ b/scripts/image/__img__.m @@ -65,7 +65,8 @@ endif endif - set (ca, "view", [0, 90]); + set (ca, "view", [0, 90], "xlimmode", "manual", "ylimmode", "manual", + "xlim", xlim, "ylim", ylim); if (strcmp (get (ca, "nextplot"), "replace")) set (ca, "ydir", "reverse");
--- a/scripts/plot/__go_draw_axes__.m +++ b/scripts/plot/__go_draw_axes__.m @@ -31,27 +31,17 @@ persistent have_newer_gnuplot ... = compare_versions (__gnuplot_version__ (), "4.0", ">"); - ## Set axis properties here? - pos = [0, 0, 1, 1]; - if (strcmpi (axis_obj.activepositionproperty, "outerposition")) - ymirror = true; - if (! isempty (axis_obj.outerposition)) - pos = axis_obj.outerposition; - endif - else + pos = axis_obj.position; + fprintf (plot_stream, "set tmargin 0;\n"); + fprintf (plot_stream, "set bmargin 0;\n"); + fprintf (plot_stream, "set lmargin 0;\n"); + fprintf (plot_stream, "set rmargin 0;\n"); + + ## Set to false for plotyy axes. + if (strcmp (axis_obj.tag, "plotyy")) ymirror = false; - if (! isempty (axis_obj.position)) - pos = axis_obj.position; - fprintf (plot_stream, "set tmargin 0;\n"); - fprintf (plot_stream, "set bmargin 0;\n"); - fprintf (plot_stream, "set lmargin 0;\n"); - fprintf (plot_stream, "set rmargin 0;\n"); - endif - endif - - if (! strcmpi (get (h, "__colorbar__"), "none")) - [pos, cbox_orient, cbox_size, cbox_origin, cbox_mirror] = ... - gnuplot_position_colorbox (pos, get (h, "__colorbar__"), axis_obj); + else + ymirror = true; endif fprintf (plot_stream, "set origin %.15g, %.15g;\n", pos(1), pos(2)); @@ -358,12 +348,16 @@ if (x_dim > 1) dx = abs (img_xdata(2)-img_xdata(1))/(x_dim-1); else - dx = 1; + x_dim = 2; + img_data = [img_data, img_data]; + dx = abs (img_xdata(2)-img_xdata(1)); endif if (y_dim > 1) dy = abs (img_ydata(2)-img_ydata(1))/(y_dim-1); else - dy = 1; + y_dim = 2; + img_data = [img_data; img_data]; + dy = abs (img_ydata(2)-img_ydata(1)); endif x_origin = min (img_xdata); y_origin = min (img_ydata); @@ -1027,6 +1021,8 @@ have_data = (! (isempty (data) || all (cellfun (@isempty, data)))); + ## Note we don't use the [xy]2range of gnuplot as we don't use the + ## dual axis plotting features of gnuplot if (isempty (xlim)) return; endif @@ -1035,8 +1031,7 @@ else xdir = "noreverse"; endif - fprintf (plot_stream, "set %srange [%.15e:%.15e] %s;\n", - xaxisloc, xlim, xdir); + fprintf (plot_stream, "set xrange [%.15e:%.15e] %s;\n", xlim, xdir); if (isempty (ylim)) return; @@ -1046,8 +1041,7 @@ else ydir = "noreverse"; endif - fprintf (plot_stream, "set %srange [%.15e:%.15e] %s;\n", - yaxisloc, ylim, ydir); + fprintf (plot_stream, "set yrange [%.15e:%.15e] %s;\n", ylim, ydir); if (nd == 3) if (isempty (zlim)) @@ -1209,16 +1203,8 @@ fputs (plot_stream, ");\n"); endif endif - - if (strcmpi (get (h, "__colorbar__"), "none")) - fputs (plot_stream, "unset colorbox;\n"); - else - ## FIXME If cbox_mirror is true we want to invert the tic labels - ## but gnuplot doesn't allow that - fputs (plot_stream, - sprintf ("set colorbox %s user origin %f,%f size %f,%f;\n", - cbox_orient, cbox_origin, cbox_size)); - endif + + fputs (plot_stream, "unset colorbox;\n"); if (have_data) if (nd == 2) @@ -1549,7 +1535,7 @@ function do_tics_1 (ticmode, tics, labelmode, labels, color, ax, plot_stream, mirror, mono, axispos, tickdir) colorspec = get_text_colorspec (color, mono); - if (strcmpi (ticmode, "manual")) + if (strcmpi (ticmode, "manual") || strcmpi (labelmode, "manual")) if (isempty (tics)) fprintf (plot_stream, "unset %stics;\n", ax); elseif (strcmpi (labelmode, "manual") && ! isempty (labels)) @@ -1562,7 +1548,8 @@ nlabels = numel (labels); fprintf (plot_stream, "set format %s \"%%s\";\n", ax); if (mirror) - fprintf (plot_stream, "set %stics %s %s (", ax, tickdir, axispos); + fprintf (plot_stream, "set %stics %s %s mirror (", ax, + tickdir, axispos); else fprintf (plot_stream, "set %stics %s %s nomirror (", ax, tickdir, axispos); @@ -1584,7 +1571,8 @@ else fprintf (plot_stream, "set format %s \"%%g\";\n", ax); if (mirror) - fprintf (plot_stream, "set %stics %s %s (", ax, tickdir, axispos ); + fprintf (plot_stream, "set %stics %s %s mirror (", ax, + tickdir, axispos ); else fprintf (plot_stream, "set %stics %s %s nomirror (", ax, tickdir, axispos); @@ -1595,8 +1583,8 @@ else fprintf (plot_stream, "set format %s \"%%g\";\n", ax); if (mirror) - fprintf (plot_stream, "set %stics %s %s %s;\n", ax, axispos, tickdir, - colorspec); + fprintf (plot_stream, "set %stics %s %s mirror %s;\n", ax, + axispos, tickdir, colorspec); else fprintf (plot_stream, "set %stics %s %s nomirror %s;\n", ax, tickdir, axispos, colorspec); @@ -1987,105 +1975,6 @@ sym.int = '{/Symbol \362}'; endfunction -function [pos, orient, sz, origin, mirr] = gnuplot_position_colorbox (pos, cbox, obj) - ## This is an emprically derived function that attempts to find a good - ## size for the colorbox even for subplots and strange aspect ratios. - - if (strncmp (cbox, "north", 5) || strncmp (cbox, "south", 5)) - scl = pos([2,4]); - else - scl = pos([1,3]); - endif - - if (length(cbox) > 7 && strncmp (cbox(end-6:end), "outside", 7)) - scl(2) -= 0.2 * scl(2); - if (strncmp (cbox, "west", 4) || strncmp (cbox, "south", 5)) - scl(1) += 0.2 * scl(2); - endif - endif - - if (strcmpi (obj.dataaspectratiomode, "manual")) - sz = min(pos(3:4))([1,1]); - r = obj.dataaspectratio; - if (pos(3) > pos(4)) - switch (cbox) - case {"north", "northoutside"} - off = 4 / 3 * [(pos(3) - pos(4)) ./ (r(2)/r(1)), pos(4) / pos(3) / 2]; - sz = 2 * sz / 3; - case {"south", "southoutside"} - off = 4 / 3 * [(pos(3) - pos(4)) ./ (r(2)/r(1)), 0]; - sz = 2 * sz / 3; - otherwise - off = [(pos(3) - pos(4)) ./ (r(2)/r(1)), 0]; - endswitch - else - switch (cbox) - case {"north", "northoutside"} - off = 1.5 * [0, (pos(4) - pos(3)) ./ (r(1) / r(2))]; - case {"south", "southoutside"} - off = 0.5 * [0, (pos(4) - pos(3)) ./ (r(1) / r(2))]; - otherwise - off = [0, (pos(4) - pos(3)) ./ (r(1) / r(2))]; - endswitch - endif - off = off / 2; - else - sz = pos(3:4); - off = 0; - endif - switch (cbox) - case "northoutside" - sz = sz - 0.08; - origin = [0.05, 0.06] + [0.00, 0.88] .* sz + pos(1:2) + off; - mirr = true; - orient = "horizontal"; - case "north" - sz = sz - 0.16; - origin = [0.09, 0.09] + [0.00, 0.94] .* sz + pos(1:2) + off; - mirr = false; - orient = "horizontal"; - case "southoutside" - sz = sz - 0.08; - origin = [0.05, 0.06] + [0.00, 0.00] .* sz + pos(1:2) + off; - mirr = false; - orient = "horizontal"; - case "south" - sz = sz - 0.16; - origin = [0.08, 0.09] + [0.03, 0.05] .* sz + pos(1:2) + off; - mirr = true; - orient = "horizontal"; - case "eastoutside" - sz = sz - 0.08; - origin = [0.00, 0.06] + [0.94, 0.00] .* sz + pos(1:2) + off; - mirr = false; - orient = "vertical"; - case "east" - sz = sz - 0.16; - origin = [0.09, 0.10] + [0.91, 0.01] .* sz + pos(1:2) + off; - mirr = true; - orient = "vertical"; - case "westoutside" - sz = sz - 0.08; - origin = [0.00, 0.06] + [0.06, 0.00] .* sz + pos(1:2) + off; - mirr = true; - orient = "vertical"; - case "west" - sz = sz - 0.16; - origin = [0.06, 0.09] + [0.04, 0.03] .* sz + pos(1:2) + off; - mirr = false; - orient = "vertical"; - endswitch - - if (strncmp (cbox, "north", 5) || strncmp (cbox, "south", 5)) - sz = sz .* [1, 0.07]; - pos([2,4]) = scl; - else - sz = sz .* [0.07, 1]; - pos([1,3]) = scl; - endif - -endfunction - function retval = __do_enhanced_option__ (enhanced, obj) retval = ""; if (enhanced)
--- a/scripts/plot/__go_draw_figure__.m +++ b/scripts/plot/__go_draw_figure__.m @@ -37,10 +37,6 @@ switch (obj.type) case "axes" axes_count++; - ## Force multiplot with a colorbar to ensure colorbar on the page - if (!strcmp (obj.__colorbar__, "none")) - axes_count++; - endif endswitch endfor
--- a/scripts/plot/colorbar.m +++ b/scripts/plot/colorbar.m @@ -1,4 +1,4 @@ -## Copyright (C) 2007 David Bateman +## Copyright (C) 2008 David Bateman ## ## This file is part of Octave. ## @@ -47,51 +47,304 @@ ## @end deftypefn -## PKG_ADD: mark_as_command colorbar +function h = colorbar (varargin) + ax = []; + loc = "eastoutside"; + args = {}; + deleting = false; + + i = 1; + while (i <= nargin) + arg = varargin {i++}; -function colorbar (varargin) - - if (nargin > 0 && strcmpi(varargin{1}, "peer")) - if (nargin > 1) - ax = varargin{2}; - if (!isscalar (ax) || ! ishandle (ax) - || strcmp (get (ax, "type"), "axes")) - error ("colorbar: expecting an axes handle following 'peer'"); + if (ischar(arg)) + if (strcmpi (arg, "peer")) + if (i > nargin) + error ("colorbar: missing axes handle after 'peer'"); + else + ax = vargin{i++} + if (!isscalar (ax) || ! ishandle (ax) + || strcmp (get (ax, "type"), "axes")) + error ("colorbar: expecting an axes handle following 'peer'"); + endif + endif + elseif (strcmpi (arg, "north") || strcmpi (arg, "south") + || strcmpi (arg, "east") || strcmpi (arg, "west") + || strcmpi (arg, "northoutside") || strcmpi (arg, "southoutside") + || strcmpi (arg, "eastoutside") || strcmpi (arg, "westoutside")) + loc = arg; + elseif (strcmpi (arg, "off") || strcmpi (arg, "none")) + deleting = true; + else + args{end+1} = arg; endif else - error ("colorbar: misisng axes handle after 'peer'"); + args{end+1} = arg; endif + endwhile + + if (isempty (ax)) + ax = gca (); + endif + obj = get (ax); + + if (deleting) + objs = findobj (get (ax, "parent"), "type", "axes"); + for i = 1 : length (objs) + if (strcmp (get (objs(i), "tag"), "colorbar") && + get (objs(i), "axes") == ax) + delete (objs(i)); + endif + endfor else - ax = gca (); + position = obj.position; + clen = rows (get (get (ax, "parent"), "colormap")); + cext = get (ax, "clim"); + cdiff = (cext(2) - cext(1)) / clen / 2; + cmin = cext(1) + cdiff; + cmax = cext(2) - cdiff; + + orig_pos = obj.position; + orig_opos = obj.outerposition; + [pos, cpos, vertical, mirror, aspect] = ... + __position_colorbox__ (loc, obj, ancestor (ax, "figure")); + set (ax, "activepositionproperty", "position", "position", pos); + + cax = __go_axes__ (get (ax, "parent"), "tag", "colorbar", + "handlevisibility", "off", + "activepositionproperty", "position", + "position", cpos); + addproperty ("location", cax, "radio", + "eastoutside|east|westoutside|west|northoutside|north|southoutside|south", + loc); + addproperty ("axes", cax, "handle", ax); + + if (vertical) + hi = image (cax, [0,1], [cmin, cmax], [1 : clen]'); + if (mirror) + set (cax, "xtick", [], "xdir", "normal", "ydir", "normal", + "ylim", cext, "ylimmode", "manual", + "yaxislocation", "right", args{:}); + else + set (cax, "xtick", [], "xdir", "normal", "ydir", "normal", + "ylim", cext, "ylimmode", "manual", + "yaxislocation", "left", args{:}); + endif + else + hi = image (cax, [cmin, cmax], [0,1], [1 : clen]); + if (mirror) + set (cax, "ytick", [], "xdir", "normal", "ydir", "normal", + "xlim", cext, "xlimmode", "manual", + "xaxislocation", "top", args{:}); + else + set (cax, "ytick", [], "xdir", "normal", "ydir", "normal", + "xlim", cext, "xlimmode", "manual", + "xaxislocation", "bottom", args{:}); + endif + endif + + if (! isnan (aspect)) + set (cax, "dataaspectratio", aspect); + endif + + ctext = text (0, 0, "", "tag", "colorbar","visible", "off", + "handlevisibility", "off", "xliminclude", "off", + "yliminclude", "off", "zliminclude", "off", + "deletefcn", {@deletecolorbar, cax, orig_pos, orig_opos}); + + set (cax, "deletefcn", {@resetaxis, orig_pos, orig_opos}); + + addlistener (ax, "clim", {@update_colorbar_clim, hi, vertical}) + addlistener (ax, "dataaspectratio", {@update_colorbar_axis, cax}) + addlistener (ax, "position", {@update_colorbar_axis, cax}) + endif - pos = "eastoutside"; - for i = 1 : length (varargin) - arg = varargin{i}; - if (length(arg) < 1) - pos = "eastoutside"; - elseif (ischar (arg)) - arg = tolower (arg); - if (strcmp (arg, "off") || strcmp (arg, "none")) - pos = "none"; - elseif (strcmp (arg, "north") || strcmp (arg, "south") - || strcmp (arg, "east") || strcmp (arg, "west") - || strcmp (arg, "northoutside") || strcmp (arg, "southoutside") - || strcmp (arg, "eastoutside") || strcmp (arg, "westoutside")) - pos = arg; + if (nargout > 0) + h = cax; + endif +endfunction + +function deletecolorbar (h, d, hc, pos, opos) + ## Don't delete the colorbar and reset the axis size if the + ## parent figure is being deleted. + if (ishandle (hc) && strcmp (get (hc, "type"), "axes") && + (isempty (gcbf()) || strcmp (get (gcbf(), "beingdeleted"),"off"))) + if (strcmp (get (hc, "beingdeleted"), "off")) + delete (hc); + endif + if (!isempty (ancestor (h, "axes")) && + strcmp (get (ancestor (h, "axes"), "beingdeleted"), "off")) + #set (ancestor (h, "axes"), "position", pos, "outerposition", opos); + endif + endif +endfunction + +function resetaxis (h, d, pos, opos) + if (ishandle (h) && strcmp (get (h, "type"), "axes") && + (isempty (gcbf()) || strcmp (get (gcbf(), "beingdeleted"),"off")) && + ishandle (get (h, "axes"))) + #set (get (h, "axes"), "position", pos, "outerposition", opos); + endif +endfunction + +function update_colorbar_clim (h, d, hi, vert) + if (ishandle (h) && strcmp (get (h, "type"), "image") && + (isempty (gcbf()) || strcmp (get (gcbf(), "beingdeleted"),"off"))) + clen = rows (get (get (h, "parent"), "colormap")); + cext = get (h, "clim"); + cdiff = (cext(2) - cext(1)) / clen / 2; + cmin = cext(1) + cdiff; + cmax = cext(2) - cdiff; + + if (vert) + set (hi, "ydata", [cmin, cmax]); + set (get (hi, "parent"), "ylim", cext); + else + set (hi, "xdata", [cmin, cmax]); + set (get (hi, "parent"), "xlim", cext); + endif + endif +endfunction + +function update_colorbar_axis (h, d, cax) + if (ishandle (cax) && strcmp (get (cax, "type"), "axes") && + (isempty (gcbf()) || strcmp (get (gcbf(), "beingdeleted"),"off"))) + loc = get (cax, "location"); + obj = get (h); + [pos, cpos, vertical, mirror, aspect] = ... + __position_colorbox__ (loc, obj, ancestor (h, "figure")); + + if (vertical) + if (mirror) + set (cax, "xtick", [], "xdir", "normal", "ydir", "normal", + "yaxislocation", "right", "position", cpos); else - error ("colorbar: unrecognized position argument"); + set (cax, "xtick", [], "xdir", "normal", "ydir", "normal", + "yaxislocation", "left", "position", cpos); endif else - error ("colorbar: expecting string arguments"); + if (mirror) + set (cax, "ytick", [], "xdir", "normal", "ydir", "normal", + "xaxislocation", "top", "position", cpos); + else + set (cax, "ytick", [], "xdir", "normal", "ydir", "normal", + "xaxislocation", "bottom", "position", cpos); + endif + endif + + if (! isnan (aspect)) + aspect + set (cax, "dataaspectratio", aspect); + endif + endif +endfunction + +function [pos, cpos, vertical, mirr, aspect] = __position_colorbox__ (cbox, obj, cf) + + pos = obj.position; + sz = pos(3:4); + + off = 0; + if (strcmpi (obj.dataaspectratiomode, "manual")) + r = obj.dataaspectratio; + if (pos(3) > pos(4)) + switch (cbox) + case {"east", "eastoutside", "west", "westoutside"} + off = [(pos(3) - pos(4)) ./ (r(2) / r(1)), 0]; + endswitch + else + switch (cbox) + case {"north", "northoutside", "south", "southoutside"} + off = [0, (pos(4) - pos(3)) ./ (r(1) / r(2))]; + ## This shouldn't be here except that gnuplot doesn't have a + ## square window and so a square aspect ratio is not square. + ## The corrections are empirical. + if (strcmp (get (cf, "__backend__"), "gnuplot")) + if (length (cbox) > 7 && strcmp (cbox(end-6:end),"outside")) + off = off / 2; + else + off = off / 1.7; + endif + endif + endswitch endif - endfor + off = off / 2; + endif - set (ax, "__colorbar__", pos); + switch (cbox) + case "northoutside" + origin = pos(1:2) + [0., 0.9] .* sz + [1, -1] .* off; + sz = sz .* [1.0, 0.06]; + pos(4) = 0.8 * pos(4); + mirr = true; + vertical = false; + case "north" + origin = pos(1:2) + [0.05, 0.9] .* sz + [1, -1] .* off; + sz = sz .* [1.0, 0.06] * 0.9; + mirr = false; + vertical = false; + case "southoutside" + origin = pos(1:2) + off; + sz = sz .* [1.0, 0.06]; + pos(2) = pos(2) + pos(4) * 0.2; + pos(4) = 0.8 * pos(4); + mirr = false; + vertical = false; + case "south" + origin = pos(1:2) + [0.05, 0.05] .* sz + off; + sz = sz .* [1.0, 0.06] * 0.9; + mirr = true; + vertical = false; + case "eastoutside" + origin = pos(1:2) + [0.9, 0] .* sz + [-1, 1] .* off; + sz = sz .* [0.06, 1.0]; + pos(3) = 0.8 * pos(3); + mirr = true; + vertical = true; + case "east" + origin = pos(1:2) + [0.9, 0.05] .* sz + [-1, 1] .* off; + sz = sz .* [0.06, 1.0] * 0.9; + mirr = false; + vertical = true; + case "westoutside" + origin = pos(1:2) + off; + sz = sz .* [0.06, 1.0]; + pos(1) = pos(1) + pos(3) * 0.2; + pos(3) = 0.8 * pos(3); + mirr = false; + vertical = true; + case "west" + origin = pos(1:2) + [0.05, 0.05] .* sz + off; + sz = sz .* [0.06, 1.0] .* 0.9; + mirr = true; + vertical = true; + endswitch + + cpos = [origin, sz]; + + if (strcmpi (obj.dataaspectratiomode, "manual")) + r = obj.dataaspectratio; + + if (pos(3) > pos(4)) + if (vertical) + aspect = [1, 0.21, 1]; + else + aspect = [0.21, 1, 1]; + endif + else + if (vertical) + aspect = [1, 0.21, 1]; + else + aspect = [0.21, 1, 1]; + endif + endif + else + aspect = NaN; + endif endfunction - %!demo %! hold off; %! close all;
--- a/scripts/plot/legend.m +++ b/scripts/plot/legend.m @@ -80,10 +80,9 @@ function legend (varargin) + [ca, varargin, nargin] = __plt_get_axis_arg__ ("legend", varargin{:}); nargs = nargin; - ca = gca (); - if (nargs > 0) pos = varargin{nargs}; if (isnumeric (pos) && isscalar (pos) && round (pos) == pos) @@ -132,12 +131,25 @@ case "boxoff" set (ca, "keybox", "off"); otherwise - while (k <= nkids && ! strcmp (get (kids(k), "type"), "line")) + typ = get (kids (k), "type"); + while (k <= nkids && ! strcmp (typ, "line") && + ! strcmp (typ, "hggroup")) k++; endwhile if (k <= nkids) turn_on_legend = true; - set (kids(k), "keylabel", arg); + if (strcmp (typ, "hggroup")) + hgkids = get (kids(k), "children"); + for j = 1 : length (hgkids) + hgobj = get (hgkids (j)); + if (isfield (hgobj, "keylabel")) + set (hgkids(j), "keylabel", arg); + break; + endif + endfor + else + set (kids(k), "keylabel", arg); + endif else warning ("legend: ignoring extra labels"); endif @@ -160,7 +172,8 @@ for i = 1:nkids if (strcmp (get (kids(k), "type"), "line") || strcmp (get (kids(k), "type"), "surface") - || strcmp (get (kids(k), "type"), "patch")) + || strcmp (get (kids(k), "type"), "patch") + || strcmp (get (kids(k), "type"), "hggroup")) have_data = true; break; endif @@ -177,11 +190,23 @@ while (k <= nkids && ! (strcmp (get (kids(k), "type"), "line") || strcmp (get (kids(k), "type"), "surface") - || strcmp (get (kids(k), "type"), "patch"))) + || strcmp (get (kids(k), "type"), "patch") + || strcmp (get (kids(k), "type"), "hggroup"))) k++; endwhile if (k <= nkids) - set (kids(k), "keylabel", arg); + if (strcmp (get (kids(k), "type"), "hggroup")) + hgkids = get (kids(k), "children"); + for j = 1 : length (hgkids) + hgobj = get (hgkids (j)); + if (isfield (hgobj, "keylabel")) + set (hgkids(j), "keylabel", arg); + break; + endif + endfor + else + set (kids(k), "keylabel", arg); + endif turn_on_legend = true; k++; elseif (! warned) @@ -189,6 +214,9 @@ warning ("legend: ignoring extra labels"); endif else + arg + get(kids(k),"type") + k error ("legend: expecting argument to be a character string"); endif endfor
--- a/scripts/plot/newplot.m +++ b/scripts/plot/newplot.m @@ -49,8 +49,13 @@ otherwise error ("newplot: unrecognized nextplot property for current axes"); endswitch + + yt = get (ca, "ylabel"); + if (! strcmp (get (yt, "type"), "text")) + disp("BAD!!!!!"); + get(yt) + endif else print_usage (); endif - endfunction
--- a/scripts/plot/pareto.m +++ b/scripts/plot/pareto.m @@ -55,8 +55,6 @@ function h = pareto (varargin) - [ax, varargin, nargin] = __plt_get_axis_arg__ ("pareto", varargin{:}); - if (nargin != 1 && nargin != 2) print_usage (); endif @@ -84,7 +82,7 @@ cdf95 = cdf - 0.95; idx95 = find(sign(cdf95(1:end-1)) != sign(cdf95(2:end)))(1); - [ax, hbar, hline] = plotyy (ax, 1 : idx95, x (1 : idx95), + [ax, hbar, hline] = plotyy (1 : idx95, x (1 : idx95), 1 : length(cdf), 100 .* cdf, @bar, @plot);
--- a/scripts/plot/plotyy.m +++ b/scripts/plot/plotyy.m @@ -77,10 +77,14 @@ ax(2) = axes (); else ax = get (f, "children"); - for i = 3 : length (ax) - delete (ax (i)); - endfor - ax = ax(1:2); + if (length (ax) > 2) + for i = 3 : length (ax) + delete (ax (i)); + endfor + ax = ax(1:2); + elseif (length (ax) == 1) + ax(2) = axes (); + endif endif if (nargin < 2) varargin = {}; @@ -125,8 +129,6 @@ h1 = feval (fun1, x1, y1); set (ax(1), "ycolor", getcolor (h1(1))); - set (ax(1), "position", [0.11 0.13 0.78 0.73]); - set (ax(1), "activepositionproperty", "position"); set (ax(1), "xlim", xlim); cf = gcf (); @@ -141,9 +143,68 @@ set (ax(2), "yaxislocation", "right"); set (ax(2), "ycolor", getcolor (h2(1))); set (ax(2), "position", get (ax(1), "position")); - set (ax(2), "activepositionproperty", "position"); set (ax(2), "xlim", xlim); set (ax(2), "color", "none"); + + ## Add invisible text objects that when destroyed, + ## also remove the other axis + t1 = text (0, 0, "", "parent", ax(1), "tag", "plotyy", + "handlevisibility", "off", "visible", "off", + "xliminclude", "off", "yliminclude", "off"); + t2 = text (0, 0, "", "parent", ax(2), "tag", "plotyy", + "handlevisibility", "off", "visible", "off", + "xliminclude", "off", "yliminclude", "off"); + + set (t1, "deletefcn", {@deleteplotyy, ax(2), t2}); + set (t2, "deletefcn", {@deleteplotyy, ax(1), t1}); + + addlistener (ax(1), "position", {@update_position, ax(2)}); + addlistener (ax(2), "position", {@update_position, ax(1)}); + addlistener (ax(1), "view", {@update_position, ax(2)}); + addlistener (ax(2), "view", {@update_position, ax(1)}); + + ## Tag the plotyy axes, so we can use that information + ## not to mirror the y axis tick marks + set (ax, "tag", "plotyy") + +endfunction + +%!demo +%! x = 0:0.1:2*pi; +%! y1 = sin (x); +%! y2 = exp (x - 1); +%! ax = plotyy (x, y1, x - 1, y2, @plot, @semilogy); +%! xlabel ("X"); +%! ylabel (ax(1), "Axis 1"); +%! ylabel (ax(2), "Axis 2"); + +function deleteplotyy (h, d, ax2, t2) + if (ishandle (ax2) && strcmp (get (ax2, "type"), "axes") && + (isempty (gcbf()) || strcmp (get (gcbf(), "beingdeleted"),"off")) && + strcmp (get (ax2, "beingdeleted"), "off")) + set (t2, "deletefcn", []); + delete (ax2); + endif +endfunction + +function update_position (h, d, ax2) + persistent recursion = false; + + ## Don't allow recursion + if (! recursion) + unwind_protect + recursion = true; + position = get (h, "position"); + view = get (h, "view"); + oldposition = get (ax2, "position"); + oldview = get (ax2, "view"); + if (! (isequal (position, oldposition) && isequal (view, oldview))) + set (ax2, "position", position, "view", view); + endif + unwind_protect_cleanup + recursion = false; + end_unwind_protect + endif endfunction function color = getcolor (ax) @@ -159,11 +220,3 @@ endif endfunction -%!demo -%! x = 0:0.1:2*pi; -%! y1 = sin (x); -%! y2 = exp (x - 1); -%! ax = plotyy (x, y1, x - 1, y2, @plot, @semilogy); -%! xlabel ("X"); -%! ylabel (ax(1), "Axis 1"); -%! ylabel (ax(2), "Axis 2");
--- a/scripts/plot/subplot.m +++ b/scripts/plot/subplot.m @@ -126,8 +126,9 @@ continue; endif if (strcmp (get (child, "type"), "axes")) - ## Skip legend objects. - if (strcmp (get (child, "tag"), "legend")) + ## Skip legend and colorbar objects. + if (strcmp (get (child, "tag"), "legend") || + strcmp (get (child, "tag"), "colorbar")) continue; endif objpos = get (child, "outerposition"); @@ -136,7 +137,6 @@ ## existing axes object, use the existing axes. found = true; tmp = child; - break; else ## If the new axes overlap an old axes object, delete the old ## axes. @@ -154,7 +154,9 @@ if (found) set (cf, "currentaxes", tmp); else - tmp = axes ("outerposition", pos); + border = [0.130, 0.110, 0.225, 0.185] .* [xsize, ysize, xsize, ysize]; + pos2 = [pos(1:2) + border(1:2), pos(3:4) - border(1:2) - border(3:4)]; + tmp = axes ("outerposition", pos, "position", pos2); endif if (nargout > 0)
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -3,6 +3,19 @@ * octave.cc (octave_main): Make all command-line arguments available to startup scripts and PKG_ADD files. +2008-09-10 David Bateman <dbateman@free.fr> + + * graphics.h.in (radio_property axes::properties::__colorbar__): + Delete. + * graphics.cc (void axes::properties::sync_positions (void)): + Disable code synchronizing outerposiiton and position. + (void axes::properties::set_defaults (base_graphics_object&, + const std::string&): Remove __colorbar__. + (F__go_delete__): Don't delete if already being deleting to avoid + recursion in callback functions. + (F__go_axes_init__): Flag error if handle is deleted during + initialization due. + 2008-09-09 David Bateman <dbateman@free.fr> * DLD-FUNCTIONS/regexp.cc (octregexp_list): Distinguish between
--- a/src/graphics.cc +++ b/src/graphics.cc @@ -1301,8 +1301,9 @@ graphics_backend backend = p->second.get_backend (); if (backend) backend.object_destroyed (p->second); - // note - this will be valid only for first explicitly deleted object. - // All his children will have unknown backend then. + // note - this will be valid only for first explicitly + // deleted object. All its children will then have an + // unknown backend. handle_map.erase (p); @@ -1713,8 +1714,15 @@ { octave_idx_type n = children.numel (); + // A callback function might have already deleted the child, + // so check before deleting for (octave_idx_type i = 0; i < n; i++) - gh_manager::free (children(i)); + { + graphics_object go = gh_manager::get_object (children(i)); + + if (go.valid_object ()) + gh_manager::free (children(i)); + } } graphics_backend @@ -2080,8 +2088,12 @@ void axes::properties::sync_positions (void) { +#if 0 // FIXME -- this should take font metrics into consideration, - // for now we'll just make it position 90% of outerposition + // and also the fact that the colorbox leaves the outerposition + // alone but alters the position. For now just don't adjust the + // positions relative to each other. + if (activepositionproperty.is ("outerposition")) { Matrix outpos = outerposition.get ().matrix_value (); @@ -2102,6 +2114,7 @@ pos(3) *= 1.1; outerposition = pos; } +#endif update_transform (); } @@ -2158,7 +2171,14 @@ axes::properties::set_defaults (base_graphics_object& obj, const std::string& mode) { + gh_manager::free (title.handle_value ()); title = graphics_handle (); + + if (! title.handle_value ().ok ()) + std::cerr << "set_defaults not ok\n"; + else + std::cerr << "set_defaults ok " << title.handle_value().value () << "\n"; + box = "on"; key = "off"; keybox = "off"; @@ -2182,9 +2202,14 @@ ylimmode = "auto"; zlimmode = "auto"; climmode = "auto"; + + gh_manager::free (xlabel.handle_value ()); + gh_manager::free (ylabel.handle_value ()); + gh_manager::free (zlabel.handle_value ()); xlabel = graphics_handle (); ylabel = graphics_handle (); zlabel = graphics_handle (); + xgrid = "off"; ygrid = "off"; zgrid = "off"; @@ -2265,7 +2290,6 @@ } activepositionproperty = "outerposition"; - __colorbar__ = "none"; delete_children (); @@ -2279,8 +2303,19 @@ graphics_handle axes::properties::get_title (void) const { + if (! title.handle_value ().ok ()) + std::cerr << "get_title not ok\n"; + else + std::cerr << "get_title ok " << title.handle_value().value () << "\n"; + + if (! title.handle_value ().ok ()) title = gh_manager::make_graphics_handle ("text", __myhandle__); + + if (! title.handle_value ().ok ()) + std::cerr << "get_title 2 not ok\n"; + else + std::cerr << "get_title 2 ok " << title.handle_value().value () << "\n"; return title.handle_value (); } @@ -4405,19 +4440,26 @@ { graphics_object obj = gh_manager::get_object (h); - graphics_handle parent_h = obj.get_parent (); - - graphics_object parent_obj = gh_manager::get_object (parent_h); - - // NOTE: free the handle before removing it from its parent's - // children, such that the object's state is correct when - // the deletefcn callback is executed - - gh_manager::free (h); - - parent_obj.remove_child (h); - - Vdrawnow_requested = true; + // Don't do recursive deleting, due to callbacks + if (! obj.get_properties ().is_beingdeleted ()) + { + graphics_handle parent_h = obj.get_parent (); + + graphics_object parent_obj = + gh_manager::get_object (parent_h); + + // NOTE: free the handle before removing it from its parent's + // children, such that the object's state is correct + // when the deletefcn callback is executed + + gh_manager::free (h); + + // A callback function might have already deleted the parent + if (parent_obj.valid_object ()) + parent_obj.remove_child (h); + + Vdrawnow_requested = true; + } } else error ("delete: invalid graphics object (= %g)", val); @@ -4468,6 +4510,10 @@ graphics_object obj = gh_manager::get_object (h); obj.set_defaults (mode); + + h = gh_manager::lookup (val); + if (! h.ok ()) + error ("__go_axes_init__: axis deleted during initialization (= %g)", val); } else error ("__go_axes_init__: invalid graphics object (= %g)", val);
--- a/src/graphics.h.in +++ b/src/graphics.h.in @@ -2595,7 +2595,6 @@ radio_property nextplot , "add|replace_children|{replace}" array_property outerposition u , default_axes_outerposition () radio_property activepositionproperty , "{outerposition}|position" - radio_property __colorbar__ h , "{none}|north|south|east|west|northoutside|southoutside|eastoutside|westoutside" color_property ambientlightcolor , color_values (1, 1, 1) array_property cameraposition m , Matrix (1, 3, 0.0) array_property cameratarget m , Matrix (1, 3, 0.0)