Mercurial > octave
changeset 23255:aaf91b4f48e4
hgtransform.m: New function (bug #50466).
* NEWS: Announce new function.
* scripts/plot/util/hgtransform.m: New function.
* scripts/plot/util/module.mk: Add to build system.
* plot.txi: Add new section "Transform Groups" to Advanced
Plotting to contain docstring.
* octave.texi: Add new section "Transform Groups" to
Table of Contents.
* __unimplemented__.m: Remove from unimplemented list.
author | Rik <rik@octave.org> |
---|---|
date | Wed, 08 Mar 2017 15:00:35 -0800 |
parents | 7eeb2c561a1a |
children | 99ee4dd83ceb |
files | NEWS doc/interpreter/octave.texi doc/interpreter/plot.txi scripts/help/__unimplemented__.m scripts/plot/util/hgtransform.m scripts/plot/util/module.mk |
diffstat | 6 files changed, 188 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/NEWS Tue Mar 07 08:22:16 2017 -0800 +++ b/NEWS Wed Mar 08 15:00:35 2017 -0800 @@ -21,6 +21,7 @@ ** Other new functions added in 4.4: gsvd + hgtransform ** Deprecated functions.
--- a/doc/interpreter/octave.texi Tue Mar 07 08:22:16 2017 -0800 +++ b/doc/interpreter/octave.texi Wed Mar 08 15:00:35 2017 -0800 @@ -579,6 +579,7 @@ * Callbacks:: * Application-defined Data:: * Object Groups:: +* Transform Groups:: * Graphics Toolkits:: Object Groups
--- a/doc/interpreter/plot.txi Tue Mar 07 08:22:16 2017 -0800 +++ b/doc/interpreter/plot.txi Wed Mar 08 15:00:35 2017 -0800 @@ -1705,6 +1705,7 @@ * Callbacks:: * Application-defined Data:: * Object Groups:: +* Transform Groups:: * Graphics Toolkits:: @end menu @@ -2525,6 +2526,16 @@ Data source variables. @end table +@node Transform Groups +@subsection Transform Groups +@cindex transform groups + +@c FIXME: Need to add documentation on transforms. + +@DOCSTRING(hgtransform) + +@c @DOCSTRING(makehgtform) + @node Graphics Toolkits @subsection Graphics Toolkits @cindex graphics toolkits
--- a/scripts/help/__unimplemented__.m Tue Mar 07 08:22:16 2017 -0800 +++ b/scripts/help/__unimplemented__.m Wed Mar 08 15:00:35 2017 -0800 @@ -680,7 +680,6 @@ "height", "hgexport", "hgsetget", - "hgtransform", "histcounts", "histcounts2", "histogram",
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/plot/util/hgtransform.m Wed Mar 08 15:00:35 2017 -0800 @@ -0,0 +1,174 @@ +## Copyright (C) 2017 Rik Wehbring +## +## 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{h} =} {} hgtransform () +## @deftypefnx {@var{h} =} {} hgtransform (@var{property}, @var{value}, @dots{}) +## @deftypefnx {@var{h} =} {} hgtransform (@var{hax}, @dots{}) +## +## Create a graphics transform object. +## +## FIXME: Need to write documentation. +## FIXME: Add 'makehgtform' to seealso list when it is implemented. +## @seealso{hggroup} +## @end deftypefn + + +## FIXME: hgtransform should be a C++ graphics object, not an m-file. +## For the moment (3/7/17), it is quicker to implement something in +## an m-file. But, this approach requires double the memory (original +## and transformed data), and a system of listeners and callbacks. +## In OpenGL toolkits it should be possible to simply insert a transform +## somewhere in gl-render.cc to have this done on the fly. + +function h = hgtransform (varargin) + + [hax, varargin] = __plt_get_axis_arg__ ("hgtransform", varargin{:}); + + if (isempty (hax)) + hax = gca (); + endif + + htmp = hggroup (hax); + + addproperty ("matrix", htmp, "data", eye (4)); + addproperty ("__orig_data__", htmp, "any", struct ("h", {})); + if (! isempty (varargin)) + set (htmp, varargin{:}); + endif + addlistener (htmp, "matrix", @matrix_cb); + addlistener (htmp, "children", @children_cb); + + if (nargout > 0) + h = htmp; + endif + +endfunction + +function matrix_cb (hgt, ~) + + M = get (hgt, "matrix"); + ## FIXME: Need better input validation on transform matrix M. + ## Disallow shear, perspective transforms. + if (! isreal (M) || ! ismatrix (M) || rows (M) != 4 || columns (M) != 4) + error ("hgtransform: transform must be 4x4 real matrix"); + endif + + hkids = get (hgt, "children"); + xform_data (hgt, hkids); + +endfunction + +function xform_data (hgt, hlist) + + M = get (hgt, "matrix"); + orig_data = get (hgt, "__orig_data__"); + + for hk = hlist.' + + idx = find (hk == [orig_data.h]); + if (! idx) + warning ("hgtransform: original data not found for %f", hk); + continue; + endif + + xd = double (orig_data(idx).xdata); + xsz = size (xd); + + yd = double (orig_data(idx).ydata); + ysz = size (yd); + + zd = double (orig_data(idx).zdata); + zsz = size (zd); + z_empty = isempty (zd); + + if (isempty (zd)) + ## Common case of 2-D data. + zd = zeros (1, numel (xd)); + elseif (isvector (xd) && isvector (yd)) + ## Handle surface data which may be a vector/matrix combination + if (isvector (zd)) + ## Do nothing. All data will be forced to row vectors below + elseif (length (xd) == rows (zd) && length (yd) == columns (zd)) + [xd, yd] = meshgrid (xd, yd); + xsz = size (xd); + ysz = size (yd); + endif + endif + + ## Force row vectors for later concatenation + xd = xd(:).'; + yd = yd(:).'; + zd = zd(:).'; + + ## FIXME: To minimize memory, better to construct data matrix in-place? + data = [xd; yd; zd; ones(1, columns(xd))]; + tol = 2 * max (eps (data(1:3,:))); + data = M * data; + ## Need to trim or rotations which produce values near 0 will be strange. + data(abs (data) < tol) = 0; + + set (hk, "xdata", reshape (data(1,:), xsz)); + set (hk, "ydata", reshape (data(2,:), ysz)); + if (! z_empty) + set (hk, "zdata", reshape (data(3,:), zsz)); + endif + endfor + +endfunction + +function children_cb (hgt, ~) + + hkids = get (hgt, "children"); + orig_data = get (hgt, "__orig_data__"); + hlist = [orig_data.h]; + + ## Delete any children that have been removed + hdel = setdiff (hlist, hkids); + if (! isempty (hdel)) + for hk = hdel.' + idx = find (hk == hlist); + if (ishghandle (hk)) + ## child was re-parented to something else, restore data + set (hk, "xdata", orig_data(idx).xdata); + set (hk, "ydata", orig_data(idx).ydata); + set (hk, "zdata", orig_data(idx).zdata); + endif + endfor + orig_data = orig_data(hlist != hdel); + hlist = hlist(hlist != hdel); + endif + + ## Add new children + hnew = setdiff (hkids, hlist); + for hk = hnew.' + orig_data(end+1).h = hk; + orig_data(end).xdata = get (hk, "xdata"); + orig_data(end).ydata = get (hk, "ydata"); + orig_data(end).zdata = get (hk, "zdata"); + endfor + + set (hgt, "__orig_data__", orig_data); + + ## Update data of new children only + xform_data (hgt, hnew); + +endfunction + + +## Need BIST tests here
--- a/scripts/plot/util/module.mk Tue Mar 07 08:22:16 2017 -0800 +++ b/scripts/plot/util/module.mk Wed Mar 08 15:00:35 2017 -0800 @@ -55,6 +55,7 @@ scripts/plot/util/hggroup.m \ scripts/plot/util/hgload.m \ scripts/plot/util/hgsave.m \ + scripts/plot/util/hgtransform.m \ scripts/plot/util/hold.m \ scripts/plot/util/isaxes.m \ scripts/plot/util/isfigure.m \