[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Changeset]: Add area, bar, quiver and stair series objects
From: |
David Bateman |
Subject: |
[Changeset]: Add area, bar, quiver and stair series objects |
Date: |
Tue, 26 Aug 2008 17:43:33 +0200 |
User-agent: |
Thunderbird 2.0.0.16 (X11/20080725) |
Subject says it all
D.
--
David Bateman address@hidden
Motorola Labs - Paris +33 1 69 35 48 04 (Ph)
Parc Les Algorithmes, Commune de St Aubin +33 6 72 01 06 33 (Mob)
91193 Gif-Sur-Yvette FRANCE +33 1 69 35 77 01 (Fax)
The information contained in this communication has been classified as:
[x] General Business Information
[ ] Motorola Internal Use Only
[ ] Motorola Confidential Proprietary
# HG changeset patch
# User David Bateman <address@hidden>
# Date 1219765329 -7200
# Node ID 541f747484a40bad18d1f027444233b8d01ef897
# Parent 926624ba256e6c6679666ecae2d215178403c1b7
Add area, bar, quiver and stair series graphics objects. Document them
diff --git a/doc/ChangeLog b/doc/ChangeLog
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,8 @@ 2008-08-21 David Bateman <address@hidden
+2008-08-26 David Bateman <address@hidden>
+
+ * interpreter/plot.txi: Document the group objects (bar, stem,
+ stair, quiver and area series), and cllback functions.
+
2008-08-21 David Bateman <address@hidden>
* interpreter/plot.txi: Document ezplot.
diff --git a/doc/interpreter/plot.txi b/doc/interpreter/plot.txi
--- a/doc/interpreter/plot.txi
+++ b/doc/interpreter/plot.txi
@@ -439,7 +439,9 @@ at the Octave prompt should display a th
* Colors::
* Line Styles::
* Marker Styles::
-* Interaction with gnuplot::
+* Callbacks::
+* Object Groups::
+* Graphics backends::
@end menu
@node Graphics Objects
@@ -1340,9 +1342,385 @@ of 2 is twice as large as the default, e
of 2 is twice as large as the default, etc.
@end table
address@hidden Callbacks
address@hidden Callbacks
+
+Callback functions can be associated with graphics objects and triggered
+after certain events occur. The basic structure of all callback function
+is
+
address@hidden
address@hidden
+function mycallback (src, data)
address@hidden
+endfunction
address@hidden group
address@hidden example
+
+where @code{src} gives a handle to the source of the callback, and
address@hidden gives some event specific data. This can then be associated
+with an object either at the objects creation or later with the
address@hidden function. For example
+
address@hidden
+plot (x, "DeleteFcn", @@(s, e) disp("Window Deleted"))
address@hidden example
+
address@hidden
+where at the moment that the plot is deleted, the message "Window
+Deleted" will be displayed.
+
+Additional user arguments can be passed to callback functions, and will
+be passed after the 2 default arguments. For example
+
address@hidden
+plot (x, "DeleteFcn", {@@mycallback, "1"})
address@hidden
+function mycall (src, data, a1)
+ fprintf ("Closing plot %d\n", a1);
+endfunction
address@hidden example
+
+The basic callback functions that are available for all graphics objects
+are
+
address@hidden @bullet
address@hidden CreateFcn
+This is the callback that is called at the moment of the objects
+creation. It is not called if the object is altered in any way, and so
+it only makes sense to define this callback in the function call that
+defines the object. Callbacks that are added to @code{CreateFcn} later with
+the @code{set} function will never be executed.
+
address@hidden DeleteFcn
+This is the callback that is called at the moment an object is deleted.
+
address@hidden ButtonDownFcn
+This is the callback that is called if a mouse button is pressed while
+the pointer is over this object. Note, that the gnuplot interface does
+not respect this callback.
address@hidden itemize
+
+The object and figure that the event occurred in that resulted in the
+callback being called can be found with the @code{gcbo} and @code{gcbf}
+functions.
+
address@hidden(gcbo)
+
address@hidden(gcbf)
+
+Callbacks can equally be added to properties with the @code{addlistener}
+function described below.
+
address@hidden Object Groups
address@hidden Object Groups
+
+A number of Octave high level plot functions return groups of other
+graphics objects or they return graphics objects that are have their
+properties linked in such a way that changes to one of the properties
+results in changes in the others. A graphic object that groups other
+objects is an @code{hggroup}
+
address@hidden(hggroup)
+
+For example a simple use of a @code{hggroup} might be
+
address@hidden
address@hidden
+x = 0:0.1:10;
+hg = hggroup ();
+plot (x, sin (x), "color", [1, 0, 0], "parent", hg);
+hold on
+plot (x, cos (x), "color", [0, 1, 0], "parent", hg);
+set (hg, "visible", "off");
address@hidden group
address@hidden example
+
address@hidden
+which groups the two plots into a single object and contols their
+visiblity directly. The default properties of an @code{hggroup} are
+the same as the set of common properties for the other graphics
+objects. Additional properties can be added with the @code{addproperty}
+function.
+
address@hidden(addproperty)
+
+Once a property in added to an @code{hggroup}, it is not linked to any
+other property of either the children of the group, or any other
+graphics object. Add so to control the way in which this newly added
+property is used, the @code{addlistener} function is used to define a
+callback function that is executed when the property is altered.
+
address@hidden(addlistener)
+
+An example of the use of these two functions might be
+
address@hidden
address@hidden
+x = 0:0.1:10;
+hg = hggroup ();
+h = plot (x, sin (x), "color", [1, 0, 0], "parent", hg);
+addproperty ("linestyle", hg, "linelinestyle", get (h, "linestyle"));
+addlistener (hg, "linestyle", @@update_props);
+hold on
+plot (x, cos (x), "color", [0, 1, 0], "parent", hg);
+
+function update_props (h, d)
+ set (get (h, "children"), "linestyle", get (h, "linestyle"));
+endfunction
address@hidden group
address@hidden example
+
address@hidden
+that adds a @code{linestyle} property to the @code{hggroup} and
+propagating any changes its its value to the children of the group.
+
+These capabilities are used in a number of basic graphics objects.
+The @code{hggroup} objects created by the functions of Octave contain
+one or more graphics object and are used to:
+
address@hidden @bullet
address@hidden group together multiple graphics objects,
address@hidden create linked properties between different graphics objects, and
address@hidden to hide the nominal user data, from the actual data of the
objects.
address@hidden itemize
+
address@hidden
+For example the @code{stem} function creates a stem series where each
address@hidden of the stem series contains two line objects representing
+the body and head of the stem. The @code{ydata} property of the
address@hidden of the stem series represents the head of the stem,
+whereas the body of the stem is between the baseline and this value. For
+example
+
address@hidden
address@hidden
+h = stem (1:4)
+get (h, "xdata")
address@hidden [ 1 2 3 4]'
+get (get (h, "children")(1), "xdata")
address@hidden [ 1 1 NaN 2 2 NaN 3 3 NaN 4 4 NaN]'
address@hidden group
address@hidden example
+
address@hidden
+shows the the difference between the @code{xdata} of the @code{hggroup}
+of a stem series object and the underlying line.
+
+The basic properties of such group objects is that they consist of one
+or more linked @code{hggroup}, and that changes in certain properties of
+these groups are propagated to other members of the group. Whereas,
+certain properties of the members of the group only apply to the current
+member.
+
+In addition the members of the group can also be linked to other
+graphics objects through callback functions. For example the baseline of
+the @code{bar} or @code{stem} functions is a line object, whose length
+and position are automatically adjusted, based on changes to the
+corresponding hggroup elements.
+
address@hidden
+* Area series::
+* Bar series::
+* Contour groups::
+* Error bar series::
+* Line series::
+* Quiver group::
+* Scatter group::
+* Stair group::
+* Stem Series::
+* Surface group::
address@hidden menu
+
address@hidden Area series
address@hidden Area series
+
+Area series objects are created by the @code{area} function. Each of the
address@hidden elements contains a single patch object. The properties
+of the area series are
+
address@hidden @code
address@hidden basevalue
+The value where the base of the area plot is drawn.
+
address@hidden linewidth
address@hidden linestyle
+The line width and style of the edge of the patch objects making up the
+areas. @xref{Line Styles}.
+
address@hidden edgecolor
address@hidden facecolor
+The line and fill color of the patch objects making up the areas.
@xref{Colors}.
+
address@hidden xdata
address@hidden ydata
+The x and y coordinates of the original columns of the data passed to
address@hidden prior to the cummulative summation used in the @code{area}
+function.
address@hidden table
+
address@hidden Bar series
address@hidden Bar series
+
+Bar series objects are created by the @code{bar} or @code{barh}
+functions. Each @code{hgrroup} element contains a single patch object.
+The properties of the bar series are
+
address@hidden @code
address@hidden showbaseline
address@hidden baseline
address@hidden basevalue
+The property @code{showbaseline} flags whether the baseline of the bar
+series is displayed (default is "on"). The handle of the graphics object
+representing the baseline is given by the @code{baseline} property and
+the y-value of the baseline by the @code{basevalue} property.
+
+Changes to any of these property are propagated to the other members of
+the bar series and to the baseline itself. Equally changes in the
+properties of the base line itself are propagated to the members of the
+corresponding bar series.
+
address@hidden barwidth
address@hidden barlayout
address@hidden horizontal
+The property @code{barwidth} is the width of the bar corresponding to
+the @var{width} variable passed to @code{bar} or @var{barh}. Whether the
+bar series is "grouped" or "stacked" is determined by the
address@hidden property and whether the bars are horizontal or
+vertical by the @code{horizontal} property.
+
+Changes to any of these property are propagated to the other members of
+the bar series.
+
address@hidden linewidth
address@hidden linestyle
+The line width and style of the edge of the patch objects making up the
+bars. @xref{Line Styles}.
+
address@hidden edgecolor
address@hidden facecolor
+The line and fill color of the patch objects making up the bars. @xref{Colors}.
+
address@hidden xdata
+The nominal x positions of the bars. Changes in this property and
+propagated to the other members of the bar series.
+
address@hidden ydata
+The y value of the bars in the @code{hggroup}.
address@hidden table
+
address@hidden Contour groups
address@hidden Contour groups
+
+TO BE WRITTEN
+
address@hidden Error bar series
address@hidden Error bar series
+
+TO BE WRITTEN
+
address@hidden Line series
address@hidden Line series
+
+TO BE WRITTEN
+
address@hidden Quiver group
address@hidden Quiver group
+
+Quiver series objects are created by the @code{quiver} or @code{quiver3}
+functions. Each @code{hggroup} element of the series contains three line
+objects as children representing the body and head of the arrow,
+together with a marker as the point of original of the arrows. The
+properties of the quiver series are
+
address@hidden @code
address@hidden autoscale
address@hidden autoscalefactor
+Flag whether the length of the arrows is scaled or defined directly from
+the @var{u}, @var{v} and @var{w} data. If the arrow length is falgged
+as being scaled by the @code{autoscale} property, then the length of the
+autoscaled arrow is controlled by the @code{autoscalefactor}.
+
address@hidden maxheadsize
+This property controls the size of the head of the arrows in the quiver
+series. The default value is 0.2.
+
address@hidden showarrowhead
+Flag whether the arrow heads are displayed in the quiver plot.
+
address@hidden color
+The RGB color or color name of the line objects of the quiver. @xref{Colors}.
+
address@hidden linewidth
address@hidden linestyle
+The line width and style of the line objects of the quiver. @xref{Line Styles}.
+
address@hidden marker
address@hidden markerfacecolor
address@hidden markersize
+The line and fill color of the marker objects at the original of the
+arrows. @xref{Colors}.
+
address@hidden xdata
address@hidden ydata
address@hidden zdata
+The origins of the values of the vector field.
+
address@hidden udata
address@hidden vdata
address@hidden wdata
+The values of the vector field to plot.
address@hidden table
+
address@hidden Scatter group
address@hidden Scatter group
+
+TO BE WRITTEN
+
address@hidden Stair group
address@hidden Stair group
+
+Stair series objects are created by the @code{stair} function. Each
address@hidden element of the series contains a single line object as a
+child representing the stair. The properties of the stair series are
+
address@hidden @code
address@hidden color
+The RGB color or color name of the line objects of the stairs. @xref{Colors}.
+
address@hidden linewidth
address@hidden linestyle
+The line width and style of the line objects of the stairs. @xref{Line Styles}.
+
address@hidden marker
address@hidden markeredgecolor
address@hidden markerfacecolor
address@hidden markersize
+The line and fill color of the markers on the stairs. @xref{Colors}.
+
address@hidden xdata
address@hidden ydata
+The original x and y data of the stairs.
address@hidden table
+
address@hidden Surface group
address@hidden Surface group
+
+TO BE WRITTEN
+
address@hidden Graphics backends
address@hidden Graphics backends
+
address@hidden(available_backends)
+
address@hidden
+* Interaction with gnuplot::
address@hidden menu
+
@node Interaction with gnuplot
address@hidden Interaction with @code{gnuplot}
address@hidden Interaction with @code{gnuplot}
@DOCSTRING(gnuplot_binary)
@DOCSTRING(gnuplot_use_title_option)
+
diff --git a/scripts/ChangeLog b/scripts/ChangeLog
--- a/scripts/ChangeLog
+++ b/scripts/ChangeLog
@@ -1,3 +1,23 @@ 2008-08-25 Thomas L. Scofield <scofiel
+2008-08-26 David Bateman <address@hidden>
+
+ * plot/__area__.m: Use __next_line_color__ rather than fixed set
+ of colors. Convert to use area series objects.
+ * plot/area.m: Update documentation to correspond to
+ the area series usage.
+ * plot/__bar.m: Pass the original rather than scaled width to
+ __bars__.
+ * plot/__bars__.m: Convert to use bar series objects.
+ * plot/bar.m, plor/barh.m: Update documentation to correspond to
+ the bar series usage.
+ * plot/__quiver__.m: Convert to use quiver series objects. Change
+ the default scaling and arrowsize for compatibility.
+ * plot/quiver.m: Update documentation to correspond to
+ the quiver series usage.
+ * plot/stairs.m: Convert to use stair series objects.
+ * plot/stem.m: Don't include baseline in xlim calculation. Correct
+ test of whether baseline xdata needs updating in the update_xlim
+ callback.
+
2008-08-25 Thomas L. Scofield <address@hidden>
* image/imwrite.m: Add ras and tiff to the list of accepted formats.
@@ -5,11 +25,14 @@ 2008-08-25 Thomas L. Scofield <scofiel
2008-08-25 David Bateman <address@hidden>
+ * plot/__stem__.m: Use property inheritance and don't explicitly
+ call drawnow.
+
* plot/__go_draw_axes__.m: Respect the "visible" property of object and
don't draw them if the object is not visible.
* plot/__stem__.m: Convert to use stem series object.
- * plot/stem.m, plot/stem3.m: Update documentation to correpsond to
+ * plot/stem.m, plot/stem3.m: Update documentation to correspond to
the stem series usage.
2008-08-22 John W. Eaton <address@hidden>
@@ -36,11 +59,6 @@ 2008-08-20 Jaroslav Hajek <address@hidden
* pkg/pkg.m (configure_make): Pass handle to is_architecture_dependent
directly.
-
-2008-08-25 David Bateman <address@hidden>
-
- * plot/__stem__.m: Use property inheritance and don't explicitly
- call drawnow.
2008-08-20 David Bateman <address@hidden>
diff --git a/scripts/plot/__area__.m b/scripts/plot/__area__.m
--- a/scripts/plot/__area__.m
+++ b/scripts/plot/__area__.m
@@ -20,20 +20,99 @@
function retval = __area__ (ax, x, y, bv, varargin)
- colors = [1, 0, 0; 0, 1, 0; 0, 0, 1; 1, 1, 0; 1, 0, 1; 0, 1, 1];
+ y0 = bv * ones (1, rows (y));
+ y0 = zeros (1, rows (y));
+ retval = [];
+ for i = 1: size (y, 2);
+ hg = hggroup ();
+ x1 = x(:, 1).';
+ y1 = y (:, i).';
+ addproperty ("xdata", hg, "data", x1);
+ addproperty ("ydata", hg, "data", y1);
- x = [x(1,:); x; x(end,:)];
+ addlistener (hg, "xdata", @update_data);
+ addlistener (hg, "ydata", @update_data);
- y = cumsum ([[bv, ones(1, size (y, 2) - 1)]; y;
- [bv, ones(1, size (y, 2) - 1)]], 2);
+ if (i == 1)
+ h = patch (ax, [x1(1), x1, fliplr(x1)], [bv, y1, bv*ones(1, length(y1))],
+ __next_line_color__ (), "parent", hg, varargin{:});
+ else
+ y1 = y0 + y1;
+ h = patch (ax, [x1(1), x1, fliplr(x1)], [y0(1), y1, fliplr(y0)],
+ __next_line_color__ (), "parent", hg, varargin{:});
+ endif
- retval = patch (ax, x(:,1), y(:,1), colors(1,:), varargin{:});
+ y0 = y1;
- for i = 2:size(y,2)
- tmp = patch (ax, [x(:,i); flipud(x(:,i))],
- [y(:,i) ; flipud(y(:, i-1))], colors(i,:), varargin{:});
+ addproperty ("basevalue", hg, "data", bv);
+ addlistener (hg, "basevalue", @move_baseline);
- retval = [retval; tmp];
+ addproperty ("edgecolor", hg, "patchedgecolor", get (h, "edgecolor"));
+ addproperty ("linewidth", hg, "patchlinewidth", get (h, "linewidth"));
+ addproperty ("linestyle", hg, "patchlinestyle", get (h, "linestyle"));
+ addproperty ("facecolor", hg, "patchfacecolor", get (h, "facecolor"));
+
+ addlistener (hg, "edgecolor", @update_props);
+ addlistener (hg, "linewidth", @update_props);
+ addlistener (hg, "linestyle", @update_props);
+ addlistener (hg, "facecolor", @update_props);
+
+ retval = [retval; hg];
+ addproperty ("areagroup", hg, "data");
+ set (retval, "areagroup", retval);
endfor
endfunction
+
+function update_props (h, d)
+ kids = get (h, "children");
+ set (kids, "edgecolor", get (h, "edgecolor"),
+ "linewidth", get (h, "linewidth"),
+ "linestyle", get (h, "linestyle"),
+ "facecolor", get (h, "facecolor"));
+endfunction
+
+function move_baseline (h, d)
+ persistent recursion = false;
+
+ ## Don't allow recursion
+ if (! recursion)
+ unwind_protect
+ recursion = true;
+ hlist = get (h, "areagroup");
+ b0 = get (h, "basevalue");
+
+ for hh = hlist(:)'
+ if (hh != h )
+ b1 = get (hh, "basevalue");
+ if (b1 != b0)
+ set (hh, "basevalue", b0);
+ endif
+ endif
+ endfor
+ update_data (h, d);
+ unwind_protect_cleanup
+ recursion = false;
+ end_unwind_protect
+ endif
+endfunction
+
+function update_data (h, d)
+ hlist = get (h, "areagroup");
+ bv = get (h, "basevalue");
+ for i = 1 : length (hlist)
+ hh = hlist(i);
+ x1 = get (hh, "xdata")(:);
+ y1 = get (hh, "ydata")(:);
+
+ set (get (hh, "children"), "xdata", [x1(1); x1; flipud(x1)]);
+ if (i == 1)
+ set (get (hh, "children"), "ydata", [bv; y1; bv*ones(length(y1), 1)]);
+ else
+ y1 = y0 + y1;
+ set (get (hh, "children"), "ydata", [y0(1); y1; flipud(y0)]);
+ endif
+
+ y0 = y1;
+ endfor
+endfunction
diff --git a/scripts/plot/__bar__.m b/scripts/plot/__bar__.m
--- a/scripts/plot/__bar__.m
+++ b/scripts/plot/__bar__.m
@@ -110,18 +110,17 @@ function varargout = __bar__ (vertical,
endif
ycols = size (y, 2);
+ cutoff = min (diff (double(x))) / 2;
if (group)
- width = width / ycols;
+ delta_p = delta_m = repmat (cutoff * width / ycols, size (x));
+ else
+ delta_p = delta_m = repmat (cutoff * width, size (x));
endif
-
- cutoff = min (diff (double(x))) / 2;
- delta_p = delta_m = repmat (cutoff * width, size (x));
x1 = (x - delta_m)(:)';
x2 = (x + delta_p)(:)';
xb = repmat ([x1; x1; x2; x2](:), 1, ycols);
if (group)
- width = width / ycols;
offset = ((delta_p + delta_m) * [-(ycols - 1) / 2 : (ycols - 1) / 2]);
xb(1:4:4*ylen,:) += offset;
xb(2:4:4*ylen,:) += offset;
diff --git a/scripts/plot/__bars__.m b/scripts/plot/__bars__.m
--- a/scripts/plot/__bars__.m
+++ b/scripts/plot/__bars__.m
@@ -20,43 +20,245 @@
## Author: jwe
-function tmp = __bars__ (h, vertical, x, y, xb, yb, width, group,
have_color_spec, base_value, varargin)
-
- ## Note, base_value is used by the Jhandles backend, which replaces
- ## this function with its own version.
+function tmp = __bars__ (ax, vertical, x, y, xb, yb, width, group,
have_color_spec, base_value, varargin)
ycols = columns (y);
- clim = get (h, "clim");
-
- if (vertical)
- tmp = [];
- for i = 1:ycols
+ clim = get (ax, "clim");
+ tmp = [];
+
+ for i = 1:ycols
+ hg = hggroup ();
+ tmp = [tmp; hg];
+
+ if (vertical)
if (! have_color_spec)
if (ycols == 1)
lev = clim(1);
else
lev = (i - 1) * (clim(2) - clim(1)) / (ycols - 1) - clim(1);
endif
- tmp = [tmp; patch(xb(:,:,i), yb(:,:,i), "FaceColor", "flat",
- "cdata", lev, varargin{:})];
+ h = patch(xb(:,:,i), yb(:,:,i), "FaceColor", "flat",
+ "cdata", lev, "parent", hg, varargin{:});
else
- tmp = [tmp; patch(xb(:,:,i), yb(:,:,i), varargin{:})];
- endif
- endfor
- else
- tmp = [];
- for i = 1:ycols
+ h = patch(xb(:,:,i), yb(:,:,i), "parent", hg, varargin{:});
+ endif
+ else
if (! have_color_spec)
if (ycols == 1)
lev = clim(1)
else
lev = (i - 1) * (clim(2) - clim(1)) / (ycols - 1) - clim(1);
endif
- tmp = [tmp; patch(yb(:,:,i), xb(:,:,i), "FaceColor", "flat",
- "cdata", lev, varargin{:})];
+ h = patch(yb(:,:,i), xb(:,:,i), "FaceColor", "flat",
+ "cdata", lev, "parent", hg, varargin{:});
else
- tmp = [tmp; patch(yb(:,:,i), xb(:,:,i), varargin{:})];
- endif
- endfor
- endif
-endfunction
+ h = patch(yb(:,:,i), xb(:,:,i), "parent", hg, varargin{:});
+ endif
+ endif
+
+ if (i == 1)
+ x_axis_range = get (ax, "xlim");
+ h_baseline = line (x_axis_range, [0, 0], "color", [0, 0, 0]);
+ set (h_baseline, "handlevisibility", "off");
+ set (h_baseline, "xliminclude", "off");
+ addlistener (ax, "xlim", @update_xlim);
+ addlistener (h_baseline, "ydata", @update_baseline);
+ addlistener (h_baseline, "visible", @update_baseline);
+ endif
+
+ ## Setup the hggroup and listeners
+ addproperty ("showbaseline", hg, "radio", "{on}|off");
+ addproperty ("basevalue", hg, "data", base_value);
+ addproperty ("baseline", hg, "data", h_baseline);
+
+ addlistener (hg, "showbaseline", @show_baseline);
+ addlistener (hg, "basevalue", @move_baseline);
+
+ addproperty ("barwidth", hg, "data", width);
+ if (group)
+ addproperty ("barlayout", hg, "radio", "stacked|{grouped}", "grouped");
+ else
+ addproperty ("barlayout", hg, "radio", "{stacked}|grouped", "stacked");
+ endif
+ if (vertical)
+ addproperty ("horizontal", hg, "radio", "on|{off}", "off")
+ else
+ addproperty ("horizontal", hg, "radio", "{on}|off", "on")
+ endif
+
+ addlistener (hg, "barwidth", @update_group);
+ addlistener (hg, "barlayout", @update_group);
+ addlistener (hg, "horizontal", @update_group);
+
+ addproperty ("edgecolor", hg, "patchedgecolor", get (h, "edgecolor"));
+ addproperty ("linewidth", hg, "patchlinewidth", get (h, "linewidth"));
+ addproperty ("linestyle", hg, "patchlinestyle", get (h, "linestyle"));
+ addproperty ("facecolor", hg, "patchfacecolor", get (h, "facecolor"));
+
+ addlistener (hg, "edgecolor", @update_props);
+ addlistener (hg, "linewidth", @update_props);
+ addlistener (hg, "linestyle", @update_props);
+ addlistener (hg, "facecolor", @update_props);
+
+ if (isvector (x))
+ addproperty ("xdata", hg, "data", x);
+ else
+ addproperty ("xdata", hg, "data", x(:, i));
+ endif
+ addproperty ("ydata", hg, "data", y(:, i));
+
+ addlistener (hg, "xdata", @update_data);
+ addlistener (hg, "ydata", @update_data);
+
+ addproperty ("bargroup", hg, "data");
+ set (tmp, "bargroup", tmp);
+ endfor
+
+ update_xlim (ax, []);
+endfunction
+
+function update_xlim (h, d)
+ kids = get (h, "children");
+ xlim = get (h, "xlim");
+
+ for i = 1 : length (kids)
+ obj = get (kids (i));
+ if (strcmp (obj.type, "hggroup") && isfield (obj, "baseline"))
+ if (any (get (obj.baseline, "xdata") != xlim))
+ set (obj.baseline, "xdata", xlim);
+ endif
+ endif
+ endfor
+endfunction
+
+function update_baseline (h, d)
+ visible = get (h, "visible");
+ ydata = get (h, "ydata")(1);
+
+ kids = get (get (h, "parent"), "children");
+ for i = 1 : length (kids)
+ obj = get (kids (i));
+ if (strcmp (obj.type, "hggroup") && isfield (obj, "baseline")
+ && obj.baseline == h)
+ ## Only alter if changed to avoid recursion of the listener functions
+ if (! strcmp (get (kids(i), "showbaseline"), visible))
+ set (kids (i), "showbaseline", visible);
+ endif
+ if (! strcmp (get (kids(i), "basevalue"), visible))
+ set (kids (i), "basevalue", ydata);
+ endif
+ endif
+ endfor
+endfunction
+
+function show_baseline (h, d)
+ persistent recursion = false;
+
+ ## Don't allow recursion
+ if (! recursion)
+ unwind_protect
+ recursion = true;
+ hlist = get (h, "bargroup");
+ showbaseline = get (h, "showbaseline");
+ for hh = hlist(:)'
+ if (hh != h)
+ set (hh, "showbaseline", showbaseline);
+ endif
+ endfor
+ set (get (h, "baseline"), "visible", showbaseline);
+ unwind_protect_cleanup
+ recursion = false;
+ end_unwind_protect
+ endif
+endfunction
+
+function move_baseline (h, d)
+ b0 = get (h, "basevalue");
+ bl = get (h, "baseline");
+
+ if (get (bl, "ydata") != [b0, b0])
+ set (bl, "ydata", [b0, b0]);
+ endif
+
+ if (strcmp (get (h, "barlayout"), "grouped"))
+ update_data (h, d);
+ endif
+endfunction
+
+function update_props (h, d)
+ kids = get (h, "children");
+ set (kids, "edgecolor", get (h, "edgecolor"),
+ "linewidth", get (h, "linewidth"),
+ "linestyle", get (h, "linestyle"),
+ "facecolor", get (h, "facecolor"));
+endfunction
+
+function update_data (h, d)
+ persistent recursion = false;
+
+ ## Don't allow recursion
+ if (! recursion)
+ unwind_protect
+ recursion = true;
+ hlist = get (h, "bargroup");
+ x = get (h, "xdata");
+ if (!isvector (x))
+ x = x(:);
+ endif
+ y = [];
+ for hh = hlist(:)'
+ ytmp = get (hh, "ydata");
+ y = [y ytmp(:)];
+ endfor
+
+ [xb, yb] = bar (x, y, get (h, "barwidth"), get (h, "barlayout"),
+ "basevalue", get (h, "basevalue"));
+ ny = columns (y);
+ vert = strcmp (get (h, "horizontal"), "off");
+
+ for i = 1:ny
+ hp = get (hlist(i), "children");
+ if (vert)
+ set (hp, "xdata", xb(:,:,i), "ydata", yb(:,:,i));
+ else
+ set (hp, "xdata", yb(:,:,i), "ydata", xb(:,:,i));
+ endif
+ endfor
+ unwind_protect_cleanup
+ recursion = false;
+ end_unwind_protect
+ endif
+endfunction
+
+function update_group (h, d)
+ persistent recursion = false;
+
+ ## Don't allow recursion
+ if (! recursion)
+ unwind_protect
+ recursion = true;
+ hlist = get (h, "bargroup");
+ barwidth = get(h, "barwidth");
+ barlayout = get (h, "barlayout");
+ horizontal = get (h, "horizontal");
+
+ ## To prevent recursion, only change if modified
+ for hh = hlist(:)'
+ if (hh != h)
+ if (get (hh, "barwidth") != barwidth)
+ set (hh, "barwidth", barwidth);
+ endif
+ if (! strcmp (get (hh, "barlayout"), barlayout))
+ set (hh, "barlayout", barlayout);
+ endif
+ if (! strcmp (get (hh, "horizontal"), horizontal))
+ set (hh, "horizontal", horizontal);
+ endif
+ endif
+ endfor
+ update_data (h, d);
+ unwind_protect_cleanup
+ recursion = false;
+ end_unwind_protect
+ endif
+endfunction
diff --git a/scripts/plot/__quiver__.m b/scripts/plot/__quiver__.m
--- a/scripts/plot/__quiver__.m
+++ b/scripts/plot/__quiver__.m
@@ -18,13 +18,13 @@
## Undocumented internal function
-function hlist = __quiver__ (varargin)
+function hg = __quiver__ (varargin)
h = varargin{1};
is3d = varargin{2};
- s = 1;
- arrowsize = 0.33;
+ autoscale = 0.9;
+ arrowsize = 0.2;
firstnonnumeric = Inf;
for i = 3:nargin
@@ -46,7 +46,7 @@ function hlist = __quiver__ (varargin)
endif
if (nargin >= ioff && isnumeric (varargin{ioff})
&& isscalar (varargin{ioff}))
- s = varargin{ioff++};
+ autoscale = varargin{ioff++};
endif
else
x = varargin{ioff++};
@@ -69,7 +69,7 @@ function hlist = __quiver__ (varargin)
endif
if (nargin >= ioff && isnumeric (varargin{ioff})
&& isscalar (varargin{ioff}))
- s = varargin{ioff++};
+ autoscale = varargin{ioff++};
endif
endif
@@ -95,7 +95,7 @@ function hlist = __quiver__ (varargin)
endif
endwhile
- if (s)
+ if (autoscale)
## Scale the arrows to fit in the grid
dx = (max(x(:)) - min(x(:))) ./ size (x, 2);
dy = (max(y(:)) - min(y(:))) ./ size (y, 1);
@@ -108,59 +108,83 @@ function hlist = __quiver__ (varargin)
dz = 0;
endif
if (len > 0)
- s = s / sqrt (2) * sqrt (dx.^2 + dy.^2 + dz.^2) / len;
- u = s * u;
- v = s * v;
- if (is3d)
- w = s*w;
- endif
- endif
- endif
-
- x = x(:);
- y = y(:);
- xend = x + u(:);
- yend = y + v(:);
- if (is3d)
- z = z(:);
- zend = z + w(:);
+ s = 2 * autoscale / sqrt (2) * sqrt (dx.^2 + dy.^2 + dz.^2) / len;
+ uu = s * u;
+ vv = s * v;
+ if (is3d)
+ ww = s*w;
+ endif
+ endif
endif
hstate = get (h, "nextplot");
unwind_protect
+ hg = hggroup ();
+ hold on;
+
+ addproperty ("xdata", hg, "data", x);
+ addproperty ("ydata", hg, "data", y);
+
+ addproperty ("udata", hg, "data", u);
+ addproperty ("vdata", hg, "data", v);
+ if (is3d)
+ addproperty ("zdata", hg, "data", z);
+ addproperty ("wdata", hg, "data", w);
+ else
+ addproperty ("zdata", hg, "data", []);
+ addproperty ("wdata", hg, "data", []);
+ endif
+
+ addlistener (hg, "xdata", @update_data);
+ addlistener (hg, "ydata", @update_data);
+ addlistener (hg, "zdata", @update_data);
+ addlistener (hg, "udata", @update_data);
+ addlistener (hg, "vdata", @update_data);
+ addlistener (hg, "wdata", @update_data);
+
+ x = x(:);
+ y = y(:);
+ xend = x + uu(:);
+ yend = y + vv(:);
+ if (is3d)
+ z = z(:);
+ zend = z + ww(:);
+ endif
+
if (have_line_spec)
if (is3d)
h1 = plot3 ([x.'; xend.'; NaN(1, length (x))](:),
[y.'; yend.'; NaN(1, length (y))](:),
[z.'; zend.'; NaN(1, length (z))](:),
"linestyle", linespec.linestyle,
- "color", linespec.color);
+ "color", linespec.color, "parent", hg);
else
h1 = plot ([x.'; xend.'; NaN(1, length (x))](:),
[y.'; yend.'; NaN(1, length (y))](:),
"linestyle", linespec.linestyle,
- "color", linespec.color);
+ "color", linespec.color, "parent", hg);
endif
else
if (is3d)
h1 = plot3 ([x.'; xend.'; NaN(1, length (x))](:),
[y.'; yend.'; NaN(1, length (y))](:),
- [z.'; zend.'; NaN(1, length (z))](:));
+ [z.'; zend.'; NaN(1, length (z))](:),
+ "parent", hg);
else
h1 = plot ([x.'; xend.'; NaN(1, length (x))](:),
- [y.'; yend.'; NaN(1, length (y))](:));
- endif
- endif
- hold on;
-
- xtmp = x + u(:) .* (1 - arrowsize);
- ytmp = y + v(:) .* (1 - arrowsize);
+ [y.'; yend.'; NaN(1, length (y))](:),
+ "parent", hg);
+ endif
+ endif
+
+ xtmp = x + uu(:) .* (1 - arrowsize);
+ ytmp = y + vv(:) .* (1 - arrowsize);
xarrw1 = xtmp + (y - yend) * arrowsize / 3;
xarrw2 = xtmp - (y - yend) * arrowsize / 3;
yarrw1 = ytmp - (x - xend) * arrowsize / 3;
yarrw2 = ytmp + (x - xend) * arrowsize / 3;
if (is3d)
- zarrw1 = zarrw2 = zend - w(:) * arrowsize;
+ zarrw1 = zarrw2 = zend - ww(:) * arrowsize;
endif
if (have_line_spec)
@@ -170,11 +194,11 @@ function hlist = __quiver__ (varargin)
h2 = plot3 ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
[yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),
[zarrw1.'; zend.'; zarrw2.'; NaN(1, length (z))](:),
- "linestyle", "none");
+ "linestyle", "none", "parent", hg);
else
h2 = plot ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
[yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),
- "linestyle", "none");
+ "linestyle", "none", "parent", hg);
endif
else
if (is3d)
@@ -182,47 +206,190 @@ function hlist = __quiver__ (varargin)
[yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),
[zarrw1.'; zend.'; zarrw2.'; NaN(1, length (z))](:),
"linestyle", linespec.linestyle,
- "color", linespec.color);
+ "color", linespec.color, "parent", hg);
else
h2 = plot ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
[yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),
"linestyle", linespec.linestyle,
- "color", linespec.color);
+ "color", linespec.color, "parent", hg);
endif
endif
elseif (is3d)
h2 = plot3 ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
[yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),
- [zarrw1.'; zend.'; zarrw2.'; NaN(1, length (z))](:));
+ [zarrw1.'; zend.'; zarrw2.'; NaN(1, length (z))](:),
+ "parent", hg);
else
h2 = plot ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
- [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:));
+ [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),
+ "parent", hg);
endif
if (! have_line_spec
|| (isfield (linespec, "marker")
&& strncmp (linespec.marker, "none", 4)))
if (is3d)
- h3 = plot3 (x, y, z, "linestyle", "none", "marker", "none");
- else
- h3 = plot (x, y, "linestyle", "none", "marker", "none");
- endif
- else
- if (is3d)
- h3 = plot3 (x, y, z, "linestyle", "none", "marker", linespec.marker);
- else
-
- h3 = plot (x, y, "linestyle", "none", "marker", linespec.marker);
+ h3 = plot3 (x, y, z, "linestyle", "none", "marker", "none",
+ "parent", hg);
+ else
+ h3 = plot (x, y, "linestyle", "none", "marker", "none", "parent", hg);
+ endif
+ else
+ if (is3d)
+ h3 = plot3 (x, y, z, "linestyle", "none", "marker", linespec.marker,
+ "parent", hg);
+ else
+
+ h3 = plot (x, y, "linestyle", "none", "marker", linespec.marker,
+ "parent", hg);
endif
endif
if (have_filled)
## FIXME gnuplot doesn't respect the markerfacecolor field
set (h3, "markerfacecolor", get (h1, "color"));
endif
+
+ ## Set up the hggroup properties and listeners
+ if (autoscale)
+ addproperty ("autoscale", hg, "radio", "{on}|off", "on");
+ addproperty ("autoscalefactor", hg, "data", autoscale)
+ else
+ addproperty ("autoscale", hg, "radio", "{on}|off", "off");
+ addproperty ("autoscalefactor", hg, "data", 1.0)
+ endif
+ addlistener (hg, "autoscale", @update_data)
+ addlistener (hg, "autoscalefactor", @update_data)
+
+ addproperty ("maxheadsize", hg, "data", arrowsize)
+ addlistener (hg, "maxheadsize", @update_data);
+
+ addproperty ("showarrowhead", hg, "radio", "{on}|off", "on");
+ addlistener (hg, "showarrowhead", @update_props);
+
+ addproperty ("color", hg, "linecolor", get (h1, "color"));
+ addproperty ("linewidth", hg, "linelinewidth", get (h1, "linewidth"));
+ addproperty ("linestyle", hg, "linelinestyle", get (h1, "linestyle"));
+ addproperty ("marker", hg, "linemarker", get (h3, "marker"));
+ addproperty ("markerfacecolor", hg, "linemarkerfacecolor",
+ get (h3, "markerfacecolor"));
+ addproperty ("markersize", hg, "linemarkersize", get (h3, "markersize"));
+
+ addlistener (hg, "color", @update_props);
+ addlistener (hg, "linewidth", @update_props);
+ addlistener (hg, "linestyle", @update_props);
+ addlistener (hg, "marker", @update_props);
+ addlistener (hg, "markerfacecolor", @update_props);
+ addlistener (hg, "markersize", @update_props);
+
unwind_protect_cleanup
set (h, "nextplot", hstate);
end_unwind_protect
- hlist = [h1; h2; h3];
-
endfunction
+
+function update_data (h, d)
+ x = get (h, "xdata");
+ y = get (h, "ydata");
+ z = get (h, "zdata");
+
+ u = get (h, "udata");
+ v = get (h, "vdata");
+ w = get (h, "wdata");
+
+ s = get (h, "autoscalefactor");
+ arrowsize = get (h, "maxheadsize");
+
+ kids = get (h, "children");
+
+ if (isempty (z) || isempty (w))
+ is3d = false;
+ else
+ is3d = true;
+ endif
+
+ if (strcmp (get (h, "autoscale"), "on") && s != 0)
+ ## Scale the arrows to fit in the grid
+ dx = (max(x(:)) - min(x(:))) ./ size (x, 2);
+ dy = (max(y(:)) - min(y(:))) ./ size (y, 1);
+ if (is3d)
+ ## What should this be divided by? The below seems right
+ dz = (max(z(:)) - min(z(:))) ./ max (size (z));
+ len = max (sqrt (u(:).^2 + dy(:).^2) + dz(:).^2);
+ else
+ len = max (sqrt (u(:).^2 + dy(:).^2));
+ dz = 0;
+ endif
+ if (len > 0)
+ s = 2 * s / sqrt (2) * sqrt (dx.^2 + dy.^2 + dz.^2) / len;
+ u = s * u;
+ v = s * v;
+ if (is3d)
+ w = s*w;
+ endif
+ endif
+ endif
+
+ x = x(:);
+ y = y(:);
+ xend = x + u(:);
+ yend = y + v(:);
+ if (is3d)
+ z = z(:);
+ zend = z + w(:);
+ endif
+
+ set (kids (1), "xdata", [x.'; xend.'; NaN(1, length (x))](:));
+ set (kids (1), "ydata", [y.'; yend.'; NaN(1, length (y))](:));
+ if (is3d)
+ set (kids (1), "zdata", [z.'; zend.'; NaN(1, length (z))](:));
+ endif
+
+ xtmp = x + u(:) .* (1 - arrowsize);
+ ytmp = y + v(:) .* (1 - arrowsize);
+ xarrw1 = xtmp + (y - yend) * arrowsize / 3;
+ xarrw2 = xtmp - (y - yend) * arrowsize / 3;
+ yarrw1 = ytmp - (x - xend) * arrowsize / 3;
+ yarrw2 = ytmp + (x - xend) * arrowsize / 3;
+ if (is3d)
+ zarrw1 = zarrw2 = zend - w(:) * arrowsize;
+ endif
+
+ set (kids (2), "xdata", [x.'; xend.'; NaN(1, length (x))](:));
+ set (kids (2), "ydata", [y.'; yend.'; NaN(1, length (y))](:));
+ if (is3d)
+ set (kids (2), "zdata", [z.'; zend.'; NaN(1, length (z))](:));
+ endif
+
+ set (kids (2), "xdata", [xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:));
+ set (kids (2), "ydata", [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:));
+ if (is3d)
+ set (kids (2), "zdata", [zarrw1.'; zend.'; zarrw2.'; NaN(1, length
(z))](:));
+ endif
+
+ set (kids (3), "xdata", x);
+ set (kids (3), "ydata", y);
+ if (is3d)
+ set (kids (3), "zdata", z);
+ endif
+
+endfunction
+
+function update_props (h, d)
+ kids = get (h, "children");
+
+ set (kids(1), "color", get (h, "color"),
+ "linewidth", get (h, "linewidth"),
+ "linestyle", get (h, "linestyle"));
+ set (kids(2), "color", get (h, "color"),
+ "linewidth", get (h, "linewidth"),
+ "linestyle", get (h, "linestyle"));
+ if (strcmp (get (h, "showarrowhead"), "on"))
+ set (kids (2), "visible", "on");
+ else
+ set (kids (2), "visible", "off");
+ endif
+ set (kids(3), "color", get (h, "color"),
+ "marker", get (h, "marker"),
+ "markerfacecolor", get (h, "markerfacecolor"),
+ "markersize", get (h, "markersize"));
+endfunction
diff --git a/scripts/plot/__stem__.m b/scripts/plot/__stem__.m
--- a/scripts/plot/__stem__.m
+++ b/scripts/plot/__stem__.m
@@ -97,6 +97,7 @@ function h = __stem__ (have_z, varargin)
x_axis_range = get (ax, "xlim");
h_baseline = line (x_axis_range, [0, 0], "color", [0, 0, 0]);
set (h_baseline, "handlevisibility", "off");
+ set (h_baseline, "xliminclude", "off");
addlistener (ax, "xlim", @update_xlim);
addlistener (h_baseline, "ydata", @update_baseline);
addlistener (h_baseline, "visible", @update_baseline);
@@ -428,7 +429,7 @@ function update_xlim (h, d)
for i = 1 : length (kids)
obj = get (kids (i));
if (strcmp (obj.type, "hggroup") && isfield (obj, "baseline"))
- if (get (obj.baseline, "xdata") != xlim)
+ if (any (get (obj.baseline, "xdata") != xlim))
set (obj.baseline, "xdata", xlim);
endif
endif
diff --git a/scripts/plot/area.m b/scripts/plot/area.m
--- a/scripts/plot/area.m
+++ b/scripts/plot/area.m
@@ -34,7 +34,7 @@
##
## Additional arguments to the @code{area} function are passed to the
## @code{patch}. The optional return value @var{h} provides a handle to
-## the list of patch objects.
+## area series object representing the patches of the areas.
## @seealso{plot, patch}
## @end deftypefn
diff --git a/scripts/plot/bar.m b/scripts/plot/bar.m
--- a/scripts/plot/bar.m
+++ b/scripts/plot/bar.m
@@ -37,12 +37,27 @@
## argument, which can take the values @code{"grouped"} (the default),
## or @code{"stacked"}.
##
-## The optional return value @var{h} provides a handle to the patch object.
-## Whereas the option input handle @var{h} allows an axis handle to be passed.
-## Properties of the patch graphics object can be changed using
+## The optional return value @var{h} provides a handle to the "bar series"
+## object with one handle per column of the variable @var{y}. This
+## series allows common elements of the group of bar series objects to
+## be changed in a single bar series and the same properties are changed
+## in the other "bar series". For example
+##
+## @example
+## @group
+## h = bar (rand (5, 10));
+## set (h(1), "basevalue", 0.5);
+## @end group
+## @end example
+##
+## @noindent
+## changes the position on the base of all of the bar series.
+##
+## The optional input handle @var{h} allows an axis handle to be passed.
+## Properties of the patch graphics object can be changed using
## @var{prop}, @var{val} pairs.
##
-## @seealso{barh, plot}
+## @seealso{barh, plot}
## @end deftypefn
## Author: jwe
diff --git a/scripts/plot/barh.m b/scripts/plot/barh.m
--- a/scripts/plot/barh.m
+++ b/scripts/plot/barh.m
@@ -36,9 +36,11 @@
## argument, which can take the values @code{"grouped"} (the default),
## or @code{"stacked"}.
##
-## The optional return value @var{h} provides a handle to the patch object.
-## Whereas the option input handle @var{h} allows an axis handle to be passed.
-## Properties of the patch graphics object can be changed using
+## The optional return value @var{h} provides a handle to the bar series
+## object. See @code{bar} for a description of the use of the bar series.
+##
+## The optional input handle @var{h} allows an axis handle to be passed.
+## Properties of the patch graphics object can be changed using
## @var{prop}, @var{val} pairs.
##
## @seealso{bar, plot}
diff --git a/scripts/plot/quiver.m b/scripts/plot/quiver.m
--- a/scripts/plot/quiver.m
+++ b/scripts/plot/quiver.m
@@ -43,13 +43,15 @@
## printed rather than arrows. If the argument 'filled' is given then the
## markers as filled.
##
-## The optional return value @var{h} provides a list of handles to the
-## the parts of the vector field (body, arrow and marker).
+## The optional return value @var{h} provides a quiver group that
+## regroups the components of the quiver plot (body, arrow and marker),
+## and allows them to be changed together
##
## @example
## @group
## [x, y] = meshgrid (1:2:20);
-## quiver (x, y, sin (2*pi*x/10), sin (2*pi*y/10));
+## h = quiver (x, y, sin (2*pi*x/10), sin (2*pi*y/10));
+## set (h, "maxheadsize", 0.33);
## @end group
## @end example
##
@@ -81,7 +83,8 @@ endfunction
%!demo
%! [x,y] = meshgrid(1:2:20);
-%! quiver(x,y,sin(2*pi*x/10),sin(2*pi*y/10))
+%! h = quiver(x,y,sin(2*pi*x/10),sin(2*pi*y/10))
+%! set (h, "maxheadsize", 0.33);
%!demo
%! axis("equal");
diff --git a/scripts/plot/quiver3.m b/scripts/plot/quiver3.m
--- a/scripts/plot/quiver3.m
+++ b/scripts/plot/quiver3.m
@@ -43,8 +43,9 @@
## printed rather than arrows. If the argument 'filled' is given then the
## markers as filled.
##
-## The optional return value @var{h} provides a list of handles to the
-## the parts of the vector field (body, arrow and marker).
+## The optional return value @var{h} provides a quiver group that
+## regroups the components of the quiver plot (body, arrow and marker),
+## and allows them to be changed together
##
## @example
## @group
@@ -52,7 +53,8 @@
## surf (x, y, z);
## hold on;
## [u, v, w] = surfnorm (x, y, z / 10);
-## quiver3 (x, y, z, u, v, w);
+## h = quiver3 (x, y, z, u, v, w);
+## set (h, "maxheadsize", 0.33);
## @end group
## @end example
##
@@ -96,4 +98,5 @@ endfunction
%! surf (x, y, z);
%! hold on;
%! [u, v, w] = surfnorm (x, y, z / 10);
-%! quiver3 (x, y, z, u, v, w);
+%! h = quiver3 (x, y, z, u, v, w);
+%! set (h, "maxheadsize", 0.33);
diff --git a/scripts/plot/stairs.m b/scripts/plot/stairs.m
--- a/scripts/plot/stairs.m
+++ b/scripts/plot/stairs.m
@@ -128,17 +128,59 @@ function [h, xs, ys] = __stairs__ (doplo
xs(1,:) = x(1,:);
ys(1,:) = y(1,:);
- x = x(2:nr,:);
+ xtmp = x(2:nr,:);
ridx = 2:2:len-1;
- xs(ridx,:) = x;
+ xs(ridx,:) = xtmp;
ys(ridx,:) = y(1:nr-1,:);
ridx = 3:2:len;
- xs(ridx,:) = x;
+ xs(ridx,:) = xtmp;
ys(ridx,:) = y(2:nr,:);
if (doplot)
- h = plot (xs, ys, varargin{idx+1:end});
+ h = [];
+ unwind_protect
+ hold_state = get (gca (), "nextplot");
+ for i = 1 : size(y, 2)
+ hg = hggroup ();
+ h = [h; hg];
+
+ if (i == 1)
+ set (gca (), "nextplot", "add");
+ endif
+
+ addproperty ("xdata", hg, "data", x(:,i).');
+ addproperty ("ydata", hg, "data", y(:,i).');
+
+ addlistener (hg, "xdata", @update_data);
+ addlistener (hg, "ydata", @update_data);
+
+ tmp = line (xs(:,i).', ys(:,i).', "color", __next_line_color__ (),
+ "parent", hg, varargin{idx+1:end});
+
+ addproperty ("color", hg, "linecolor", get (tmp, "color"));
+ addproperty ("linewidth", hg, "linelinewidth", get (tmp, "linewidth"));
+ addproperty ("linestyle", hg, "linelinestyle", get (tmp, "linestyle"));
+
+ addproperty ("marker", hg, "linemarker", get (tmp, "marker"));
+ addproperty ("markerfacecolor", hg, "linemarkerfacecolor",
+ get (tmp, "markerfacecolor"));
+ addproperty ("markeredgecolor", hg, "linemarkeredgecolor",
+ get (tmp, "markeredgecolor"));
+ addproperty ("markersize", hg, "linemarkersize",
+ get (tmp, "markersize"));
+
+ addlistener (hg, "color", @update_props);
+ addlistener (hg, "linewidth", @update_props);
+ addlistener (hg, "linestyle", @update_props);
+ addlistener (hg, "marker", @update_props);
+ addlistener (hg, "markerfacecolor", @update_props);
+ addlistener (hg, "markeredgecolor", @update_props);
+ addlistener (hg, "markersize", @update_props);
+ endfor
+ unwind_protect_cleanup
+ set (gca (), "nextplot", hold_state);
+ end_unwind_protect
else
h = 0;
endif
@@ -148,10 +190,43 @@ endfunction
%!demo
%! x = 1:10;
%! y = rand (1, 10);
-## stairs (x, y);
+%! stairs (x, y);
%!demo
%! x = 1:10;
%! y = rand (1, 10);
%! [xs, ys] = stairs (x, y);
%! plot (xs, ys);
+
+function update_props (h, d)
+ set (get (h, "children"), "color", get (h, "color"),
+ "linewidth", get (h, "linewidth"),
+ "linestyle", get (h, "linestyle"),
+ "marker", get (h, "marker"),
+ "markerfacecolor", get (h, "markerfacecolor"),
+ "markeredgecolor", get (h, "markeredgecolor"),
+ "markersize", get (h, "markersize"));
+endfunction
+
+function update_data (h, d)
+ x = get (h, "xdata");
+ y = get (h, "ydata");
+
+ nr = length (x);
+ len = 2 * nr - 1;
+ xs = ys = zeros (1, len);
+
+ xs(1) = x(1);
+ ys(1) = y(1);
+
+ xtmp = x(2:nr);
+ ridx = 2:2:len-1;
+ xs(ridx) = xtmp;
+ ys(ridx) = y(1:nr-1);
+
+ ridx = 3:2:len;
+ xs(ridx) = xtmp;
+ ys(ridx) = y(2:nr);
+
+ set (get (h, "children"), "xdata", xs, "ydata", ys);
+endfunction
- [Changeset]: Add area, bar, quiver and stair series objects,
David Bateman <=