changeset 19115:d59d052c9858

rotate.m: new function * rotate.m: New function. * NEWS: List it. * plot.txi: Document it in new section.
author John W. Eaton <jwe@octave.org>
date Thu, 11 Sep 2014 16:07:12 -0400
parents af9c22e20a57
children 96df707c7dad
files NEWS doc/interpreter/plot.txi scripts/plot/draw/peaks.m scripts/plot/draw/rotate.m
diffstat 4 files changed, 232 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Thu Sep 11 00:49:22 2014 -0400
+++ b/NEWS	Thu Sep 11 16:07:12 2014 -0400
@@ -4,7 +4,7 @@
  ** A new syntax for object oriented programming termed classdef has been
     introduced.  See the manual for more extensive documentation of the
     classdef interface.
-    
+
     New keywords:
 
       classdef      endclassdef
@@ -49,7 +49,7 @@
     results equivalent to Matlab even for esoteric combinations of
     faces/vertices/cdata.
 
- ** The polar() plot function now draws a circular theta axis and 
+ ** The polar() plot function now draws a circular theta axis and
     radial rho axis rather than using a rectangular x/y axis.
 
  ** linkprop has been completely re-coded for performance and Matlab
@@ -66,11 +66,22 @@
 
  ** Other new functions added in 4.2:
 
-      bandwidth            ilu             javachk
-      dir_in_loadpath      isbanded        linkaxes
-      hgload               isdiag          numfields
-      hgsave               istril          sylvester
-      ichol                istriu          lscov         
+      bandwidth
+      dir_in_loadpath
+      hgload
+      hgsave
+      ichol
+      ilu
+      isbanded
+      isdiag
+      istril
+      istriu
+      javachk
+      linkaxes
+      lscov
+      numfields
+      rotate
+      sylvester
 
  ** Deprecated functions.
 
@@ -78,22 +89,23 @@
     be removed from Octave 4.6 (or whatever version is the second major
     release after 4.2):
 
-      bicubic              syl
+      bicubic
       find_dir_in_path
       nargchk
       nfields
+      syl
 
     The following functions were deprecated in Octave 3.8 and have been
     removed from Octave 4.2.
 
-      default_save_options    java_new            
-      gen_doc_cache           java_unsigned_conversion  
-      interp1q                javafields                
-      isequalwithequalnans    javamethods               
+      default_save_options    java_new
+      gen_doc_cache           java_unsigned_conversion
+      interp1q                javafields
+      isequalwithequalnans    javamethods
       java_convert_matrix     re_read_readline_init_file
-      java_debug              read_readline_init_file   
-      java_invoke             saving_history            
-                              
+      java_debug              read_readline_init_file
+      java_invoke             saving_history
+
     The following keywords were deprecated in Octave 3.8 and have been
     removed from Octave 4.2
 
@@ -144,12 +156,12 @@
 
     The following functions were deprecated in Octave 3.6 and have been
     removed from Octave 4.0.
