octave-maintainers
[Top][All Lists]
Advanced

[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.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]