Mercurial > hg > octave-nkf
changeset 14574:9546bb28648c
New Function, shrinkfaces.m
* shrinkfaces.m: New File.
* scripts/plot/module.mk (plot_FCN_FILES): Add it to the list.
* NEWS: Mention shrinkfaces.m.
* plot.txi: Documen it.
* unimplemented.m (missing_functions): Remove shrinkfaces from the
list.
author | Martin Helm <martin@mhelm.de> |
---|---|
date | Thu, 19 Apr 2012 17:44:46 -0400 |
parents | 1c0f0e8f9a1b |
children | 2e23cd0a9e40 |
files | NEWS doc/interpreter/plot.txi scripts/help/unimplemented.m scripts/plot/module.mk scripts/plot/shrinkfaces.m |
diffstat | 5 files changed, 219 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/NEWS +++ b/NEWS @@ -63,7 +63,7 @@ colorcube splinefit lines tetramesh - rgbplot + rgbplot shrinkfaces ** Deprecated functions.
--- a/doc/interpreter/plot.txi +++ b/doc/interpreter/plot.txi @@ -363,6 +363,8 @@ @DOCSTRING(isocolors) +@DOCSTRING(shrinkfaces) + @DOCSTRING(diffuse) @DOCSTRING(specular)
--- a/scripts/help/unimplemented.m +++ b/scripts/help/unimplemented.m @@ -339,7 +339,6 @@ "serial", "setpixelposition", "showplottool", - "shrinkfaces", "smooth3", "snapnow", "sound",
--- a/scripts/plot/module.mk +++ b/scripts/plot/module.mk @@ -162,6 +162,7 @@ plot/semilogyerr.m \ plot/shading.m \ plot/shg.m \ + plot/shrinkfaces.m \ plot/slice.m \ plot/sombrero.m \ plot/specular.m \
new file mode 100644 --- /dev/null +++ b/scripts/plot/shrinkfaces.m @@ -0,0 +1,215 @@ +## Copyright (C) 2012 Martin Helm +## +## 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} {} shrinkfaces (@var{p}, @var{sf}) +## @deftypefnx {Function File} {@var{nfv} =} shrinkfaces (@var{p}, @var{sf}) +## @deftypefnx {Function File} {@var{nfv} =} shrinkfaces (@var{fv}, @var{sf}) +## @deftypefnx {Function File} {@var{nfv} =} shrinkfaces (@var{f}, @var{v}, @var{sf}) +## @deftypefnx {Function File} {[@var{nf}, @var{nv}] =} shrinkfaces (@dots{}) +## +## Reduce the faces area for a given patch, structure or explicit faces +## and points matrices by a scale factor @var{sf}. The structure +## @var{fv} must contain the fields 'faces' and 'vertices'. If the +## factor @var{sf} is omitted then a default of 0.3 is used. +## +## Given a patch handle as the first input argument and no output +## parameters, perform the shrinking of the patch faces in place and +## redraw the patch. +## +## If called with one output argument, return a structure with fields +## 'faces', 'vertices', and 'facevertexcdata' containing the data after +## shrinking which can then directly be used as an input argument for the +## @command{patch} function. +## +## Performing the shrinking on faces which are not convex can lead to +## undesired results. +## +## For example +## +## @example +## @group +## [phi r] = meshgrid (linspace (0, 1.5*pi, 16), linspace (1, 2, 4)); +## tri = delaunay (phi(:), r(:)); +## v = [r(:).*sin(phi(:)) r(:).*cos(phi(:))]; +## clf () +## p = patch ("Faces", tri, "Vertices", v, "FaceColor", "none"); +## fv = shrinkfaces (p); +## patch (fv) +## axis equal +## grid on +## @end group +## @end example +## +## @noindent +## draws a triangulated 3/4 circle and the corresponding shrinked +## version. +## @seealso{patch} +## @end deftypefn + +## Author: Martin Helm <martin@mhelm.de> + +function [nf, nv] = shrinkfaces (varargin) + + if (nargin < 1 || nargin > 3 || nargout > 2) + print_usage (); + endif + + sf = 0.3; + p = varargin{1}; + colors = []; + + if (ishandle (p) && nargin < 3) + faces = get (p, "Faces"); + vertices = get (p, "Vertices"); + colors = get (p, "FaceVertexCData"); + if (nargin == 2) + sf = varargin{2}; + endif + elseif (isstruct (p) && nargin < 3) + faces = p.faces; + vertices = p.vertices; + if (isfield (p, "facevertexcdata")) + colors = p.facevertexcdata; + endif + if (nargin == 2) + sf = varargin{2}; + endif + elseif (ismatrix (p) && nargin >= 2 && ismatrix (varargin{2})) + faces = p; + vertices = varargin{2}; + if (nargin == 3) + sf = varargin{3}; + endif + else + print_usage (); + endif + + if (! isscalar (sf) || sf <= 0) + error ("shrinkfaces: scale factor must be a positive scalar") + endif + + n = size (vertices, 2); + if (n < 2 || n > 3) + error ("shrinkfaces: only 2D and 3D patches are supported") + endif + + m = size (faces, 2); + if (m < 3) + error ("shrinkfaces: faces must consist of at least 3 vertices") + endif + + v = vertices(faces'(:), :); + if (isempty (colors) || size (colors, 1) == size (faces, 1)) + c = colors; + elseif (size (colors, 1) == size (vertices, 1)) + c = colors(faces'(:), :); + else + ## Discard inconsistent color data. + c = []; + endif + sv = size (v, 1); + ## we have to deal with a probably very large number of vertices, so + ## use sparse we use as midpoint (1/m, ..., 1/m) in generalized + ## barycentric coordinates. + midpoints = full (kron ( speye (sv / m), ones (m, m) / m) * sparse (v)); + v = sqrt (sf) * (v - midpoints) + midpoints; + f = reshape (1:sv, m, sv / m)'; + + switch (nargout) + case 0 + if (ishandle (p)) + set (p, "FaceVertexCData", [], "CData", []) # avoid exceptions + set (p, "Vertices", v, "Faces", f, "FaceVertexCData", c) + else + nf = struct ("faces", f, "vertices", v, "facevertexcdata", c); + endif + case 1 + nf = struct ("faces", f, "vertices", v, "facevertexcdata", c); + case 2 + nf = f; + nv = v; + endswitch + +endfunction + +%!demo +%! faces = [1 2 3; 1 3 4]; +%! vertices = [0 0; 1 0; 1 1; 0 1]; +%! clf () +%! patch ("Faces", faces, "Vertices", vertices, "FaceColor", "none") +%! fv = shrinkfaces (faces, vertices, 0.25); +%! patch (fv) +%! axis equal + +%!demo +%! faces = [1 2 3 4; 5 6 7 8]; +%! vertices = [0 0; 1 0; 2 1; 1 1; 2 0; 3 0; 4 1; 3.5 1]; +%! clf () +%! patch ("Faces", faces, "Vertices", vertices, "FaceColor", "none") +%! fv = shrinkfaces (faces, vertices, 0.25); +%! patch (fv) +%! axis equal +%! grid on + +%!demo +%! faces = [1 2 3 4]; +%! vertices = [-1 2; 0 0; 1 2; 0 1]; +%! clf () +%! patch ("Faces", faces, "Vertices", vertices, "FaceColor", "none") +%! fv = shrinkfaces (faces, vertices, 0.25); +%! patch (fv) +%! axis equal +%! grid on +%! title "faces which are not convex are clearly not allowed" + +%!demo +%! [phi r] = meshgrid (linspace (0, 1.5*pi, 16), linspace (1, 2, 4)); +%! tri = delaunay (phi(:), r(:)); +%! v = [r(:).*sin(phi(:)) r(:).*cos(phi(:))]; +%! clf () +%! p = patch ("Faces", tri, "Vertices", v, "FaceColor", "none"); +%! fv = shrinkfaces (p); +%! patch (fv) +%! axis equal +%! grid on + +%!demo +%! N = 10; # N intervals per axis +%! [x, y, z] = meshgrid (linspace (-4,4,N+1)); +%! val = x.^3 + y.^3 + z.^3; +%! fv = isosurface (x, y, z, val, 3, z); +%! +%! clf () +%! p = patch ("Faces", fv.faces, "Vertices", fv.vertices, "FaceVertexCData", ... +%! fv.facevertexcdata, "FaceColor", "interp", "EdgeColor", "black"); +%! axis equal +%! view (115, 30) +%! drawnow +%! shrinkfaces (p, 0.6); + +%!shared faces, vertices, nfv, nfv2 +%! faces = [1 2 3]; +%! vertices = [0 0 0; 1 0 0; 1 1 0]; +%! nfv = shrinkfaces (faces, vertices, 0.7); +%! nfv2 = shrinkfaces (nfv, 1/0.7); +%!assert (isfield (nfv, "faces")); +%!assert (isfield (nfv, "vertices")); +%!assert (size (nfv.faces), [1 3]); +%!assert (size (nfv.vertices), [3 3]); +%!assert (norm (nfv2.vertices - vertices), 0, 2*eps);