-                                           
-      cut                polyderiv        
-      cor                shell_cmd        
-      corrcoef           studentize       
-      __error_text__     sylvester_matrix 
-      error_text         
+
+      cut                polyderiv
+      cor                shell_cmd
+      corrcoef           studentize
+      __error_text__     sylvester_matrix
+      error_text
 
     The following functions have been deprecated in Octave 4.0 and will
     be removed from Octave 4.4 (or whatever version is the second major
@@ -157,7 +169,7 @@
 
       allow_noninteger_range_as_index
       do_braindead_shortcircuit_evaluation
-      
+
     The internal function atan2 of the sparse matrix class has been deprecated
     in Octave 4.0 and will be removed from Octave 4.4 (or whatever version is
     the second major release after 4.0).  Use the Fatan2 function with sparse
--- a/doc/interpreter/plot.txi	Thu Sep 11 00:49:22 2014 -0400
+++ b/doc/interpreter/plot.txi	Thu Sep 11 16:07:12 2014 -0400
@@ -63,6 +63,7 @@
 * Plot Annotations::
 * Multiple Plots on One Page::
 * Multiple Plot Windows::
+* Manipulation of Plot Objects::
 * Manipulation of Plot Windows::
 * Use of the @code{interpreter} Property::
 * Printing and Saving Plots::
@@ -530,6 +531,12 @@
 
 @DOCSTRING(figure)
 
+@node Manipulation of Plot Objects
+@subsection Manipulation of Plot Objects
+@cindex plotting, object manipulation
+
+@DOCSTRING(rotate)
+
 @node Manipulation of Plot Windows
 @subsection Manipulation of Plot Windows
 @cindex plotting, window manipulation
--- a/scripts/plot/draw/peaks.m	Thu Sep 11 00:49:22 2014 -0400
+++ b/scripts/plot/draw/peaks.m	Thu Sep 11 16:07:12 2014 -0400
@@ -83,6 +83,9 @@
 
   if (nargout == 0)
     surf (x, y, Z);
+    Z_max = max (Z(:));
+    Z_min = min (Z(:));
+    axis ([-3, 3, -3, 3, Z_min, Z_max]);
   elseif (nargout == 1)
     X_out = Z;
   else
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/draw/rotate.m	Thu Sep 11 16:07:12 2014 -0400
@@ -0,0 +1,188 @@
+## Copyright (C) 2014 John W. Eaton
+##
+## 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} {} rotate (@var{h}, @var{dir}, @var{alpha})
+## @deftypefnx {Function File} {} rotate (@dots{}, @var{origin})
+## Rotate the plot object @var{h} through @var{alpha} degrees around
+## the line with direction @var{dir} and origin @var{origin}.
+##
+## The default value of @var{origin} is the center of the axes
+## object that is the parent of @var{h}.
+##
+## If @var{h} is a vector of handles, they must all have the same
+## parent axes object.
+##
+## Graphics objects that may be rotated are lines, surfaces, patches,
+## and images.
+## @end deftypefn
+
+function rotate (h, direction, alpha, origin)
+
+  ## Note in doc string about compatibility issues with calculation of
+  ## default origin due to possible differences in the auto-scaling
+  ## algorithm between Octave and Matlab.
+
+  if (nargin < 3 || nargin > 4)
+    print_unage ();
+  endif
+
+  is_h = ishandle (h);
+  if (is_h)
+    ax_list = get (h, "parent");
+    if (iscell (ax_list))
+      ax_list = cell2mat (ax_list);
+    endif
+    if (ax_list == ax_list(1))
+      ax = ax_list(1);
+    else
+       error ("rotate: all handles must be children of the same axes object");
+    endif
+  else
+    error ("rotate: H must be an array of one or more graphics handles");
+  endif
+
+  if (! (isnumeric (direction) && numel (direction) == 3))
+    error ("rotate: invalid direction");
+  endif
+
+  if (! (isnumeric (alpha) && isscalar (alpha)))
+    error ("rotate: invalid rotation angle");
+  endif
+
+  t = get (h, "type");
+
+  is_image = strcmp (t, "image");
+  is_line = strcmp (t, "line");
+  is_patch = strcmp (t, "patch");
+  is_surface = strcmp (t, "surface");
+
+  if (! all (is_image | is_line | is_patch | is_surface))
+    error ("rotate: expecting image, line, patch, or surface objects");
+  endif
+
+  if (nargin == 4)
+    if (! (isnumeric (origin) && numel (origin) == 3))
+       error ("rotate: invalid origin");
+    endif
+  else
+    ## Should Z limit be considered when computing origin?
+
+    use_zlim = any (is_patch | is_surface);
+
+    if (! use_zlim && any (is_line))
+      idx = find (is_line)';
+      for i = idx
+        if (! isempty (get (h(i), "zdata")))
+          use_zlim = true;
+          break;
+        endif
+      endfor
+    endif
+
+    xlim = get (ax, "xlim");
+    ylim = get (ax, "ylim");
+
+    a = (xlim(1) + xlim(2)) / 2;
+    b = (ylim(1) + ylim(2)) / 2;
+
+    if (use_zlim)
+      zlim = get (ax, "zlim");
+      c = (zlim(1) + zlim(2)) / 2;
+    else
+      c = 0;
+    endif
+
+    origin = [a, b, c];
+  endif
+
+  direction = direction / norm (direction);
+
+  u = direction(1);
+  v = direction(2);
+  w = direction(3);
+
+  a = origin(1);
+  b = origin(2);
+  c = origin(3);
+
+  sa = sind (alpha);
+  ca = cosd (alpha);
+
+  for i = 1:numel (h)
+    x = get (h(i), "xdata");
+    y = get (h(i), "ydata");
+
+    if (is_image(i))
+      z = zeros (size (x));
+    else
+      z = get (h(i), "zdata");
+      if (isempty (z))
+        z = zeros (size (x));
+      elseif (isvector (x) && isvector (y) && ! isvector (z))
+        [x, y] = meshgrid (x, y);
+      endif
+    endif
+
+    if (a == 0 && b == 0 && c == 0)
+      tmp = (u*x + v*y + w*z) * (1 - ca);
+
+      xr = u*tmp + x*ca + (-w*y + v*z)*sa;
+      yr = v*tmp + y*ca + (w*x - u*z)*sa;
+      zr = w*tmp + z*ca + (-v*x + u*y)*sa;
+    else
+      one_m_ca = 1 - ca;
+      tmp = u*x + v*y + w*z;
+
+      xr = ((a*(v**2 + w**2) - u*(b*v + c*w - tmp))*one_m_ca
+            + x*ca + (-c*v + b*w - w*y + v*z)*sa);
+      yr = ((b*(u**2 + w**2) - v*(a*u + c*w - tmp))*one_m_ca
+            + y*ca + (c*u - a*w + w*x - u*z)*sa);
+      zr = ((c*(u**2 + v**2) - w*(a*u + b*v - tmp))*one_m_ca
+            + z*ca + (-b*u + a*v - v*x + u*y)*sa);
+    endif
+
+    set (h(i), "xdata", xr, "ydata", yr);
+
+    if (! is_image(i))
+      set (h(i), "zdata", zr);
+    endif
+  endfor
+
+endfunction
+
+%% Test input validation
+%!shared h1, h2, o1, o2, o3
+%! h1 = figure ("visible", "off");
+%! o1 = line ();
+%! h2 = figure ("visible", "off");
+%! o2 = line ();
+%! o3 = text (0, 0, "foobar");
+%!error rotate ()
+%!error rotate (o1)
+%!error rotate (o1, [0,0,0]);
+%!error <all handles must be children of the same axes object> rotate ([o1, o2], [0,0,0], 90);
+%!error <invalid direction> rotate (o1, "foo", 90);
+%!error <invalid rotation angle> rotate (o1, [0,0,0], "foo");
+%!error <invalid origin> rotate (o1, [0,0,0], 90, "foo");
+%!error rotate (o1, [0,0,0], 90, [0,0,0], 1);
+%!error <H must be an array of one or more graphics handles> rotate (NaN, [0,0,0], 90);
+%!error <expecting image, line, patch, or surface objects> rotate (o3, [0,0,0], 90);
+%!test
+%! close (h1);
+%! close (h2);