[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Patch to add quiver3 and surfnorm
From: |
David Bateman |
Subject: |
Re: Patch to add quiver3 and surfnorm |
Date: |
Mon, 26 Nov 2007 15:51:15 +0100 |
User-agent: |
Thunderbird 1.5.0.7 (X11/20060921) |
David Bateman wrote:
> Here is a patch I worked on over the weekend that adds the quiver3
> function. Matlab has a strange arrow head in the xy plane for the arrows
> of quiver3 and so if you are looking at the plot in the xz or yz plane
> then the arrowhead tend to disappear. This is the same as in matlab
> itself and so I don't see that we can do much..
>
> As for the surfnorm function, I noticed this existed as the test
> function for quiver3 on the matlab website and so implemented it to test
> quiver3.. However, for me it makes more sense to have to normal vectors
> at the center of each quadrilateral patch defined by the meshgrid than
> at the vertices. The reason is that the definition of the normal vector
> is very clear, and its something like this normal vector that I've
> always used in the past for integral equation formulations of
> electromagnetic fields. This is NOT what surnorm does it appears. What
> surfnorm does is estimate the normal vectors at the vertices from the
> normal vectors at the centers of the quadrilaterals defined by the
> meshgrid.
>
> There is an issue with this estimation in that the vertices at the edge
> of the meshgrid must be extrapolated. This means that closed surfaces,
> like those returned by the "sphere" function, will have funny
> extrapolation effects. Matlab seems not to suffer from this problem too
> much and so I suspect that use a cubic extrapolation, whereas at the
> moment I've limited myself to a linear extrapolation. This is not a real
> issue to me however. Does anyone else care?
>
> D.
>
Sorry, missed the __quiver__ function and a small bug.. Fixed in the
attached.
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
*** ./scripts/plot/Makefile.in.orig25 2007-11-26 12:08:44.624230974 +0100
--- ./scripts/plot/Makefile.in 2007-11-26 15:49:22.076035982 +0100
***************
*** 63,68 ****
--- 63,69 ----
__plt_get_axis_arg__.m \
__pltopt1__.m \
__pltopt__.m \
+ __quiver__.m \
__scatter__.m \
ancestor.m \
area.m \
***************
*** 113,118 ****
--- 114,120 ----
polar.m \
print.m \
quiver.m \
+ quiver3.m \
replot.m \
ribbon.m \
scatter.m \
***************
*** 132,137 ****
--- 134,140 ----
surf.m \
surface.m \
surfc.m \
+ surfnorm.m \
text.m \
title.m \
view.m \
*** ./scripts/plot/quiver.m.orig25 2007-11-26 15:48:53.625477451 +0100
--- ./scripts/plot/quiver.m 2007-11-26 15:48:19.732194368 +0100
***************
*** 69,81 ****
unwind_protect
axes (h);
newplot ();
! tmp = __quiver__ (h, varargin{2:end});
unwind_protect_cleanup
axes (oldh);
end_unwind_protect
else
newplot ();
! tmp = __quiver__ (gca (), varargin{:});
endif
if (nargout > 0)
--- 69,81 ----
unwind_protect
axes (h);
newplot ();
! tmp = __quiver__ (h, 0, varargin{2:end});
unwind_protect_cleanup
axes (oldh);
end_unwind_protect
else
newplot ();
! tmp = __quiver__ (gca (), 0, varargin{:});
endif
if (nargout > 0)
***************
*** 84,221 ****
endfunction
- function hlist = __quiver__ (varargin)
- h = varargin {1};
-
- s = 1;
- arrowsize = 0.33;
-
- firstnonnumeric = Inf;
- for i = 2:nargin
- if (! isnumeric (varargin {i}))
- firstnonnumeric = i;
- break;
- endif
- endfor
-
- if (nargin < 5 || firstnonnumeric < 5)
- u = varargin{2};
- v = varargin{3};
- if (nargin == 4 && isnumeric (varargin{4}) && isscalar (varargin{4}))
- s = varargin{4};
- iarg = 5;
- else
- iarg = 4;
- endif
- [x, y] = meshgrid (1:size(u,1), 1:size(u,2));
- else
- x = varargin{2};
- y = varargin{3};
- u = varargin{4};
- v = varargin{5};
- if (isvector(x) && isvector(y) && (!isvector (u) || !isvector (v)))
- [x, y] = meshgrid (x, y);
- endif
- if (nargin > 5 && isnumeric (varargin{6}) && isscalar (varargin{6}))
- s = varargin{6};
- iarg = 7;
- else
- iarg = 6;
- endif
- endif
-
- have_filled = false;
- have_line_spec = false;
- while (iarg <= nargin)
- arg = varargin {iarg++};
- if (ischar (arg) && strncmp (tolower (arg), "filled", 6))
- have_filled = true;
- elseif ((isstr (arg) || iscell (arg))
- && ! have_line_spec)
- [linespec, valid] = __pltopt__ ("quiver", arg, false);
- if (valid)
- have_line_spec = true;
- if (strncmp (linespec.linestyle, "none", 4))
- linespec.linestyle = "-";
- endif
- else
- error ("quiver: invalid linespec");
- endif
- else
- error ("quiver: unrecognized argument");
- endif
- endwhile
-
- if (s)
- ## Scale the arrows to fit in the grid
- dx = (max(x(:)) - min(x(:))) ./ size (x, 2);
- dy = (max(y(:)) - min(y(:))) ./ size (y, 1);
- len = max (sqrt (u(:).^2 + dy(:).^2));
- if (len > 0)
- s = s / sqrt (2) * sqrt (dx.^2 + dy.^2) / len;
- u = s * u;
- v = s * v;
- endif
- endif
-
- x = x(:);
- y = y(:);
- xend = x + u(:);
- yend = y + v(:);
-
- hstate = get (h, "nextplot");
- unwind_protect
- if (have_line_spec)
- h1 = plot ([x.'; xend.'; NaN(1, length (x))](:),
- [y.'; yend.'; NaN(1, length (y))](:),
- "linestyle", linespec.linestyle);
- else
- h1 = plot ([x.'; xend.'; NaN(1, length (x))](:),
- [y.'; yend.'; NaN(1, length (y))](:));
- endif
- hold on;
-
- 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 (have_line_spec)
- if (isfield (linespec, "marker") &&
- ! strncmp (linespec.marker, "none", 4))
- h2 = plot ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
- [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),
- "linestyle", "none");
- else
- h2 = plot ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
- [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),
- "linestyle", linespec.linestyle);
- endif
- else
- h2 = plot ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
- [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:));
- endif
-
- if (! have_line_spec || (isfield (linespec, "marker") &&
- strncmp (linespec.marker, "none", 4)))
- h3 = plot (x, y, "linestyle", "none", "marker", "none");
- else
- h3 = plot (x, y, "linestyle", "none", "marker", linespec.marker);
- endif
- if (have_filled)
- ## FIXME gnuplot doesn't respect the markerfacecolor field
- set(h3, "markerfacecolor", get (h1, "color"));
- endif
- unwind_protect_cleanup
- set (h, "nextplot", hstate);
- end_unwind_protect
-
- hlist = [h1; h2; h3];
-
- endfunction
-
%!demo
%! [x,y] = meshgrid(1:2:20);
%! quiver(x,y,sin(2*pi*x/10),sin(2*pi*y/10))
--- 84,89 ----
*** ./scripts/plot/quiver3.m.orig25 2007-11-26 12:08:31.071923140 +0100
--- ./scripts/plot/quiver3.m 2007-11-26 15:48:10.786647457 +0100
***************
*** 0 ****
--- 1,97 ----
+ ## Copyright (C) 2007 David Bateman
+ ##
+ ## 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
+ ## <http://www.gnu.org/licenses/>.
+
+ ## -*- texinfo -*-
+ ## @deftypefn {Function File} {} quiver3 (@var{u}, @var{v}, @var{w})
+ ## @deftypefnx {Function File} {} quiver3 (@var{x}, @var{y}, @var{z},
@var{u}, @var{v}, @var{w})
+ ## @deftypefnx {Function File} {} quiver3 (@dots{}, @var{s})
+ ## @deftypefnx {Function File} {} quiver3 (@dots{}, @var{style})
+ ## @deftypefnx {Function File} {} quiver3 (@dots{}, 'filled')
+ ## @deftypefnx {Function File} {} quiver3 (@var{h}, @dots{})
+ ## @deftypefnx {Function File} address@hidden =} quiver3 (@dots{})
+ ##
+ ## Plot the @code{(@var{u}, @var{v}, @var{w})} components of a vector field
in
+ ## an @code{(@var{x}, @var{y}), @var{z}} meshgrid. If the grid is uniform,
you
+ ## can specify @var{x}, @var{y} @var{z} as vectors.
+ ##
+ ## If @var{x}, @var{y} and @var{z} are undefined they are assumed to be
+ ## @code{(1:@var{m}, 1:@var{n}, 1:@var{p})} where @address@hidden, @var{n}] =
+ ## size(@var{u})} and @address@hidden = max (size (@var{w}))}.
+ ##
+ ## The variable @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 0
+ ## disables all scaling. The default value is 1.
+ ##
+ ## The style to use for the plot can be defined with a line style @var{style}
+ ## in a similar manner to the line styles used with the @code{plot} command.
+ ## If a marker is specified then markers at the grid points of the vectors are
+ ## 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).
+ ##
+ ## @example
+ ## @group
+ ## [x, y, z] = peaks (25);
+ ## surf (x, y, z);
+ ## hold on;
+ ## [u, v, w] = surfnorm (x, y, z / 10);
+ ## quiver3 (x, y, z, u, v, w);
+ ## @end group
+ ## @end example
+ ##
+ ## @seealso{plot}
+ ## @end deftypefn
+
+ function retval = quiver3 (varargin)
+
+ if (nargin < 2)
+ print_usage ();
+ elseif (isscalar (varargin{1}) && ishandle (varargin{1}))
+ h = varargin {1};
+ if (! strcmp (get (h, "type"), "axes"))
+ error ("quiver: expecting first argument to be an axes object");
+ endif
+ oldh = gca ();
+ unwind_protect
+ axes (h);
+ newplot ();
+ tmp = __quiver__ (h, 1, varargin{2:end});
+ unwind_protect_cleanup
+ axes (oldh);
+ end_unwind_protect
+ else
+ newplot ();
+ tmp = __quiver__ (gca (), 1, varargin{:});
+ endif
+
+ if (nargout > 0)
+ retval = tmp;
+ endif
+
+ endfunction
+
+ %!demo
+ %! [x,y]=meshgrid (-1:0.1:1);
+ %! z=sin(2*pi*sqrt(x.^2+y.^2));
+ %! theta=2*pi*sqrt(x.^2+y.^2)+pi/2;
+ %! quiver3(x,y,z,sin(theta),cos(theta),ones(size(z)));
+ %! hold on;
+ %! mesh(x,y,z);
+ %! hold off;
*** ./scripts/plot/surfnorm.m.orig25 2007-11-26 12:09:23.765231036 +0100
--- ./scripts/plot/surfnorm.m 2007-11-26 12:19:44.998634645 +0100
***************
*** 0 ****
--- 1,155 ----
+ ## Copyright (C) 2007 David Bateman
+ ##
+ ## 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
+ ## <http://www.gnu.org/licenses/>.
+
+ ## -*- texinfo -*-
+ ## @deftypefn {Function File} {} surfnorm (@var{x}, @var{y}, @var{z})
+ ## @deftypefnx {Function File} {} surfnorm (@var{z})
+ ## @deftypefnx {Function File} address@hidden, @var{ny}, @var{nz}] =}
surfnorm (@dots{})
+ ## @deftypefnx {Function File} {} surfnorm (@var{h}, @dots{})
+ ## Find the vectors normal to a meshgridded surface. The meshed gridded
+ ## surface is defined by @var{x}, @var{y}, and @var{z}. If @var{x} and
+ ## @var{y} are not defined, then it is assumed that they are given by
+ ##
+ ## @example
+ ## address@hidden, @var{y}] = meshgrid (1:size(@var{z}, 1),
+ ## 1:size(@var{z}, 2));
+ ## @end example
+ ##
+ ## If no return arguments are requested, a surface plot with the normal
+ ## vectors to the surface is plotted. Otherwise the componets of the normal
+ ## vectors at the mesh gridded points are returned in @var{nx}, @var{ny},
+ ## and @var{nz}.
+ ##
+ ## The normal vectors are calculated by taking the cross product of the
+ ## diagonals of eash of teh quadrilaterals in the meshgrid to find the
+ ## normal vectors of the centers of these quadrilaterals. The four nearest
+ ## normal vectors to the meshgrid points are then averaged to obtain the
+ ## normal to the surface at the meshgridded points.
+ ##
+ ## An example of the use of @code{surfnorm} is
+ ##
+ ## @example
+ ## surfnorm (peaks (25));
+ ## @end example
+ ## @seealso{surf, quiver3}
+ ## @end deftypefn
+
+ function varargout = surfnorm (varargin)
+
+ if (nargout > 0)
+ varargout = cell (nargout, 1);
+ else
+ varargout = cell (0, 0);
+ endif
+ if (isscalar (varargin{1}) && ishandle (varargin{1}))
+ h = varargin {1};
+ if (! strcmp (get (h, "type"), "axes"))
+ error ("surfnorm: expecting first argument to be an axes object");
+ endif
+ if (nargin != 2 && nargin != 4)
+ print_usage ();
+ endif
+ oldh = gca ();
+ unwind_protect
+ axes (h);
+ [varargout{:}] = __surfnorm__ (h, varargin{2:end});
+ unwind_protect_cleanup
+ axes (oldh);
+ end_unwind_protect
+ else
+ if (nargin != 1 && nargin != 3)
+ print_usage ();
+ endif
+ [varargout{:}] = __surfnorm__ (gca (), varargin{:});
+ endif
+
+ endfunction
+
+ function [Nx, Ny, Nz] = __surfnorm__ (h, varargin)
+
+ if (nargin == 2)
+ z = varargin{1};
+ [x, y] = meshgrid (1:size(z,1), 1:size(z,2));
+ ioff = 2;
+ else
+ x = varargin{1};
+ y = varargin{2};
+ z = varargin{3};
+ ioff = 4;
+ endif
+
+ if (nargout == 0)
+ newplot();
+ surf (x, y, z, varargin{ioff:end});
+ hold on;
+ endif
+
+ ## Make life easier, and avoid having to do the extrapolation later, do
+ ## a simpler linear extrapolation here. This is approximative, and works
+ ## badly for closed surfaces like spheres.
+ xx = [2 .* x(:,1) - x(:,2), x, 2 .* x(:,end) - x(:,end-1)];
+ xx = [2 .* xx(1,:) - xx(2,:); xx; 2 .* xx(end,:) - xx(end-1,:)];
+ yy = [2 .* y(:,1) - y(:,2), y, 2 .* y(:,end) - y(:,end-1)];
+ yy = [2 .* yy(1,:) - yy(2,:); yy; 2 .* yy(end,:) - yy(end-1,:)];
+ zz = [2 .* z(:,1) - z(:,2), z, 2 .* z(:,end) - z(:,end-1)];
+ zz = [2 .* zz(1,:) - zz(2,:); zz; 2 .* zz(end,:) - zz(end-1,:)];
+
+ u.x = xx(1:end-1,1:end-1) - xx(2:end,2:end);
+ u.y = yy(1:end-1,1:end-1) - yy(2:end,2:end);
+ u.z = zz(1:end-1,1:end-1) - zz(2:end,2:end);
+ v.x = xx(1:end-1,2:end) - xx(2:end,1:end-1);
+ v.y = yy(1:end-1,2:end) - yy(2:end,1:end-1);
+ v.z = zz(1:end-1,2:end) - zz(2:end,1:end-1);
+
+ c = cross ([u.x(:), u.y(:), u.z(:)], [v.x(:), v.y(:), v.z(:)]);
+ w.x = reshape (c(:,1), size(u.x));
+ w.y = reshape (c(:,2), size(u.y));
+ w.z = reshape (c(:,3), size(u.z));
+
+ ## Create normal vectors as mesh vectices from normals at mesh centers
+ nx = (w.x(1:end-1,1:end-1) + w.x(1:end-1,2:end) +
+ w.x(2:end,1:end-1) + w.x(2:end,2:end)) ./ 4;
+ ny = (w.y(1:end-1,1:end-1) + w.y(1:end-1,2:end) +
+ w.y(2:end,1:end-1) + w.y(2:end,2:end)) ./ 4;
+ nz = (w.z(1:end-1,1:end-1) + w.z(1:end-1,2:end) +
+ w.z(2:end,1:end-1) + w.z(2:end,2:end)) ./ 4;
+
+ ## Normalize the normal vectors
+ len = sqrt (nx.^2 + ny.^2 + nz.^2);
+ nx = nx ./ len;
+ ny = ny ./ len;
+ nz = nz ./ len;
+
+ if (nargout == 0)
+ plot3 ([x(:)'; x(:).' + nx(:).' ; NaN(size(x(:).'))](:),
+ [y(:)'; y(:).' + ny(:).' ; NaN(size(y(:).'))](:),
+ [z(:)'; z(:).' + nz(:).' ; NaN(size(z(:).'))](:),
+ varargin{ioff:end});
+ else
+ Nx = nx;
+ Ny = ny;
+ Nz = nz;
+ endif
+ endfunction
+
+ %!demo
+ %! [x, y, z] = peaks(10);
+ %! surfnorm (x, y, z);
+
+ %!demo
+ %! surfnorm (peaks(10));
*** ./scripts/plot/__quiver__.m.orig25 2007-11-26 15:48:45.292899582 +0100
--- ./scripts/plot/__quiver__.m 2007-11-25 05:20:12.151989709 +0100
***************
*** 0 ****
--- 1,222 ----
+ ## Copyright (C) 2007 David Bateman
+ ##
+ ## 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
+ ## <http://www.gnu.org/licenses/>.
+
+ ## Undocumented internal function
+
+ function hlist = __quiver__ (varargin)
+ h = varargin {1};
+ is3d = varargin {2};
+
+ s = 1;
+ arrowsize = 0.33;
+
+ firstnonnumeric = Inf;
+ for i = 3:nargin
+ if (! isnumeric (varargin {i}))
+ firstnonnumeric = i;
+ break;
+ endif
+ endfor
+
+ ioff = 3;
+ if (nargin < (6 + is3d) || firstnonnumeric < (6 + is3d))
+ u = varargin{ioff++};
+ v = varargin{ioff++};
+ if (is3d)
+ w = varargin{ioff++}
+ [x, y, z] = meshgrid (1:size(u,1), 1:size(u,2), 1:max(size(w)));
+ else
+ [x, y] = meshgrid (1:size(u,1), 1:size(u,2));
+ endif
+ if (nargin >= ioff && isnumeric (varargin{ioff}) &&
+ isscalar (varargin{ioff}))
+ s = varargin{ioff++};
+ endif
+ else
+ x = varargin{ioff++};
+ y = varargin{ioff++};
+ if (is3d)
+ z = varargin{ioff++};
+ endif
+ u = varargin{ioff++};
+ v = varargin{ioff++};
+ if (is3d)
+ w = varargin{ioff++};
+ if (isvector(x) && isvector(y) && isvector(z) &&
+ (!isvector (u) || !isvector (v) || !isvector(w)))
+ [x, y, z] = meshgrid (x, y, z);
+ endif
+ else
+ if (isvector(x) && isvector(y) && (!isvector (u) || !isvector (v)))
+ [x, y] = meshgrid (x, y);
+ endif
+ endif
+ if (nargin >= ioff && isnumeric (varargin{ioff}) &&
+ isscalar (varargin{ioff}))
+ s = varargin{ioff++};
+ endif
+ endif
+
+ have_filled = false;
+ have_line_spec = false;
+ while (ioff <= nargin)
+ arg = varargin {ioff++};
+ if (ischar (arg) && strncmp (tolower (arg), "filled", 6))
+ have_filled = true;
+ elseif ((isstr (arg) || iscell (arg))
+ && ! have_line_spec)
+ [linespec, valid] = __pltopt__ ("quiver", arg, false);
+ if (valid)
+ have_line_spec = true;
+ if (strncmp (linespec.linestyle, "none", 4))
+ linespec.linestyle = "-";
+ endif
+ else
+ error ("quiver: invalid linespec");
+ endif
+ else
+ error ("quiver: unrecognized argument");
+ endif
+ endwhile
+
+ if (s)
+ ## 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 = 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
+
+ hstate = get (h, "nextplot");
+ unwind_protect
+ 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);
+ else
+ h1 = plot ([x.'; xend.'; NaN(1, length (x))](:),
+ [y.'; yend.'; NaN(1, length (y))](:),
+ "linestyle", linespec.linestyle);
+ endif
+ else
+ if (is3d)
+ h1 = plot3 ([x.'; xend.'; NaN(1, length (x))](:),
+ [y.'; yend.'; NaN(1, length (y))](:),
+ [z.'; zend.'; NaN(1, length (z))](:));
+ 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);
+ 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 / 3;
+ endif
+
+ if (have_line_spec)
+ if (isfield (linespec, "marker") &&
+ ! strncmp (linespec.marker, "none", 4))
+ if (is3d)
+ 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");
+ else
+ h2 = plot ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
+ [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),
+ "linestyle", "none");
+ endif
+ else
+ if (is3d)
+ h2 = plot3 ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
+ [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),
+ [zarrw1.'; zend.'; zarrw2.'; NaN(1, length (z))](:),
+ "linestyle", linespec.linestyle);
+ else
+ h2 = plot ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
+ [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:),
+ "linestyle", linespec.linestyle);
+ 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))](:));
+ else
+ h2 = plot ([xarrw1.'; xend.'; xarrw2.'; NaN(1, length (x))](:),
+ [yarrw1.'; yend.'; yarrw2.'; NaN(1, length (y))](:));
+ 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);
+ endif
+ endif
+ if (have_filled)
+ ## FIXME gnuplot doesn't respect the markerfacecolor field
+ set(h3, "markerfacecolor", get (h1, "color"));
+ endif
+ unwind_protect_cleanup
+ set (h, "nextplot", hstate);
+ end_unwind_protect
+
+ hlist = [h1; h2; h3];
+
+ endfunction
2007-11-23 David Bateman <address@hidden>
* plot/quiver3.m, plot/surfnorm.m, plot/__quiver__.m: New functions.
* plot/Makefile.in (SOURCES): Add them to the sources.
* plot/quiver.m: Modify to use __quiver__.m.