Mercurial > jwe > octave
changeset 24129:f80dc6db9d18
Add camzoom and camroll functions (patch #9049).
* scripts/plot/appearance/camroll.m, camzoom.m: New functions.
* scripts/plot/appearance/module.mk: Add new files.
* doc/interpreter/plot.txi: Add docstrings to manual.
* scripts/help/__unimplemented__.m: Remove new functions from list.
* scripts/plot/appearance/camup.m: Docs now suggest camroll.
* scripts/plot/appearance/__rotate_around_axis__.m: Move file from draw/private.
* scripts/plot/draw/module.mk: Remove moved file.
author | Colin Macdonald <cbm@m.fsf.org> |
---|---|
date | Tue, 12 Jul 2016 22:19:54 -0700 |
parents | 5ce4dfe5d906 |
children | 6fdbdb66d7cb |
files | doc/interpreter/plot.txi scripts/help/__unimplemented__.m scripts/plot/appearance/__rotate_around_axis__.m scripts/plot/appearance/camroll.m scripts/plot/appearance/camup.m scripts/plot/appearance/camzoom.m scripts/plot/appearance/module.mk scripts/plot/draw/module.mk scripts/plot/draw/private/__rotate_around_axis__.m |
diffstat | 9 files changed, 372 insertions(+), 62 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/interpreter/plot.txi Tue Jul 12 22:32:28 2016 -0700 +++ b/doc/interpreter/plot.txi Tue Jul 12 22:19:54 2016 -0700 @@ -466,12 +466,16 @@ @DOCSTRING(campos) +@DOCSTRING(camroll) + @DOCSTRING(camtarget) @DOCSTRING(camup) @DOCSTRING(camva) +@DOCSTRING(camzoom) + @DOCSTRING(slice) @DOCSTRING(ribbon)
--- a/scripts/help/__unimplemented__.m Tue Jul 12 22:32:28 2016 -0700 +++ b/scripts/help/__unimplemented__.m Tue Jul 12 22:19:54 2016 -0700 @@ -578,8 +578,6 @@ "camorbit", "campan", "camproj", - "camroll", - "camzoom", "categorical", "categories", "cdf2rdf",
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/plot/appearance/__rotate_around_axis__.m Tue Jul 12 22:19:54 2016 -0700 @@ -0,0 +1,58 @@ +## Copyright (C) 2014-2017 John W. Eaton +## Copyright (C) 2016 Colin B. Macdonald +## +## 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 {} {[@var{xr}, @var{yr}, @var{zr}] =} __rotate_around_axis__ (@var{x}, @var{y}, @var{z}, @var{angle}, @var{dir}, @var{origin}) +## Rotate the points given by X, Y, Z about an axis by ANGLE degrees. +## The axis is specified by the vector DIR and the point ORIGIN. +## @end deftypefn + +function [xr, yr, zr] = __rotate_around_axis__ (x, y, z, angle, dir, origin) + + dir /= norm (dir); + u = dir(1); + v = dir(2); + w = dir(3); + + a = origin(1); + b = origin(2); + c = origin(3); + + sa = sind (angle); + ca = cosd (angle); + + 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 + +endfunction
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/plot/appearance/camroll.m Tue Jul 12 22:19:54 2016 -0700 @@ -0,0 +1,152 @@ +## Copyright (C) 2016 Colin B. Macdonald +## +## 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. +## +## This software 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 this software; see the file COPYING. +## If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {} {} camroll (@var{theta}) +## @deftypefnx {} {} camroll (@var{ax}, @var{theta}) +## Roll the camera. +## +## Roll the camera clockwise by @var{theta} degrees. +## For example, the following command will roll the camera by +## 30 degrees clockwise (to the right); this will cause the scene +## to appear to roll by 30 degrees to the left: +## @example +## @group +## @c doctest: +SKIP +## peaks () +## camroll (30) +## @end group +## @end example +## +## Roll the camera back: +## @example +## @group +## @c doctest: +SKIP +## camroll (-30) +## @end group +## @end example +## +## The following command restores the default camera roll: +## @example +## @group +## @c doctest: +SKIP +## camup ("auto") +## @end group +## @end example +## +## By default, these commands affect the current axis; alternatively, an axis +## can be specified by the optional argument @var{ax}. +## +## @seealso{camzoom, camup} +## @end deftypefn + + +function camroll (varargin) + + [hax, varargin, nargin] = __plt_get_axis_arg__ ("camroll", varargin{:}); + + if (nargin != 1) + print_usage (); + endif + + a = varargin{1}; + + if (! (isnumeric (a) && isscalar (a) )) + print_usage (); + endif + + if (isempty (hax)) + hax = gca (); + else + hax = hax(1); + endif + + view_ax = camtarget (hax) - campos (hax); + view_ax /= norm (view_ax); + ## orthogonalize the camup vector + up = camup (hax) - view_ax*dot (camup (hax), view_ax); + up /= norm (up); + + ## rotate the modified camup vector around the view axis + up = num2cell (up); + [up{:}] = __rotate_around_axis__ (up{:}, a, view_ax, [0 0 0]); + up = [up{:}]; + camup (hax, up) + +endfunction + + +%!demo +%! peaks () +%! camroll (30) + +%!test +%! hf = figure ("visible", "off"); +%! unwind_protect +%! sphere (10); +%! campos ([10 0 0]); +%! camroll (30); +%! p = camup (); +%! assert (p, [0 1/2 sqrt(3)/2], eps); +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect + +## test rolling, then rolling back +%!test +%! hf = figure ("visible", "off"); +%! unwind_protect +%! peaks (); +%! p = camup (); +%! assert (p, [0 0 1], eps); +%! camroll (30); +%! p = camup (); +%! ## from Matlab R2014a +%! q = [0.826398839602911 0.255644120004753 0.50170812412194]; +%! assert (p, q, 10*eps); +%! camroll (-30); +%! ## note it does not go back to [0 0 1]: instead orthog to camera view: +%! p = camup (); +%! assert (dot (p, camtarget () - campos ()), 0, eps); +%! q = [0.496200420425837 0.646660977913424 0.57932264103285]; +%! assert (p, q, 10*eps); +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect + +## test ax input by creating another axis +%!test +%! hf = figure ("visible", "off"); +%! unwind_protect +%! hax1 = subplot (1, 2, 1); +%! sphere (hax1); +%! hax2 = subplot (1, 2, 2); +%! sphere (hax2); +%! camroll (hax1, 30); +%! x = camup (hax1); +%! y = camup (hax2); +%! assert (x, [0.660278 0.039151 0.750000], -1e-5) +%! assert (y, [0 0 1]) +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect + +## Test input validation +%!error <Invalid call> camroll (1, 2, 3) +%!error <Invalid call> camroll ("mod") +%!error <Invalid call> camroll (1, [1 2])
--- a/scripts/plot/appearance/camup.m Tue Jul 12 22:32:28 2016 -0700 +++ b/scripts/plot/appearance/camup.m Tue Jul 12 22:19:54 2016 -0700 @@ -56,7 +56,9 @@ ## @result{} 6... ## @end example ## A consequence is that ``pulling back'' on the up vector does not pitch the -## camera view (as that would require changing the target). +## camera view (as that would require changing the target). Setting the up +## vector is thus typically used only to roll the camera. A more intuitive +## command for this purpose is @pxref{XREFcamroll,,camroll}. ## ## Finally, we can reset the up vector to automatic mode: ## @example
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/plot/appearance/camzoom.m Tue Jul 12 22:19:54 2016 -0700 @@ -0,0 +1,152 @@ +## Copyright (C) 2016 Colin B. Macdonald +## +## 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. +## +## This software 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 this software; see the file COPYING. +## If not, see <http://www.gnu.org/licenses/>. + +## -*- texinfo -*- +## @deftypefn {} {} camzoom (@var{zf}) +## @deftypefnx {} {} camzoom (@var{ax}, @var{zf}) +## Zoom the camera in or out. +## +## A value of @var{zf} larger than 1 ``zooms in'' such that the scene appears +## magnified: +## @example +## @group +## hf = figure (); +## sphere (36) +## camzoom (1.2) +## @end group +## @end example +## +## A value smaller than 1 ``zooms out'' so the camera can see more of the scene: +## @example +## @group +## camzoom (0.5) +## @end group +## @end example +## +## Technically speaking, zooming affects the ``viewing angle''. The following +## command resets to the default zoom: +## @example +## @group +## camva ("auto") +## close (hf) +## @end group +## @end example +## +## By default, these commands affect the current axis; alternatively, an axis +## can be specified by the optional argument @var{ax}. +## +## @seealso{camroll, camva} +## @end deftypefn + + +function camzoom (varargin) + + [hax, varargin, nargin] = __plt_get_axis_arg__ ("camva", varargin{:}); + + if (nargin != 1) + print_usage (); + endif + + zf = varargin{1}; + + if (! (isnumeric (zf) && isscalar (zf) )) + print_usage (); + endif + + if (isempty (hax)) + hax = gca (); + else + hax = hax(1); + endif + + va = 2 * atand (tand (camva (hax)/2) / zf); + camva (hax, va); + +endfunction + + +%!demo +%! peaks (); +%! camzoom (2); + +%!test +%! hf = figure ("visible", "off"); +%! unwind_protect +%! sphere (); +%! x = camva (); +%! camzoom (5); +%! assert (tand (x/2) / tand (camva ()/2), 5); +%! camzoom (1/5); +%! y = camva (); +%! assert (x, y, eps); +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect + +%!test +%! hf = figure ("visible", "off"); +%! unwind_protect +%! sphere(); +%! x = camva (); +%! camzoom (2); +%! y = camva (); +%! ## Matlab 2014a +%! xm = 10.339584907202; +%! ym = 5.18033628450948; +%! assert (tand (x/2) / tand (y/2), tand (xm/2) / tand (ym/2), 2e-14) +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect + +%!test +%! hf = figure ("visible", "off"); +%! unwind_protect +%! peaks (); +%! campos ([20, 30, 50]); +%! camtarget ([0 0 1]); +%! x = camva (); +%! camzoom (5); +%! y = camva (); +%! ## Matlab 2014a +%! xm = 13.0746680295069; +%! ym = 2.62588066987212; +%! assert (tand (x/2) / tand (y/2), tand (xm/2) / tand (ym/2), 2e-14) +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect + +## test ax input by creating another axis +%!test +%! hf = figure ("visible", "off"); +%! unwind_protect +%! hax1 = subplot (1, 2, 1); +%! sphere (hax1); +%! hax2 = subplot (1, 2, 2); +%! sphere (hax2); +%! camzoom (hax1, 2) +%! x = camva (hax1); +%! y = camva (hax2); +%! assert (tand (y/2) / tand (x/2), 2) +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect + +## Test input validation +%!error <Invalid call> camzoom (1, 2, 3) +%!error <Invalid call> camzoom (1, [2, 3]) +%!error <Invalid call> camzoom ("string")
--- a/scripts/plot/appearance/module.mk Tue Jul 12 22:32:28 2016 -0700 +++ b/scripts/plot/appearance/module.mk Tue Jul 12 22:19:54 2016 -0700 @@ -9,13 +9,16 @@ %canon_reldir%_FCN_FILES = \ %reldir%/__clabel__.m \ %reldir%/__getlegenddata__.m \ + %reldir%/__rotate_around_axis__.m \ %reldir%/annotation.m \ %reldir%/axis.m \ %reldir%/box.m \ %reldir%/campos.m \ + %reldir%/camroll.m \ %reldir%/camtarget.m \ %reldir%/camup.m \ %reldir%/camva.m \ + %reldir%/camzoom.m \ %reldir%/caxis.m \ %reldir%/clabel.m \ %reldir%/daspect.m \
--- a/scripts/plot/draw/module.mk Tue Jul 12 22:32:28 2016 -0700 +++ b/scripts/plot/draw/module.mk Tue Jul 12 22:19:54 2016 -0700 @@ -16,7 +16,6 @@ %reldir%/private/__pie__.m \ %reldir%/private/__plt__.m \ %reldir%/private/__quiver__.m \ - %reldir%/private/__rotate_around_axis__.m \ %reldir%/private/__scatter__.m \ %reldir%/private/__stem__.m \ %reldir%/private/__unite_shared_vertices__.m
--- a/scripts/plot/draw/private/__rotate_around_axis__.m Tue Jul 12 22:32:28 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -## Copyright (C) 2014-2017 John W. Eaton -## Copyright (C) 2016 Colin B. Macdonald -## -## 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 {} {[@var{xr}, @var{yr}, @var{zr}] =} __rotate_around_axis__ (@var{x}, @var{y}, @var{z}, @var{angle}, @var{dir}, @var{origin}) -## Rotate the points given by X, Y, Z about an axis by ANGLE degrees. -## The axis is specified by the vector DIR and the point ORIGIN. -## @end deftypefn - -function [xr, yr, zr] = __rotate_around_axis__ (x, y, z, angle, dir, origin) - - dir /= norm (dir); - u = dir(1); - v = dir(2); - w = dir(3); - - a = origin(1); - b = origin(2); - c = origin(3); - - sa = sind (angle); - ca = cosd (angle); - - 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 - -endfunction