Mercurial > octave
changeset 24137:60e4e324a525
Fix failing xtest in camlookat.m (patch #9049).
* camlookat.m: Use perspective projection. Take dataaspectratio into account.
Add more input checks.
* NEWS: Announce new cam* functions.
author | Markus Mützel <markus.muetzel@gmx.de> |
---|---|
date | Wed, 11 Oct 2017 21:21:28 +0200 |
parents | 141e6e16d900 |
children | e201dc969e24 |
files | NEWS scripts/plot/appearance/camlookat.m |
diffstat | 2 files changed, 71 insertions(+), 22 deletions(-) [+] |
line wrap: on
line diff
--- a/NEWS Thu Jul 14 22:26:00 2016 -0700 +++ b/NEWS Wed Oct 11 21:21:28 2017 +0200 @@ -61,6 +61,14 @@ ** Other new functions added in 4.4: + camlookat + camorbit + campos + camroll + camtarget + camup + camva + camzoom corrcoef getframe gsvd
--- a/scripts/plot/appearance/camlookat.m Thu Jul 14 22:26:00 2016 -0700 +++ b/scripts/plot/appearance/camlookat.m Wed Oct 11 21:21:28 2017 +0200 @@ -52,10 +52,20 @@ endif if (nargin == 0) - hh = get (gca (), "children"); + hax = gca (); + hh = get (hax, "children"); elseif (nargin == 1) if (isaxes (hh)) - hh = get (hh, "children"); + hax = hh; + hh = get (hax, "children"); + elseif (all (ishandle (hh))) + hax = ancestor (hh, "axes"); + if numel (hax) > 1 + hax = unique ([hax{:}]); + endif + if (numel (hax) > 1) + error ("camlookat: HANDLE_LIST must be children of the same axes.") + endif endif endif @@ -89,33 +99,52 @@ endif endfor - ## current view direction and projection operator - curdir = camtarget () - campos (); + dar = daspect (hax); + + ## current view direction + curdir = (camtarget () - campos ()) ./ dar; curdir /= norm (curdir); - P = eye (3) - (curdir.' * curdir); ## target to middle of bounding box - mid = [x0+x1; y0+y1; z0+z1]/2; + mid = [x0+x1, y0+y1, z0+z1]/2 ./ dar; ## vertices of the bounding box - bb = [x0 x0 x0 x0 x1 x1 x1 x1; - y0 y0 y1 y1 y0 y0 y1 y1; - z0 z1 z0 z1 z0 z1 z0 z1]; - - ## project bounding box onto view plane - Pbb = P*(bb - mid) + mid; + bb = [x0 y0 z0; + x0 y0 z1; + x0 y1 z0; + x0 y1 z1; + x1 y0 z0; + x1 y0 z1; + x1 y1 z0; + x1 y1 z1] ./ dar; + + ## Find corner of bounding box with maximum opening angle. + ## Make sure temporary pov is well outside boundary of bounding box. + bb_diag = norm ([x0-x1, y0-y1, z0-z1] ./ dar); + cp_test = mid - 2*bb_diag*curdir; + bb_cp = bb - cp_test; + bb_cp ./= norm (bb_cp, 2, "rows"); + aperture = norm (curdir .* bb_cp, 2, "rows"); + max_corner = find (aperture == max (aperture), 1, "first"); + + ## projection of corner on line of sight + sz = curdir * (bb(max_corner,:) - mid)'; + bb_proj = mid + sz * curdir; - ## estimate size based on projected bb, choose distance for campos - ## (XXX: only matches Matlab to about 1 digit, see xtests) - sz = max (norm (Pbb - mid, 2, "cols")); - dist = 2*sz / tand (camva ()); + ## Calculate distance for which that corner appears at camva/2 + dist = norm (bb(max_corner,:) - bb_proj) / tand (camva () / 2); - ## avoid auto-adjusting - camva ("manual") + ## Is bb_proj in front of or behind mid? + if (curdir * (mid - bb_proj)' > 0) + cp = bb_proj - dist * curdir; + else + cp = 2*mid - bb_proj - dist * curdir; + endif - camtarget (mid.') - - campos (mid.' - dist*curdir) + ## set camera properties + camva ("manual") # avoid auto-adjusting + camtarget (mid .* dar) + campos (cp .* dar) endfunction @@ -223,7 +252,7 @@ %! end_unwind_protect ## compare to matlab2014a output -%!xtest +%!test %! hf = figure ("visible", "off"); %! unwind_protect %! [x, y, z] = peaks (); @@ -253,3 +282,15 @@ ## Test input validation %!error <Invalid call> camlookat (1, 2) %!error <must be handle> camlookat ("a") +%!error <children of the same axes> +%! hf = figure ("visible", "off"); +%! unwind_protect +%! [x, y, z] = sphere (); +%! hax1 = subplot (1, 2, 1); +%! hs1 = surf (hax1, x, y, z); +%! hax2 = subplot (1, 2, 2); +%! hs2 = surf (hax2, x, y, z); +%! camlookat ([hs1 hs2]); +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect