changeset 17055:9fe930c5abbf

plot3.m: Update to use __plt_get_axis_arg__ and newplot. * scripts/plot/plot3.m: Update to use __plt_get_axis_arg__ and newplot. Redo docstring. Add second %!demo.
author Rik <rik@octave.org>
date Wed, 24 Jul 2013 23:12:46 -0700
parents 27b3a675ea6b
children 5dae8af4773d
files scripts/plot/plot3.m
diffstat 1 files changed, 240 insertions(+), 204 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/plot/plot3.m	Wed Jul 24 23:12:46 2013 -0700
+++ b/scripts/plot/plot3.m	Wed Jul 24 23:12:46 2013 -0700
@@ -17,9 +17,17 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {} plot3 (@var{args})
-## Produce three-dimensional plots.  Many different combinations of
-## arguments are possible.  The simplest form is
+## @deftypefn  {Function File} {} plot3 (@var{x}, @var{y}, @var{z})
+## @deftypefnx {Function File} {} plot3 (@var{x}, @var{y}, @var{z}, @var{property}, @var{value}, @dots{})
+## @deftypefnx {Function File} {} plot3 (@var{x}, @var{y}, @var{z}, @var{fmt})
+## @deftypefnx {Function File} {} plot3 (@var{x}, @var{cplx})
+## @deftypefnx {Function File} {} plot3 (@var{cplx})
+## @deftypefnx {Function File} {} plot3 (@var{hax}, @dots{})
+## @deftypefnx {Function File} {@var{h} =} plot3 (@dots{})
+## Produce three-dimensional plots.
+##
+## Many different combinations of arguments are possible.  The simplest
+## form is
 ##
 ## @example
 ## plot3 (@var{x}, @var{y}, @var{z})
@@ -29,14 +37,13 @@
 ## in which the arguments are taken to be the vertices of the points to
 ## be plotted in three dimensions.  If all arguments are vectors of the
 ## same length, then a single continuous line is drawn.  If all arguments
-## are matrices, then each column of the matrices is treated as a
-## separate line.  No attempt is made to transpose the arguments to make
-## the number of rows match.
+## are matrices, then each column of is treated as a separate line.  No attempt
+## is made to transpose the arguments to make the number of rows match.
 ##
 ## If only two arguments are given, as
 ##
 ## @example
-## plot3 (@var{x}, @var{c})
+## plot3 (@var{x}, @var{cplx})
 ## @end example
 ##
 ## @noindent
@@ -46,7 +53,7 @@
 ## If only one argument is given, as
 ##
 ## @example
-## plot3 (@var{c})
+## plot3 (@var{cplx})
 ## @end example
 ##
 ## @noindent
@@ -70,6 +77,15 @@
 ## plot3 (@var{x1}, @var{c1}, "", @var{c2}, "", @dots{})
 ## @end example
 ##
+## Multiple property-value pairs may be specified which will affect the line
+## objects drawn by @code{plot3}.  If the @var{fmt} argument is supplied it
+## will format the line objects in the same manner as @code{plot}.
+##
+## If the first argument is an axis handle @var{hax}, then plot into these axes,
+## rather than the current axis handle returned by @code{gca}.
+##
+## The optional return value @var{h} is a graphics handle to the created plot.
+##
 ## An example of the use of @code{plot3} is
 ##
 ## @example
@@ -79,7 +95,7 @@
 ## plot3 (z, exp (2i*pi*z), ";complex sinusoid;");
 ## @end group
 ## @end example
-## @seealso{plot, xlabel, ylabel, zlabel, title, print}
+## @seealso{ezplot3, plot}
 ## @end deftypefn
 
 ## Author: Paul Kienzle
@@ -87,73 +103,209 @@
 
 function retval = plot3 (varargin)
 
