Mercurial > octave
view scripts/plot/draw/quiver.m @ 32044:31f7f5359ba2
quiver: Add scale factor and input validation BISTs (bug #39552)
* scripts/plot/draw/quiver.m: Add BISTs for too few inputs. Add BISTs to
verify single and multiple arrow quiver plots honor scaling factor.
author | Nicholas R. Jankowski <jankowski.nicholas@gmail.com> |
---|---|
date | Thu, 20 Apr 2023 16:49:31 -0400 |
parents | 597f3ee61a48 |
children | ada96a467a28 |
line wrap: on
line source
######################################################################## ## ## Copyright (C) 2007-2023 The Octave Project Developers ## ## See the file COPYRIGHT.md in the top-level directory of this ## distribution or <https://octave.org/copyright/>. ## ## This file is part of Octave. ## ## Octave is free software: you can redistribute it and/or modify it ## under the terms of the GNU General Public License as published by ## the Free Software Foundation, either version 3 of the License, or ## (at your option) any later version. ## ## Octave is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Octave; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## ######################################################################## ## -*- texinfo -*- ## @deftypefn {} {} quiver (@var{u}, @var{v}) ## @deftypefnx {} {} quiver (@var{x}, @var{y}, @var{u}, @var{v}) ## @deftypefnx {} {} quiver (@dots{}, @var{s}) ## @deftypefnx {} {} quiver (@dots{}, @var{style}) ## @deftypefnx {} {} quiver (@dots{}, "filled") ## @deftypefnx {} {} quiver (@var{hax}, @dots{}) ## @deftypefnx {} {@var{h} =} quiver (@dots{}) ## ## Plot a 2-D vector field with arrows. ## ## Plot the (@var{u}, @var{v}) components of a vector field at the grid points ## defined by (@var{x}, @var{y}). If the grid is uniform then @var{x} and ## @var{y} can be specified as vectors and @code{meshgrid} is used to create ## the 2-D grid. ## ## If @var{x} and @var{y} are not given they are assumed to be ## @code{(1:@var{m}, 1:@var{n})} where ## @code{[@var{m}, @var{n}] = size (@var{u})}. ## ## The optional input @var{s} is a scalar defining a scaling factor to use for ## the arrows of the field relative to the mesh spacing. A value of 1.0 will ## result in the longest vector exactly filling one grid square. A value of 0 ## disables all scaling. The default value is 0.9. ## ## The style to use for the plot can be defined with a line style @var{style} ## of the same format as the @code{plot} command. If a marker is specified ## then the markers are drawn at the origin of the vectors (which are the grid ## points defined by @var{x} and @var{y}). When a marker is specified, the ## arrowhead is not drawn. If the argument @qcode{"filled"} is given then the ## markers are filled. ## ## If the first argument @var{hax} is an axes handle, then plot into this axes, ## rather than the current axes returned by @code{gca}. ## ## The optional return value @var{h} is a graphics handle to a quiver object. ## A quiver object regroups the components of the quiver plot (body, arrow, ## and marker), and allows them to be changed together. ## ## Example: ## ## @example ## @group ## [x, y] = meshgrid (1:2:20); ## h = quiver (x, y, sin (2*pi*x/10), sin (2*pi*y/10)); ## set (h, "maxheadsize", 0.33); ## @end group ## @end example ## ## @seealso{quiver3, compass, feather, plot} ## @end deftypefn function h = quiver (varargin) [hax, varargin, nargin] = __plt_get_axis_arg__ ("quiver", varargin{:}); if (nargin < 2) print_usage (); endif oldfig = []; if (! isempty (hax)) oldfig = get (0, "currentfigure"); endif unwind_protect hax = newplot (hax); htmp = __quiver__ (hax, false, varargin{:}); ## FIXME: This should be moved into __quiver__ when problem with ## re-initialization of title object is fixed. if (! ishold ()) set (hax, "box", "on"); endif unwind_protect_cleanup if (! isempty (oldfig)) set (0, "currentfigure", oldfig); endif end_unwind_protect if (nargout > 0) h = htmp; endif endfunction %!demo %! clf; %! [x,y] = meshgrid (1:2:20); %! h = quiver (x,y, sin (2*pi*x/10), sin (2*pi*y/10)); %! title ("quiver() plot w/arrowheads (default)"); %!demo %! clf; %! [x,y] = meshgrid (1:2:20); %! h = quiver (x,y, sin (2*pi*x/10), sin (2*pi*y/10), "o"); %! title ("quiver() plot w/origin markers"); %!demo %! clf; %! [x,y] = meshgrid (1:2:20); %! h = quiver (x,y, sin (2*pi*x/10), sin (2*pi*y/10)); %! set (h, "marker", "o"); %! title ("quiver() plot w/origin markers and arrowheads"); %!demo %! clf; %! x = linspace (0, 3, 80); %! y = sin (2*pi*x); %! theta = 2*pi*x + pi/2; %! quiver (x, y, sin (theta)/10, cos (theta)/10, 0.4); %! axis equal tight; %! hold on; plot (x,y,"r"); hold off; %! title ("quiver() with scaled arrows"); %!test <*39552> # Check arrow length, scale factor adjustment, one arrow. %! hf = figure ("visible", "off"); %! hax = gca (); %! unwind_protect %! [x,y] = meshgrid (1:2); %! u = [0 1; 2 3]; %! v = [1 2; 3 4]; %! numpts = numel (x); %! sf = 0.5; %! %! ## Check single arrow. %! h = quiver (hax, x(4), y(4), u(4), v(4), 1); %! childxdata = get (get (h, "children"), "xdata"); %! stemchild = find (cellfun (@numel, childxdata) == 3); %! xendpoint = childxdata{stemchild}(2); %! assert (xendpoint, x(4) + u(4), eps); %! %! h = quiver (hax, x(4), y(4), u(4), v(4), sf); %! childxdata = get (get (h, "children"), "xdata"); %! stemchild = find (cellfun (@numel, childxdata) == 3); %! xendpoint = childxdata{stemchild}(2); %! assert (xendpoint, x(4) + sf*u(4), eps); %! %! unwind_protect_cleanup %! close (hf); %! end_unwind_protect %!test <*39552> # Check arrow length, scale factor adjustment, multiple arrows. %! hf = figure ("visible", "off"); %! hax = gca (); %! unwind_protect %! [x,y] = meshgrid (1:2); %! u = [0 1; 2 3]; %! v = [1 2; 3 4]; %! numpts = numel (x); %! sf = 0.5; %! %! ## Check multiple arrows. %! h = quiver (hax, x, y, u, v, 1); %! childxdata = get (get (h, "children"), "xdata"); %! stemchild = find (cellfun (@numel, childxdata) == 3*numpts); %! xendpoint1 = childxdata{stemchild}(5); %! xendpoint2 = childxdata{stemchild}(11); %! assert (xendpoint1, x(2) + (sqrt(2)/10)*u(2), eps); %! assert (xendpoint2, x(4) + (sqrt(2)/10)*u(4), eps); %! %! h = quiver (hax, x, y, u, v, sf); %! childxdata = get (get (h, "children"), "xdata"); %! stemchild = find (cellfun (@numel, childxdata) == 3*numpts); %! xendpoint1 = childxdata{stemchild}(5); %! xendpoint2 = childxdata{stemchild}(11); %! assert (xendpoint1, x(2) + sf*(sqrt(2)/10)*u(2), eps); %! assert (xendpoint2, x(4) + sf*(sqrt(2)/10)*u(4), eps); %! %! unwind_protect_cleanup %! close (hf); %! end_unwind_protect ## Test input validation %!error <Invalid call> quiver() %!error <Invalid call> quiver(1)