# HG changeset patch
# User Martin Helm
# Date 1334410972 -7200
# Node ID f91b72aefe48918ca85bd7129836a8741b78f57f
# Parent 26b2983a8acd6512c10a9ef92a139e36f059351e
New Function, shrinkfaces.m
* shrinkfaces.m: New File.
* scripts/plot/module.mk: Add new file.
* NEWS: added to list of new functions
* doc/interpreter/plot.txi: added DOCSTRING near related isosurface
* scripts/help/unimplemented.m: removed shrinkfaces
diff -r 75f751023a42 -r a2a07d621813 NEWS
--- a/NEWS Thu Apr 19 21:20:45 2012 +0200
+++ b/NEWS Thu Apr 19 22:32:44 2012 +0200
@@ -63,7 +63,7 @@
colorcube splinefit
lines tetramesh
- rgbplot
+ rgbplot shrinkfaces
** Deprecated functions.
diff -r 75f751023a42 -r a2a07d621813 doc/interpreter/plot.txi
--- a/doc/interpreter/plot.txi Thu Apr 19 21:20:45 2012 +0200
+++ b/doc/interpreter/plot.txi Thu Apr 19 22:32:44 2012 +0200
@@ -363,6 +363,8 @@
@DOCSTRING(isocolors)
address@hidden(shrinkfaces)
+
@DOCSTRING(diffuse)
@DOCSTRING(specular)
diff -r 75f751023a42 -r a2a07d621813 scripts/help/unimplemented.m
--- a/scripts/help/unimplemented.m Thu Apr 19 21:20:45 2012 +0200
+++ b/scripts/help/unimplemented.m Thu Apr 19 22:32:44 2012 +0200
@@ -339,7 +339,6 @@
"serial",
"setpixelposition",
"showplottool",
- "shrinkfaces",
"smooth3",
"snapnow",
"sound",
diff -r 75f751023a42 -r a2a07d621813 scripts/plot/module.mk
--- a/scripts/plot/module.mk Fri Apr 13 14:07:45 2012 -0400
+++ b/scripts/plot/module.mk Sat Apr 14 15:42:52 2012 +0200
@@ -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 \
diff -r 75f751023a42 -r a2a07d621813 scripts/plot/shrinkfaces.m
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/shrinkfaces.m Sat Apr 14 15:42:52 2012 +0200
@@ -0,0 +1,228 @@
+## 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
+## .
+
+## -*- texinfo -*-
+## @deftypefn {Function File} shrinkfaces (@var{p})
+## @deftypefnx {Function File} shrinkfaces (@var{p}, @var{sf})
+## @deftypefnx {Function File} address@hidden =} shrinkfaces (@var{p}, @var{sf})
+## @deftypefnx {Function File} address@hidden =} shrinkfaces (@var{fv}, @var{sf})
+## @deftypefnx {Function File} address@hidden =} shrinkfaces (@var{f}, @var{v}, @var{sf})
+## @deftypefnx {Function File} address@hidden, @var{nv}] =} = shrinkfaces (@dots{})
+##
+## @command{shrinkfaces} reduces the faces area for a given patch, structure or
+## explicit faces and points matrices by a scale factor @var{sf}. The structure
+## @var{fv} needs to contain the fields 'faces' and 'vertices'.
+## If the factor @var{sf} is omited then a default of 0.3 is used.
+##
+## Calling the function without output parameters and a patch handle as first
+## input argument performs the shrinking of the patch faces in place and redraws
+## the patch.
+##
+## Called with one output argument it returns a structure with fields
+## 'faces', 'vertices' and 'facevertexcdata' containing the data after shrinking
+## which can then directly be used as 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
+## will draw a triangulated 3/4 circle and the corresponding shrinked version.
+##
+## The command
+##
+## @example
+## @group
+## demo shrinkfaces
+## @end group
+## @end example
+##
+## @noindent
+## shows further examples how to use it.
+##
+## @seealso{patch}
+## @end deftypefn
+
+## Author: Martin Helm
+
+function [nf,nv] = shrinkfaces (varargin)
+
+ # begin: check input
+ 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
+ # end: check input
+
+ 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
+ c = []; # inconsistent color data, let's discard it
+ 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);