-  newplot ();
+  [hax, varargin, nargs] = __plt_get_axis_arg__ ("plot3", varargin{:});
+
+  if (nargs < 1)
+    print_usage ();
+  endif
+
+  oldfig = ifelse (isempty (hax), [], get (0, "currentfigure"));
+  unwind_protect
+    hax = newplot (hax);
+
+    x_set = 0;
+    y_set = 0;
+    z_set = 0;
+    property_set = 0;
+    fmt_set = 0;
+    properties = {};
+    tlgnd = {};
+    hlgnd = [];
+    idx = 0;
+
+    ## Gather arguments, decode format, and plot lines.
+    arg = 0;
+    while (arg++ < nargs)
+      new = varargin{arg};
+      new_cell = varargin(arg);
+
+      if (property_set)
+        properties = [properties, new_cell];
+        property_set = 0;
+        continue;
+      endif
+
+      if (ischar (new))
+        if (! z_set)
+          if (! y_set)
+            if (! x_set)
+              error ("plot3: needs X, [ Y, [ Z ] ]");
+            else
+              y = real (x);
+              z = imag (x);
+              y_set = 1;
+              z_set = 1;
+              if (rows (x) > 1)
+                x = repmat ((1:rows (x))', 1, columns (x));
+              else
+                x = 1:columns (x);
+              endif
+            endif
+          else
+            z = imag (y);
+            y = real (y);
+            z_set = 1;
+          endif
+        endif
+
+        if (! fmt_set)
+          [options, valid] = __pltopt__ ("plot3", new, false);
+          if (! valid)
+            properties = [properties, new_cell];
+            property_set = 1;
+            continue;
+          else
+            fmt_set = 1;
+            while (arg < nargs && ischar (varargin{arg+1}))
+              if (nargs - arg < 2)
+                error ("plot3: properties must appear followed by a value");
+              endif
+              properties = [properties, varargin(arg+1:arg+2)];
+              arg += 2;
+            endwhile
+          endif
+        else
+          properties = [properties, new_cell];
+          property_set = 1;
+          continue;
+        endif
+
+        if (isvector (x) && isvector (y))
+          if (isvector (z))
+            x = x(:);
+            y = y(:);
+            z = z(:);
+          elseif (length (x) == rows (z) && length (y) == columns (z))
+            [x, y] = meshgrid (x, y);
+          else
+            error ("plot3: [length(X), length(Y)] must match size (Z)");
+          endif
+        endif
 
-  x_set = 0;
-  y_set = 0;
-  z_set = 0;
-  property_set = 0;
-  fmt_set = 0;
-  properties = {};
-  tlgnd = {};
-  hlgnd = [];
-  idx = 0;
+        if (! size_equal (x, y, z))
+          error ("plot3: X, Y, and Z must have the same shape");
+        elseif (ndims (x) > 2)
+          error ("plot3: X, Y, and Z must not have more than two dimensions");
+        endif
+
+        for i = 1 : columns (x)
+          linestyle = options.linestyle;
+          marker = options.marker;
+          if (isempty (marker) && isempty (linestyle))
+             [linestyle, marker] = __next_line_style__ ();
+          endif
+          color = options.color;
+          if (isempty (color))
+            color = __next_line_color__ ();
+          endif
+
+          htmp(++idx) = line (hax, x(:, i), y(:, i), z(:, i),
+                              "color", color, "linestyle", linestyle,
+                              "marker", marker, properties{:});
+          key = options.key;
+          if (! isempty (key))
+            hlgnd = [hlgnd, htmp(idx)];
+            tlgnd = {tlgnd{:}, key};
+          endif
+        endfor
 
-  ## Gather arguments, decode format, and plot lines.
-  arg = 0;
-  while (arg++ < nargin)
-    new = varargin{arg};
-    new_cell = varargin(arg);
+        x_set = 0;
+        y_set = 0;
+        z_set = 0;
+        fmt_set = 0;
+        properties = {};
+      elseif (! x_set)
+        x = new;
+        x_set = 1;
+      elseif (! y_set)
+        y = new;
+        y_set = 1;
+      elseif (! z_set)
+        z = new;
+        z_set = 1;
+      else
+        if (isvector (x) && isvector (y))
+          if (isvector (z))
+            x = x(:);
+            y = y(:);
+            z = z(:);
+          elseif (length (x) == rows (z) && length (y) == columns (z))
+            [x, y] = meshgrid (x, y);
+          else
+            error ("plot3: [length(X), length(Y)] must match size (Z)");
+          endif
+        endif
+
+        if (! size_equal (x, y, z))
+          error ("plot3: X, Y, and Z must have the same shape");
+        elseif (ndims (x) > 2)
+          error ("plot3: X, Y, and Z must not have more than two dimensions");
+        endif
+
+        options = __default_plot_options__ ();
+        for i = 1 : columns (x)
+          linestyle = options.linestyle;
+          marker = options.marker;
+          if (isempty (marker) && isempty (linestyle))
+            [linestyle, marker] = __next_line_style__ ();
+          endif
+          color = options.color;
+          if (isempty (color))
+            color = __next_line_color__ ();
+          endif
+
+          htmp(++idx) = line (hax, x(:, i), y(:, i), z(:, i),
+                              "color", color, "linestyle", linestyle,
+                              "marker", marker, properties{:});
+          key = options.key;
+          if (! isempty (key))
+            hlgnd = [hlgnd, htmp(idx)];
+            tlgnd = {tlgnd{:}, key};
+          endif
+        endfor
+
+        x = new;
+        y_set = 0;
+        z_set = 0;
+        fmt_set = 0;
+        properties = {};
+      endif
+
+    endwhile
 
     if (property_set)
-      properties = [properties, new_cell];
-      property_set = 0;
-      continue;
+      error ("plot3: properties must appear followed by a value");
     endif
 
-    if (ischar (new))
-      if (! z_set)
-        if (! y_set)
-          if (! x_set)
-            error ("plot3: needs x, [ y, [ z ] ]");
-          else
-            z = imag (x);
-            y = real (x);
-            y_set = 1;
-            z_set = 1;
-            if (rows (x) > 1)
-              x = repmat ((1:rows (x))', 1, columns (x));
-            else
-              x = 1:columns (x);
-            endif
-          endif
-        else
+    ## Handle last plot.
+
+    if (x_set)
+      if (y_set)
+        if (! z_set)
           z = imag (y);
           y = real (y);
           z_set = 1;
         endif
-      endif
-
-      if (! fmt_set)
-        [options, valid] = __pltopt__ ("plot3", new, false);
-        if (! valid)
-          properties = [properties, new_cell];
-          property_set = 1;
-          continue;
+      else
+        y = real (x);
+        z = imag (x);
+        y_set = 1;
+        z_set = 1;
+        if (rows (x) > 1)
+          x = repmat ((1:rows (x))', 1, columns (x));
         else
-          fmt_set = 1;
-          while (arg < nargin && ischar (varargin{arg+1}))
-            if (nargin - arg < 2)
-              error ("plot3: properties must appear followed by a value");
-            endif
-            properties = [properties, varargin(arg+1:arg+2)];
-            arg += 2;
-          endwhile
+          x = 1:columns (x);
         endif
-      else
-        properties = [properties, new_cell];
-        property_set = 1;
-        continue;
       endif
 
       if (isvector (x) && isvector (y))
@@ -164,176 +316,56 @@
         elseif (length (x) == rows (z) && length (y) == columns (z))
           [x, y] = meshgrid (x, y);
         else
-          error ("plot3: [length(x), length(y)] must match size (z)");
+          error ("plot3: [length(X), length(Y)] must match size (Z)");
         endif
       endif
 
       if (! size_equal (x, y, z))
-        error ("plot3: x, y, and z must have the same shape");
+        error ("plot3: X, Y, and Z must have the same shape");
       elseif (ndims (x) > 2)
-        error ("plot3: x, y, and z must not have more than two dimensions");
+        error ("plot3: X, Y, and Z must not have more than two dimensions");
       endif
 
+      options = __default_plot_options__ ();
+
       for i = 1 : columns (x)
         linestyle = options.linestyle;
         marker = options.marker;
         if (isempty (marker) && isempty (linestyle))
-           [linestyle, marker] = __next_line_style__ ();
-        endif
-        color = options.color;
-        if (isempty (color))
-          color = __next_line_color__ ();
-        endif
-
-        tmp(++idx) = line (x(:, i), y(:, i), z(:, i),
-                           "color", color, "linestyle", linestyle,
-                           "marker", marker, properties{:});
-        key = options.key;
-        if (! isempty (key))
-          hlgnd = [hlgnd, tmp(idx)];
-          tlgnd = {tlgnd{:}, key};
-        endif
-      endfor
-
-      x_set = 0;
-      y_set = 0;
-      z_set = 0;
-      fmt_set = 0;
-      properties = {};
-    elseif (! x_set)
-      x = new;
-      x_set = 1;
-    elseif (! y_set)
-      y = new;
-      y_set = 1;
-    elseif (! z_set)
-      z = new;
-      z_set = 1;
-    else
-      if (isvector (x) && isvector (y))
-        if (isvector (z))
-          x = x(:);
-          y = y(:);
-          z = z(:);
-        elseif (length (x) == rows (z) && length (y) == columns (z))
-          [x, y] = meshgrid (x, y);
-        else
-          error ("plot3: [length(x), length(y)] must match size (z)");
-        endif
-      endif
-
-      if (! size_equal (x, y, z))
-        error ("plot3: x, y, and z must have the same shape");
-      elseif (ndims (x) > 2)
-        error ("plot3: x, y, and z must not have more than two dimensions");
-      endif
-
-      options =  __default_plot_options__ ();
-      for i = 1 : columns (x)
-        linestyle = options.linestyle;
-        marker = options.marker;
-        if (isempty (marker) && isempty (linestyle))
-           [linestyle, marker] = __next_line_style__ ();
+          [linestyle, marker] = __next_line_style__ ();
         endif
         color = options.color;
         if (isempty (color))
           color = __next_line_color__ ();
         endif
 
-        tmp(++idx) = line (x(:, i), y(:, i), z(:, i),
-                           "color", color, "linestyle", linestyle,
-                           "marker", marker, properties{:});
+        htmp(++idx) = line (hax, x(:, i), y(:, i), z(:, i),
+                            "color", color, "linestyle", linestyle,
+                            "marker", marker, properties{:});
         key = options.key;
         if (! isempty (key))
-          hlgnd = [hlgnd, tmp(idx)];
+          hlgnd = [hlgnd, htmp(idx)];
           tlgnd = {tlgnd{:}, key};
         endif
       endfor
-
-      x = new;
-      y_set = 0;
-      z_set = 0;
-      fmt_set = 0;
-      properties = {};
     endif
 
-  endwhile
-
-  if (property_set)
-    error ("plot3: properties must appear followed by a value");
-  endif
-
-  ## Handle last plot.
-
-  if (x_set)
-    if (y_set)
-      if (! z_set)
-        z = imag (y);
-        y = real (y);
-        z_set = 1;
-      endif
-    else
-      z = imag (x);
-      y = real (x);
-      y_set = 1;
-      z_set = 1;
-      if (rows (x) > 1)
-        x = repmat ((1:rows (x))', 1, columns (x));
-      else
-        x = 1:columns (x);
-      endif
+    if (! isempty (hlgnd))
+      legend (hax, hlgnd, tlgnd);
     endif
 
-    if (isvector (x) && isvector (y))
-      if (isvector (z))
-        x = x(:);
-        y = y(:);
-        z = z(:);
-      elseif (length (x) == rows (z) && length (y) == columns (z))
-        [x, y] = meshgrid (x, y);
-      else
-        error ("plot3: [length(x), length(y)] must match size (z)");
-      endif
-    endif
-
-    if (! size_equal (x, y, z))
-      error ("plot3: x, y, and z must have the same shape");
-    elseif (ndims (x) > 2)
-      error ("plot3: x, y, and z must not have more than two dimensions");
+    if (! ishold ())
+      set (hax, "view", [-37.5, 30]);
     endif
 
-    options =  __default_plot_options__ ();
-
-    for i = 1 : columns (x)
-      linestyle = options.linestyle;
-      marker = options.marker;
-      if (isempty (marker) && isempty (linestyle))
-        [linestyle, marker] = __next_line_style__ ();
-      endif
-      color = options.color;
-      if (isempty (color))
-        color = __next_line_color__ ();
-      endif
-
-      tmp(++idx) = line (x(:, i), y(:, i), z(:, i),
-                         "color", color, "linestyle", linestyle,
-                         "marker", marker, properties{:});
-      key = options.key;
-      if (! isempty (key))
-        hlgnd = [hlgnd, tmp(idx)];
-        tlgnd = {tlgnd{:}, key};
-      endif
-    endfor
-  endif
-
-  if (!isempty (hlgnd))
-    legend (gca (), hlgnd, tlgnd);
-  endif
-
-  set (gca (), "view", [-37.5, 30]);
+  unwind_protect_cleanup
+    if (! isempty (oldfig))
+      set (0, "currentfigure", oldfig);
+    endif
+  end_unwind_protect
 
   if (nargout > 0 && idx > 0)
-    retval = tmp;
+    retval = htmp;
   endif
 
 endfunction
@@ -343,5 +375,9 @@
 %! clf;
 %! z = [0:0.05:5];
 %! plot3 (cos (2*pi*z), sin (2*pi*z), z, ';helix;');
+
+%!demo
+%! clf;
+%! z = [0:0.05:5];
 %! plot3 (z, exp (2i*pi*z), ';complex sinusoid;');