# HG changeset patch
# User Markus Mützel <markus.muetzel@gmx.de>
# Date 1470843891 -7200
#      Wed Aug 10 17:44:51 2016 +0200
# Node ID eb68e4e938e6486c5d8d6d9374a2c8fe8a177285
# Parent  60986498af9e1c03d4363f0d3c41feea1510aaaa
Add function "isocaps" (patch #8872)

* scripts/plot/draw/isocaps.m: New function.

* scripts/plot/draw/isosurface.m: Add "isocaps" to @seealso. Ignore
empty strings in input.

* scripts/plot/draw/module.mk: Add isocaps.m to build system.

* NEWS: Announce new functions.

* __unimplemented__.m: Remove "isocaps" from list.

* doc/interpreter/plot.txi: Add to documentation.

diff -r 60986498af9e -r eb68e4e938e6 NEWS
--- a/NEWS	Wed Aug 10 03:56:38 2016 +0100
+++ b/NEWS	Wed Aug 10 17:44:51 2016 +0200
@@ -116,6 +116,8 @@
       gsvd
       hash
       im2double
+      isocaps
+      lighting
       localfunctions
       material
       normest1
@@ -127,6 +129,7 @@
       rad2deg
       reducepatch
       reducevolume
+      smooth3
       uibuttongroup
 
  ** Deprecated functions.
diff -r 60986498af9e -r eb68e4e938e6 doc/interpreter/plot.txi
--- a/doc/interpreter/plot.txi	Wed Aug 10 03:56:38 2016 +0100
+++ b/doc/interpreter/plot.txi	Wed Aug 10 17:44:51 2016 +0200
@@ -382,6 +382,8 @@
 
 @DOCSTRING(isonormals)
 
+@DOCSTRING(isocaps)
+
 @DOCSTRING(isocolors)
 
 @DOCSTRING(smooth3)
diff -r 60986498af9e -r eb68e4e938e6 scripts/help/__unimplemented__.m
--- a/scripts/help/__unimplemented__.m	Wed Aug 10 03:56:38 2016 +0100
+++ b/scripts/help/__unimplemented__.m	Wed Aug 10 17:44:51 2016 +0200
@@ -687,7 +687,6 @@
   "isenum",
   "isKey",
   "ismissing",
-  "isocaps",
   "isordinal",
   "isprotected",
   "isstudent",
diff -r 60986498af9e -r eb68e4e938e6 scripts/plot/draw/isocaps.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/draw/isocaps.m	Wed Aug 10 17:44:51 2016 +0200
@@ -0,0 +1,544 @@
+## Copyright (C) 2016 Markus Mützel
+##
+## 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{fvc_struct} =} isocaps (@var{val}, @var{iso})
+## @deftypefnx {} {@var{fvc_struct} =} isocaps (@var{val})
+## @deftypefnx {} {@var{fvc_struct} =} isocaps (@var{x}, @var{y}, @var{z}, @var{val}, @var{iso})
+## @deftypefnx {} {@var{fvc_struct} =} isocaps (@var{x}, @var{y}, @var{z}, @var{val})
+## @deftypefnx {} {@var{fvc_struct} =} isocaps (@dots{}, @var{which_caps})
+## @deftypefnx {} {@var{fvc_struct} =} isocaps (@dots{}, @var{which_plane})
+## @deftypefnx {} {@var{fvc_struct} =} isocaps (@dots{}, @qcode{"verbose"})
+## @deftypefnx {} {[@var{faces}, @var{vertices}, @var{cdata}] =} isocaps (@dots{})
+## @deftypefnx {} {} isocaps (@dots{})
+##
+## Create end-caps for isosurfaces of 3d data
+##
+## This function places caps at open ends of isosurfaces.
+##
+## @var{val} must be a 3-dimensional matrix. The end-caps for this data are
+## calculated for the isosurface at value @var{iso}.  If @var{iso} is omitted
+## or empty, a "good" value for an isosurface is determined from the histogram
+## of @var{val}.
+##
+## If called with one output argument the results are returned in a structure
+## with the fields: @code{vertices}, @code{faces} and @code{facevertexcdata}.
+##
+## Optionally, @var{x}, @var{y} and @var{z} can be supplied to represent the
+## set of coordinates of @var{val}.  They can either be matrices of the same
+## size as @var{val} or vectors with sizes according to the dimensions of
+## @var{val} in which case they are expanded to matrices (see:
+## @command{meshgrid}).
+##
+## If @command{isocaps} is called without passing @var{x}, @var{y} and @var{z}
+## or they are empty, they are assumed to match the respective indices of
+## @var{val}.
+##
+## The optional parameter @var{which_caps} can have one of the following
+## string values to define how the data should be enclosed:
+## @table @asis
+## @item "above", "a" (default)
+## for end-caps that enclose the data above @var{iso}.
+## @item "below", "b"
+## for end-caps that enclose the data below @var{iso}.
+## @end table
+##
+## The optional parameter @var{which_plane} can have one of the following string
+## values to define in which plane the cap should be drawn:
+## @table @asis
+## @item "xmax"
+## for the end-caps at the upper x-plain of the data.
+## @item "xmin"
+## for the end-caps at the lower x-plain of the data.
+## @item "ymax"
+## for the end-caps at the upper y-plain of the data.
+## @item "ymin"
+## for the end-caps at the lower y-plain of the data.
+## @item "zmax"
+## for the end-caps at the upper z-plain of the data.
+## @item "zmin"
+## for the end-caps at the lower z-plain of the data.
+## @item "all" (default)
+## for all of these end-caps.
+## @end table
+##
+## The optional parameter @qcode{"verbose"} is passed to isosurface.
+##
+## If called with two or three output arguments, the data for faces @var{faces},
+## vertices @var{vertices} and the color data @var{cdata} are returned in
+## separate arrays instead of a single structure.
+##
+## If called with no output arguments, the results are drawn in the current
+## figure with the @command{patch} command.
+##
+## @seealso{isosurface, isonormals, patch}
+## @end deftypefn
+
+## Author: mmuetzel
+
+function varargout = isocaps (varargin)
+
+  if (nargin < 1 || nargin > 8 || nargout > 3)
+    print_usage ();
+  endif
+
+  faces = vertices = caps_cdata = [];
+
+  [x, y, z, data, iso, which_caps, which_plane, verbose] = ...
+                                     __get_check_isocaps_args__ (varargin{:});
+
+  ## select type of cap (above or below iso value)
+  data_min = min([data(:); iso]);
+  data_max = max([data(:); iso]);
+  switch (tolower (which_caps))
+    case {"a", "above"}
+      pad_val = data_min - 1;
+    case {"b", "below"}
+      pad_val = data_max + 1;
+    otherwise
+      error ("isocaps: internal error.")
+  endswitch
+
+  ## create patches for caps
+  if (strcmpi (which_plane, "all"))
+    ## get patches for all planes
+    [f_xmin, v_xmin] = __get_isocaps_patches__ (x, y, z, data, iso, ...
+                                                pad_val, "xmin", verbose);
+    [f_xmax, v_xmax] = __get_isocaps_patches__ (x, y, z, data, iso, ...
+                                                pad_val, "xmax", verbose);
+    [f_ymin, v_ymin] = __get_isocaps_patches__ (x, y, z, data, iso, ...
+                                                pad_val, "ymin", verbose);
+    [f_ymax, v_ymax] = __get_isocaps_patches__ (x, y, z, data, iso, ...
+                                                pad_val, "ymax", verbose);
+    [f_zmin, v_zmin] = __get_isocaps_patches__ (x, y, z, data, iso, ...
+                                                pad_val, "zmin", verbose);
+    [f_zmax, v_zmax] = __get_isocaps_patches__ (x, y, z, data, iso, ...
+                                                pad_val, "zmax", verbose);
+    vertices = [v_xmin; v_xmax; v_ymin; v_ymax; v_zmin; v_zmax];
+    v_nums = [rows(v_xmin), rows(v_xmax), ...
+              rows(v_ymin), rows(v_ymax), rows(v_zmin)];
+    f_offset = cumsum (v_nums);
+    faces = [f_xmin; f_xmax + f_offset(1); ...
+             f_ymin + f_offset(2); f_ymax + f_offset(3); ...
+             f_zmin + f_offset(4); f_zmax + f_offset(5)];
+  else  # only one plain specified
+    [faces, vertices] = __get_isocaps_patches__ (x, y, z, data, iso, ...
+                                          pad_val, which_plane, verbose);
+  endif
+
+  if (! isempty (vertices))
+    ## interpolate data at the vertices for coloring of the end-cap
+    caps_cdata = interp3 (x, y, z, data, ...
+                          vertices(:,1), vertices(:,2), vertices(:,3))';
+  endif
+
+  switch nargout
+    case 0
+      hp = patch ("Faces", faces, "Vertices", vertices, ...
+                  "FaceVertexCData", caps_cdata, ...
+                  "FaceColor", "interp", "EdgeColor", "none");
+
+    case 1
+      vfc.vertices = vertices;
+      vfc.faces = faces;
+      vfc.facevertexcdata = caps_cdata;
+      varargout = {vfc};
+
+    otherwise
+      varargout{1} = faces;
+      varargout{2} = vertices;
+      varargout{3} = caps_cdata;
+
+  endswitch
+
+endfunction
+
+function [x, y, z, data, iso, which_caps, which_plane, verbose] = ...
+                                  __get_check_isocaps_args__ (varargin)
+## get arguments from input and check values
+
+  x = [];
+  y = [];
+  z = [];
+  data = [];
+  iso = [];
+
+  ## default values
+  which_caps = "above";
+  which_plane = "all";
+  verbose = "";
+
+  num_string_inputs = 0;
+  for (i_arg = nargin:-1:nargin-2)
+    ## check whether last maximum 3 input arguments are strings
+    ## and assign parameters
+    if (! ischar (varargin{i_arg}) || i_arg < 1)
+      ## string arguments must be at the end
+      break
+    end
+    switch (lower (varargin{i_arg}))
+      case {"v", "verbose"}
+        verbose = "verbose";
+        num_string_inputs++;
+
+      case {"all", "xmin", "xmax", "ymin", "ymax", "zmin", "zmax"}
+        which_plane = lower (varargin{i_arg});
+        num_string_inputs++;
+
+      case {"above", "a", "below", "b"}
+        which_caps = lower (varargin{i_arg});
+        num_string_inputs++;
+
+      otherwise
+        error ("isocaps: parameter '%s' not supported", varargin{i_arg})
+
+    endswitch
+  endfor
+
+  ## assign arguments
+  switch (nargin - num_string_inputs)
+    case 1  # isocaps (val, ...)
+      data = varargin{1};
+
+    case 2  # isocaps (val, iso, ...)
+      data = varargin{1};
+      iso = varargin{2};
+
+    case 4  # isocaps (x, y, z, val, ...)
+      x = varargin{1};
+      y = varargin{2};
+      z = varargin{3};
+      data = varargin{4};
+
+    case 5  # isocaps (x, y, z, val, iso, ...)
+      x = varargin{1};
+      y = varargin{2};
+      z = varargin{3};
+      data = varargin{4};
+      iso = varargin{5};
+
+    otherwise
+      error ("isocaps: incorrect number of input arguments")
+
+  endswitch
+
+  ## check dimensions of data
+  data_size = size (data);
+  if (ndims (data) != 3 || any (data_size(1:3) < 2))
+    error ("isocaps: VAL must be a non-singleton 3-dimensional matrix");
+  endif
+
+  if (isempty (x))
+    x = 1:data_size(2);
+  endif
+  if (isempty (y))
+    y = 1:data_size(1);
+  endif
+  if (isempty (z))
+    z = 1:data_size(3);
+  endif
+
+  ## check x
+  if (isvector (x) && length (x) == data_size(2))
+    x = repmat (x(:)', [data_size(1) 1 data_size(3)]);
+  elseif (! size_equal (data, x))
+    error ("isocaps: X must match the size of VAL");
+  endif
+
+  ## check y
+  if (isvector (y) && length (y) == data_size(1))
+    y = repmat (y(:), [1 data_size(2) data_size(3)]);
+  elseif (! size_equal (data, y))
+    error ("isocaps: Y must match the size of VAL");
+  endif
+
+  ## check z
+  if (isvector (z) && length (z) == data_size(3))
+    z = repmat (reshape (z(:), [1 1 length(z)]), ...
+                [data_size(1) data_size(2) 1]);
+  elseif (! size_equal (data, z))
+    error ("isocaps: Z must match the size of VAL");
+  endif
+
+  ## check iso
+  if (isempty (iso))
+    ## calculate "good" iso value from data
+    iso = __calc_isovalue_from_data__ (data);
+  endif
+
+  if (! isscalar (iso) || ! isnumeric (iso))
+    error ("isocaps: ISO must be a scalar number")
+  endif
+
+endfunction
+
+function [faces, vertices] = __get_isocaps_patches__ (x, y, z, data, iso, ...
+                                                      pad_val, which_plane, ...
+                                                      verbose)
+## calculate patches for end-caps
+
+  data_size = size (data);
+  is_lower_cap = strcmp (which_plane(2:end), "min");
+  switch (lower (which_plane(1)))
+    case "y"
+      coor = 2;
+      capdata = zeros (2, data_size(2), data_size(3));
+      if (is_lower_cap)
+        cap_idx = 1;
+      else
+        cap_idx = data_size(1);
+      endif
+      coor_val = y(cap_idx,1,1);
+      cap_data(2,:,:) = data(cap_idx,:,:);
+      cap_data(1,:,:) = pad_val;
+
+    case "x"
+      coor = 1;
+      cap_data = zeros(data_size(1), 2, data_size(3));
+      if (is_lower_cap)
+        cap_idx = 1;
+      else
+        cap_idx = data_size(2);
+      endif
+      coor_val = x(1,cap_idx,1);
+      cap_data(:,2,:) = data(:,cap_idx,:);
+      cap_data(:,1,:) = pad_val;
+
+    case "z"
+      coor = 3;
+      cap_data = zeros(data_size(1), data_size(2), 2);
+      if (is_lower_cap)
+        cap_idx = 1;
+      else
+        cap_idx = data_size(3);
+      endif
+      coor_val = z(1,1,cap_idx);
+      cap_data(:,:,2) = data(:,:,cap_idx);
+      cap_data(:,:,1) = pad_val;
+
+    otherwise
+      error ("isocaps: internal error.")
+
+  endswitch
+
+  n_cap = size (cap_data);
+  x_iso = x(1:n_cap(1),1:n_cap(2),1:n_cap(3));
+  y_iso = y(1:n_cap(1),1:n_cap(2),1:n_cap(3));
+  z_iso = z(1:n_cap(1),1:n_cap(2),1:n_cap(3));
+
+  [faces, vertices] = isosurface (x_iso, y_iso, z_iso, cap_data, iso, verbose);
+
+  if (! isempty (vertices))
+    vertices(:,coor) = coor_val;
+  endif
+
+endfunction
+
+%!demo
+%! iso = .4;
+%! lin = linspace (0, 1.2, 15);
+%! [x, y, z] = meshgrid (lin, lin, lin);
+%! val = abs ((x-.45).^2 + (y-.55).^2 + (z-.8).^2);
+%! hf = clf;
+%! ha = axes;
+%! view (3)
+%! fvc_iso = isosurface (x, y, z, val, iso);
+%! cmap = get (hf, "Colormap");
+%! p_iso = patch (fvc_iso, "FaceLighting", "gouraud", ...
+%!                "FaceColor", cmap(end,:), "EdgeColor", "none");
+%! isonormals (x, y, z, val, p_iso)
+%! fvc_xmin = isocaps (x, y, z, val, iso, "xmin", "b");
+%! patch (fvc_xmin, "FaceColor", "interp", "EdgeColor", "none", ...
+%!        "FaceLighting", "gouraud", ...
+%!        "VertexNormals", repmat([-1 0 0], rows (fvc_xmin.vertices), 1));
+%! fvc_ymin = isocaps (x, y, z, val, iso, "ymin", "b");
+%! patch (fvc_ymin, "FaceColor", "interp", "EdgeColor", "none", ...
+%!        "FaceLighting", "gouraud", ...
+%!        "VertexNormals", repmat([0 -1 0], rows (fvc_ymin.vertices), 1));
+%! fvc_zmax = isocaps (x, y, z, val, iso, "zmax", "b");
+%! patch (fvc_zmax, "FaceColor", "interp", "EdgeColor", "none", ...
+%!        "FaceLighting", "gouraud", ...
+%!        "VertexNormals", repmat([0 -1 0], rows (fvc_zmax.vertices), 1));
+%! axis equal
+%! light ();
+
+
+%!demo
+%! val = smooth3 (rand (6, 8, 4));
+%! iso = .5;
+%! x = 1:3:22; y = -14:5:11; z = linspace (16, 18, 4);
+%! [xx, yy, zz] = meshgrid (x, y, z);
+%! clf; 
+%% two arguments, no output
+%! subplot (2, 2, 1); isocaps (val, iso); view (3)
+%% five arguments, no output (x, y, z are vectors)
+%! subplot (2, 2, 2); isocaps (x, y, z, val, iso); view (3)
+%% five arguments, no output (x, y, z are matrices)
+%! subplot (2, 2, 3); isocaps (xx, yy, zz, val, iso); view (3)
+%% five arguments, no output (mixed x, y, z)
+%! subplot (2, 2, 4); isocaps (x, yy, z, val, iso); view (3)
+%! annotation("textbox", [0.1 0.9 0.9 0.1], ...
+%!    "String", ["Apart from the first plot having a different scale, " ...
+%!               "all four plots must look the same."], ...
+%!    "HorizontalAlignment", "left", ...
+%!    "FontSize", 12);
+
+%!shared x, y, z, xx, yy, zz, val, iso
+%! val = rand (6, 8, 4);
+%! iso = .5;
+%! x = 1:3:22; y = -14:5:11; z = linspace (16, 18, 4);
+%! [xx, yy, zz] = meshgrid (x, y, z);
+
+## check results for differently shaped input coordinates
+%!test
+%! fvc_vectors = isocaps (x, y, z, val, iso);
+%! fvc_matrices = isocaps (xx, yy, zz, val, iso);
+%! fvc_mixed = isocaps (xx, y, zz, val, iso);
+%! assert (fvc_vectors, fvc_matrices);
+%! assert (fvc_vectors, fvc_mixed);
+
+## two arguments, one output
+%!test
+%! fvc = isocaps (val, iso);
+%! assert (isfield (fvc, "vertices"));
+%! assert (isfield (fvc, "faces"));
+%! assert (isfield (fvc, "facevertexcdata"));
+
+## one argument (un-documented Matlab)
+%!test
+%! fvc = isocaps (val);
+%! fvc2 = isocaps (val, []);
+%! assert (fvc, fvc2);
+%! assert (isfield (fvc, "vertices"));
+%! assert (isfield (fvc, "faces"));
+%! assert (isfield (fvc, "facevertexcdata"));
+
+## four arguments (un-documented Matlab)
+%!test
+%! fvc = isocaps (x, [], z, val);
+%! assert (isfield (fvc, "vertices"));
+%! assert (isfield (fvc, "faces"));
+%! assert (isfield (fvc, "facevertexcdata"));
+
+## five arguments, two outputs
+%!test
+%! [faces, vertices] = isocaps ([], y, z, val, iso);
+%! assert (columns (faces), 3);
+%! assert (columns (vertices), 3);
+
+## five arguments, three outputs
+%!test
+%! [faces, vertices, caps_cdata] = isocaps (x, y, [], val, iso);
+%! assert (columns (faces), 3);
+%! assert (columns (vertices), 3);
+%! assert (columns (caps_cdata), 1);
+%! assert (rows (vertices), rows (caps_cdata));
+
+## two arguments + one string, one output
+%!test
+%! fvc = isocaps (val, iso, "below");
+%! assert (isfield (fvc, "vertices"));
+%! assert (isfield (fvc, "faces"));
+%! assert (isfield (fvc, "facevertexcdata"));
+
+## two arguments + two strings, one output
+%!test
+%! fvc = isocaps (val, iso, "b", "ymax");
+%! assert (isfield (fvc, "vertices"));
+%! assert (isfield (fvc, "faces"));
+%! assert (isfield (fvc, "facevertexcdata"));
+
+## two arguments + three strings, one output
+%!test
+%! fvc = isocaps (val, iso, "a", "ymin", "verbose");
+%! assert (isfield (fvc, "vertices"));
+%! assert (isfield (fvc, "faces"));
+%! assert (isfield (fvc, "facevertexcdata"));
+
+## five arguments + one string, three outputs
+%!test
+%! [faces, vertices, caps_cdata] = isocaps (x, y, z, val, iso, "xmin");
+%! assert (columns (faces), 3);
+%! assert (columns (vertices), 3);
+%! assert (columns (caps_cdata), 1);
+%! assert (rows (vertices), rows (caps_cdata));
+
+## five arguments + one string, three outputs
+%!test
+%! [faces, vertices, caps_cdata] = isocaps (x, y, z, val, iso, "verbose");
+%! assert (columns (faces), 3);
+%! assert (columns (vertices), 3);
+%! assert (columns (caps_cdata), 1);
+%! assert (rows (vertices), rows (caps_cdata));
+
+## five arguments + two strings, three outputs
+%!test
+%! [faces, vertices, caps_cdata] = isocaps (x, y, z, val, iso, ...
+%!                                          "xmax", "above");
+%! assert (columns (faces), 3);
+%! assert (columns (vertices), 3);
+%! assert (columns (caps_cdata), 1);
+%! assert (rows (vertices), rows (caps_cdata));
+
+## five arguments + three strings, three outputs
+%!test
+%! [faces, vertices, caps_cdata] = isocaps (x, y, z, val, iso, ...
+%!                                          "zmin", "b", "verbose");
+%! assert (columns (faces), 3);
+%! assert (columns (vertices), 3);
+%! assert (columns (caps_cdata), 1);
+%! assert (rows (vertices), rows (caps_cdata));
+
+## five arguments + three strings (different order), three outputs
+%!test
+%! [faces, vertices, caps_cdata] = isocaps (x, y, z, val, iso, ...
+%!                                          "below", "v", "zmax");
+%! assert (columns (faces), 3);
+%! assert (columns (vertices), 3);
+%! assert (columns (caps_cdata), 1);
+%! assert (rows (vertices), rows (caps_cdata));
+
+## test for each error
+%!error fvc = isocaps ();
+%!error <X must match the size of VAL> x = 1:2:24; fvc = isocaps (x, y, z, val, iso);
+%!error <Y must match the size of VAL> y = -14:6:11; fvc = isocaps (x, y, z, val, iso);
+%!error <Z must match the size of VAL> z = linspace (16, 18, 5); fvc = isocaps (x, y, z, val, iso);
+%!error <X must match the size of VAL>
+%! x = 1:2:24;
+%! [xx, yy, zz] = meshgrid (x, y, z);
+%! fvc = isocaps (xx, yy, zz, val, iso);
+%!error <X must match the size of VAL>
+%! y = -14:6:11;
+%! [xx, yy, zz] = meshgrid (x, y, z);
+%! fvc = isocaps (xx, yy, zz, val, iso);
+%!error <X must match the size of VAL>
+%! z = linspace (16, 18, 3);
+%! [xx, yy, zz] = meshgrid (x, y, z);
+%! fvc = isocaps (xx, yy, zz, val, iso);
+%!error <VAL must be a non-singleton 3-dimensional matrix>
+%! v2 = reshape (1:6*8, [6 8]);
+%! fvc = isocaps (v2, iso);
+%!error <VAL must be a non-singleton 3-dimensional matrix>
+%! v3 = reshape (1:6*8, [6 1 8]);
+%! fvc = isocaps (v3, iso);
+%!error <ISO must be a scalar> fvc = isocaps (val, [iso iso]);
+%!error <ISO must be a scalar> fvc = isocaps (val, {iso});
+%!error <incorrect number of input arguments> fvc = isocaps (xx, yy, zz, val, iso, 5);
+%!error <incorrect number of input arguments> fvc = isocaps (x, val, iso);
+%!error <parameter 'foo' not supported> fvc = isocaps (val, iso, "foo");
+
diff -r 60986498af9e -r eb68e4e938e6 scripts/plot/draw/isosurface.m
--- a/scripts/plot/draw/isosurface.m	Wed Aug 10 03:56:38 2016 +0100
+++ b/scripts/plot/draw/isosurface.m	Wed Aug 10 17:44:51 2016 +0200
@@ -135,7 +135,7 @@
 ## light ("Position", [1 1 5]);
 ## @end smallexample
 ##
-## @seealso{isonormals, isocolors, smooth3, reducevolume, reducepatch, patch}
+## @seealso{isonormals, isocolors, isocaps, smooth3, reducevolume, reducepatch, patch}
 ## @end deftypefn
 
 ## Author: Martin Helm <martin@mhelm.de>
@@ -243,6 +243,10 @@
         noshare = true;
         num_string_inputs++;
 
+      case ""
+        num_string_inputs++;
+        ## silently ignore empty strings
+
       otherwise
         error ("isosurface: parameter '%s' not supported", varargin{i_arg});
 
diff -r 60986498af9e -r eb68e4e938e6 scripts/plot/draw/module.mk
--- a/scripts/plot/draw/module.mk	Wed Aug 10 03:56:38 2016 +0100
+++ b/scripts/plot/draw/module.mk	Wed Aug 10 17:44:51 2016 +0200
@@ -48,6 +48,7 @@
   scripts/plot/draw/fill.m \
   scripts/plot/draw/fplot.m \
   scripts/plot/draw/hist.m \
+  scripts/plot/draw/isocaps.m \
   scripts/plot/draw/isocolors.m \
   scripts/plot/draw/isonormals.m \
   scripts/plot/draw/isosurface.m \
