1######################################################################## 2## 3## Copyright (C) 2016-2021 The Octave Project Developers 4## 5## See the file COPYRIGHT.md in the top-level directory of this 6## distribution or <https://octave.org/copyright/>. 7## 8## This file is part of Octave. 9## 10## Octave is free software: you can redistribute it and/or modify it 11## under the terms of the GNU General Public License as published by 12## the Free Software Foundation, either version 3 of the License, or 13## (at your option) any later version. 14## 15## Octave is distributed in the hope that it will be useful, but 16## WITHOUT ANY WARRANTY; without even the implied warranty of 17## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18## GNU General Public License for more details. 19## 20## You should have received a copy of the GNU General Public License 21## along with Octave; see the file COPYING. If not, see 22## <https://www.gnu.org/licenses/>. 23## 24######################################################################## 25 26## -*- texinfo -*- 27## @deftypefn {} {} camroll (@var{theta}) 28## @deftypefnx {} {} camroll (@var{ax}, @var{theta}) 29## Roll the camera. 30## 31## Roll the camera clockwise by @var{theta} degrees. 32## For example, the following command will roll the camera by 33## 30 degrees clockwise (to the right); this will cause the scene 34## to appear to roll by 30 degrees to the left: 35## 36## @example 37## @group 38## @c doctest: +SKIP 39## peaks () 40## camroll (30) 41## @end group 42## @end example 43## 44## Roll the camera back: 45## 46## @example 47## @group 48## @c doctest: +SKIP 49## camroll (-30) 50## @end group 51## @end example 52## 53## The following command restores the default camera roll: 54## 55## @example 56## @group 57## @c doctest: +SKIP 58## camup ("auto") 59## @end group 60## @end example 61## 62## By default, these commands affect the current axis; alternatively, an axis 63## can be specified by the optional argument @var{ax}. 64## 65## @seealso{camzoom, camorbit, camlookat, camup} 66## @end deftypefn 67 68 69function camroll (varargin) 70 71 [hax, varargin, nargin] = __plt_get_axis_arg__ ("camroll", varargin{:}); 72 73 if (nargin != 1) 74 print_usage (); 75 endif 76 77 a = varargin{1}; 78 79 if (! (isnumeric (a) && isscalar (a) )) 80 print_usage (); 81 endif 82 83 if (isempty (hax)) 84 hax = gca (); 85 else 86 hax = hax(1); 87 endif 88 89 dar = get (hax, "dataaspectratio"); 90 91 view_ax = (camtarget (hax) - campos (hax)) ./ dar; 92 view_ax /= norm (view_ax); 93 ## orthogonalize the camup vector 94 up = camup (hax) ./ dar; 95 up = up - view_ax * dot (up, view_ax); 96 up /= norm (up); 97 98 ## rotate the modified camup vector around the view axis 99 up = num2cell (up); 100 [up{:}] = __rotate_around_axis__ (up{:}, a, view_ax, [0 0 0]); 101 up = [up{:}] .* dar; 102 camup (hax, up / norm (up)) 103 104endfunction 105 106 107%!demo 108%! clf; 109%! peaks (); 110%! camroll (30); 111%! title ("camroll() demo #1"); 112 113%!test 114%! hf = figure ("visible", "off"); 115%! unwind_protect 116%! sphere (10); 117%! campos ([10 0 0]); 118%! camroll (30); 119%! p = camup (); 120%! assert (p, [0 1/2 sqrt(3)/2], eps); 121%! unwind_protect_cleanup 122%! close (hf); 123%! end_unwind_protect 124 125## test rolling, then rolling back 126%!test 127%! hf = figure ("visible", "off"); 128%! unwind_protect 129%! hax = axes ("parent", hf); 130%! peaks (); 131%! p = camup (hax); 132%! assert (p, [0 0 1], eps); 133%! camroll (hax, 30); 134%! p = camup (hax); 135%! ## from Matlab R2017b 136%! q = [0.33969638129660373 0.02014238382998192 0.94031944194919104]; 137%! assert (p, q, 10*eps); 138%! camroll (hax, -30); 139%! ## Note: It does not go back to [0 0 1]: instead orthog to camera view: 140%! p = camup (hax); 141%! ## The "cameraupvector" is now perpendicular to the viewing vector 142%! dar = get (hax, "dataaspectratio"); 143%! ## FIXME: looser tolerance needed on i386 for assert below 144%! assert (dot (p./dar, (camtarget (hax) - campos (hax))./dar), 0, 32*eps); 145%! ## from Matlab R2017b 146%! q = [0.14033891839365262 0.18289323924769943 0.97306477226420207]; 147%! assert (p, q, 10*eps); 148%! unwind_protect_cleanup 149%! close (hf); 150%! end_unwind_protect 151 152## test ax input by creating another axis 153%!test 154%! hf = figure ("visible", "off"); 155%! unwind_protect 156%! hax1 = subplot (1, 2, 1); 157%! sphere (hax1); 158%! hax2 = subplot (1, 2, 2); 159%! sphere (hax2); 160%! camroll (hax1, 30); 161%! x = camup (hax1); 162%! y = camup (hax2); 163%! ## from Matlab R2016a 164%! assert (x, [0.66027810132845211 0.03915135893036471 0.75000000000000022], 165%! -1e-5); 166%! assert (y, [0 0 1]); 167%! unwind_protect_cleanup 168%! close (hf); 169%! end_unwind_protect 170 171## Test input validation 172%!error <Invalid call> camroll (1, 2, 3) 173%!error <Invalid call> camroll ("mod") 174%!error <Invalid call> camroll (1, [1 2]) 175