function cube_display ( m, blue, red, title_string )

%*****************************************************************************80
%
%% CUBE_DISPLAY plots integer triples as filled cubes.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    08 September 2017
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, the greatest X, Y, and Z indices.
%    This might be 5, 10 or 20.
%
%    Input, function handle BLUE, a function handle, or an anonymous function, 
%    returning a logical value. If blue(x,y,z) is true, the cube will be colored blue.
%
%    Input, function handle RED, a function handle, or an anonymous function, 
%    returning a logical value.  If red(x,y,z) is true, the cube will be colored red, 
%    unless it was already blue. Thus, the red cubes indicate "new" information.
%
%    Input, string TITLE_STRING, a title for the plot.
%    If TITLE_STRING = '', no title is displayed.
%

%
%  If no input was given, set up a sample display.
%
  if ( nargin < 1 )
    m = 25;
    blue = @(x,y,z)(x+1)*(y+1)*(z+1)<=27;
    red = @(x,y,z)(x+1)*(y+1)*(z+1)<=64;
    title_string = 'Sample CUBE\_DISPLAY calculation';
  end
%
%  Clear the figure area, in case a previous plot was showing.
%
  clf
%
%  Consider each (x,y,z) location in (0:m,0:m,0:m).
%  If the user says it should be blue or red, plot a blue or red cube there.
%
  for x = 0 : m

    for y = 0 : m

      for z = 0 : m

        if ( blue ( x, y, z ) )
          plotcube ( [ 0.8, 0.8, 0.8 ], [ x+0.1, y+0.1, z+0.1 ], 1.0, [ 0.0, 0.0, 1.0 ] );
        elseif ( red ( x, y, z ) )
          plotcube ( [ 0.8, 0.8, 0.8 ], [ x+0.1, y+0.1, z+0.1 ], 1.0, [ 1.0, 0.0, 0.0 ] );
        end

      end

    end
    
  end
%
%  The TITLE function will interpret underscores in the title.
%  We need to unescape such escape sequences!
%
  if ( 0 < length ( title_string ) )
    title ( title_string )
  end
%
%  Determine the plot range.
%
  x_data_min = 0;
  x_data_max = m;
  y_data_min = 0;
  y_data_max = m;
  z_data_min = 0;
  z_data_max = m;

  x_plot_min = x_data_min - 0.5;
  x_plot_max = x_data_max + 0.5;

  y_plot_min = y_data_min - 0.5;
  y_plot_max = y_data_max + 0.5;

  z_plot_min = z_data_min - 0.5;
  z_plot_max = z_data_max + 0.5;

  x_plot_range = x_plot_max - x_plot_min;
  y_plot_range = y_plot_max - y_plot_min;
  z_plot_range = z_plot_max - z_plot_min;

  margin = 0.025 * max ( [ x_plot_range, y_plot_range, z_plot_range ] );

  x_axes_min = x_plot_min - margin;
  x_axes_max = x_plot_max + margin;
  y_axes_min = y_plot_min - margin;
  y_axes_max = y_plot_max + margin;
  z_axes_min = z_plot_min - margin;
  z_axes_max = z_plot_max + margin;
%
%  Set the plot to have the size and shape you want.
%
  axis ( [ x_axes_min, x_axes_max, y_axes_min, y_axes_max, z_axes_min, z_axes_max ] );
  axis equal
  axis ( [ -0.5, m+0.5, -0.5, m+0.5, -0.5, m+0.5 ] )

  return
end
function plotcube ( varargin )
%
% PLOTCUBE - Display a 3D-cube in the current axes
%
%   PLOTCUBE(EDGES,ORIGIN,ALPHA,COLOR) displays a 3D-cube in the current axes
%   with the following properties:
%   * EDGES : 3-elements vector that defines the length of cube edges
%   * ORIGIN: 3-elements vector that defines the start point of the cube
%   * ALPHA : scalar that defines the transparency of the cube faces (from 0
%             to 1)
%   * COLOR : 3-elements vector that defines the faces color of the cube
%
% Example:
%   >> plotcube([5 5 5],[ 2  2  2],.8,[1 0 0]);
%   >> plotcube([5 5 5],[10 10 10],.8,[0 1 0]);
%   >> plotcube([5 5 5],[20 20 20],.8,[0 0 1]);

%
% Default input arguments
%
  inArgs = { ...
    [10 56 100] , ... % Default edge sizes (x,y and z)
    [10 10  10] , ... % Default coordinates of the origin point of the cube
    .7          , ... % Default alpha value for the cube's faces
    [1 0 0]       ... % Default Color for the cube
    };
%
% Replace default input arguments by input values
%
  inArgs(1:nargin) = varargin;
%
% Create all variables
%
  [edges,origin,alpha,clr] = deal(inArgs{:});

  XYZ = { ...
    [0 0 0 0]  [0 0 1 1]  [0 1 1 0] ; ...
    [1 1 1 1]  [0 0 1 1]  [0 1 1 0] ; ...
    [0 1 1 0]  [0 0 0 0]  [0 0 1 1] ; ...
    [0 1 1 0]  [1 1 1 1]  [0 0 1 1] ; ...
    [0 1 1 0]  [0 0 1 1]  [0 0 0 0] ; ...
    [0 1 1 0]  [0 0 1 1]  [1 1 1 1]   ...
    };

  XYZ = mat2cell(...
    cellfun( @(x,y,z) x*y+z , ...
      XYZ , ...
      repmat(mat2cell(edges,1,[1 1 1]),6,1) , ...
      repmat(mat2cell(origin,1,[1 1 1]),6,1) , ...
      'UniformOutput',false), ...
      6,[1 1 1]);

  cellfun(@patch,XYZ{1},XYZ{2},XYZ{3},...
    repmat({clr},6,1),...
    repmat({'FaceAlpha'},6,1),...
    repmat({alpha},6,1)...
    );

  view(3);

  return
end

