function stla_to_tri_surface ( stla_file_name, node_file_name, triangle_file_name )

%*****************************************************************************80
%
%% STLA_TO_TRI_SURFACE converts an ASCII STL file to a TRI_SURFACE file.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 September 2008
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string STLA_FILE_NAME, the name of the ASCII STL file to be read.
%
%    Input, string NODE_FILE_NAME, the name of the TRI_SURFACE node file
%    to be written.
%
%    Input, string TRIANGLE_FILE_NAME, the name of the TRI_SURFACE triangle
%    file to be written.
%

%
%  Get the size of the STLA data.
%
  [ solid_num, node_num, triangle_num, text_num ] = stla_size ( stla_file_name );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  STLA file "%s".\n', stla_file_name );
  fprintf ( 1, '  Number of solids   = %d\n', solid_num );
  fprintf ( 1, '  Number of nodes    = %d\n', node_num );
  fprintf ( 1, '  Number of faces    = %d\n', triangle_num );
  fprintf ( 1, '  Number of textures = %d\n', text_num );
%
%  Read the STLA data.
%
  [ node_xyz, triangle_node, triangle_normal ] = stla_read ( stla_file_name, ...
    node_num, triangle_num );
%
%  Write the data to the TRI_SURFACE files.
%
  dim_num = size ( node_xyz, 1 );
  order_num = 3;

  tri_surface_write ( node_file_name, triangle_file_name, dim_num, node_num, ...
    order_num, triangle_num, node_xyz, triangle_node );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  TRI_SURFACE data written to:\n' );
  fprintf ( 1, '  node file     "%s".\n', node_file_name );
  fprintf ( 1, '  triangle_file "%s".\n', triangle_file_name );

  return
end
function c2 = ch_cap ( c )

%*****************************************************************************80
%
%% CH_CAP capitalizes a single character.
%
%  Modified:
%
%    22 November 2003
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, character C, the character to capitalize.
%
%    Output, character C2, the capitalized character.
%
  if ( 'a' <= c & c <= 'z' )
    c2 = c + 'A' - 'a';
  else
    c2 = c;
  end

  return
end
function truefalse = ch_eqi ( c1, c2 )

%*****************************************************************************80
%
%% CH_EQI is a case insensitive comparison of two characters for equality.
%
%  Examples:
%
%    CH_EQI ( 'A', 'a' ) is TRUE.
%
%  Modified:
%
%    28 July 2000
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, character C1, C2, the characters to compare.
%
%    Output, logical TRUEFALSE, is TRUE (1) if the characters are equal.
%
  FALSE = 0;
  TRUE = 1;

  if ( ch_cap ( c1 ) == ch_cap ( c2 ) )
    truefalse = TRUE;
  else
    truefalse = FALSE;
  end

  return
end
function truefalse = ch_is_digit ( c )

%*****************************************************************************80
%
% CH_IS_DIGIT returns TRUE if the character C is a digit.
%
%  Modified:
%
%    11 December 2003
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, character C, a character.
%
%    Output, integer TRUEFALSE, is TRUE (1) if C is a digit, FALSE (0) otherwise.
%
  TRUE = 1;
  FALSE = 0;

  if ( '0' <= c & c <= '9' )
    truefalse = TRUE;
  else
    truefalse = FALSE;
  end

  return
end
function digit = ch_to_digit ( c )

%*****************************************************************************80
%
%% CH_TO_DIGIT returns the integer value of a base 10 digit.
%
%  Example:
%
%     C   DIGIT
%    ---  -----
%    '0'    0
%    '1'    1
%    ...  ...
%    '9'    9
%    ' '    0
%    'X'   -1
%
%  Modified:
%
%    22 November 2003
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, character C, the decimal digit, '0' through '9' or blank
%    are legal.
%
%    Output, integer DIGIT, the corresponding integer value.  If C was
%    'illegal', then DIGIT is -1.
%
  if ( '0' <= c & c <= '9' )

    digit = c - '0';

  elseif ( c == ' ' )

    digit = 0;

  else

    digit = -1;

  end

  return
end
function i4mat_write0 ( output_filename, m, n, table )

%*****************************************************************************80
%
%% I4MAT_WRITE0 writes an I4MAT file with no header.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    20 July 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string OUTPUT_FILENAME, the output filename.
%
%    Input, integer M, the spatial dimension.
%
%    Input, integer N, the number of points.
%
%    Input, integer TABLE(M,N), the points.
%
%    Input, logical HEADER, is TRUE if the header is to be included.
%

%
%  Open the file.
%
  output_unit = fopen ( output_filename, 'wt' );

  if ( output_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'I4MAT_WRITE0 - Error!\n' );
    fprintf ( 1, '  Could not open the output file.\n' );
    error ( 'I4MAT_WRITE0 - Error!' );
    return;
  end
%
%  Write the data.
%
  for j = 1 : n
    for i = 1 : m
      fprintf ( output_unit, '  %12d', round ( table(i,j) ) );
    end
    fprintf ( output_unit, '\n' );
  end
%
%  Close the file.
%
  fclose ( output_unit );

  return
end
function r8mat_write0 ( output_filename, m, n, table )

%*****************************************************************************80
%
%% R8MAT_WRITE0 writes an R8MAT file with no header.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    29 June 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string OUTPUT_FILENAME, the output filename.
%
%    Input, integer M, the spatial dimension.
%
%    Input, integer N, the number of points.
%
%    Input, real TABLE(M,N), the points.
%

%
%  Open the file.
%
  output_unit = fopen ( output_filename, 'wt' );

  if ( output_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'R8MAT_WRITE0 - Error!\n' );
    fprintf ( 1, '  Could not open the output file.\n' );
    error ( 'R8MAT_WRITE0 - Error!' );
    return;
  end
%
%  Write the data.
%
%  For greater precision, try:
%
%     fprintf ( output_unit, '  %24,16f', table(i,j) );
%
  for j = 1 : n
    for i = 1 : m
      fprintf ( output_unit, '  %14f', table(i,j) );
    end
    fprintf ( output_unit, '\n' );
  end
%
%  Close the file.
%
  fclose ( output_unit );

  return
end
function s3 = s_cat ( s1, s2 )

%*****************************************************************************80
%
%% S_CAT concatenates two strings to make a third string.
%
%  Discussion:
%
%    MATLAB provides the STRCAT function, which you should
%    probably use instead of this function!
%
%    s3 = strcat ( s1, s2 )
%
%    Although STRCAT does not ignore trailing blanks.
%
%  Modified:
%
%    28 May 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string S1, the "prefix" string.
%
%    Input, string S2, the "postfix" string.
%
%    Output, string S3, the string made by
%    concatenating S1 and S2, ignoring any trailing blanks.
%
  l1 = s_len_trim ( s1 );
  l2 = s_len_trim ( s2 );
%
%  The following line essentially "declares" S3 to be a
%  character string.  Omitting this line would cause S3
%  to be regarded as a numeric array.
%
  s3 = '';
%
%  Now copy the strings.
%
  s3(   1:l1   ) = s1(1:l1);
  s3(l1+1:l1+l2) = s2(1:l2);

  return
end
function value = s_eqi ( s1, s2 )

%*****************************************************************************80
%
%% S_EQI is a case insensitive comparison of two strings for equality.
%
%  Example:
%
%    S_EQI ( 'Anjana', 'ANJANA' ) is TRUE.
%
%  Modified:
%
%    30 April 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, character ( len = * ) S1, S2, the strings to compare.
%
%    Output, logical VALUE, is TRUE if the strings are equal.
%
  FALSE = 0;
  TRUE = 1;

  len1 = length ( s1 );
  len2 = length ( s2 );
  lenc = min ( len1, len2 );

  value = FALSE;

  for i = 1 : lenc

    c1 = ch_cap ( s1(i) );
    c2 = ch_cap ( s2(i) );

    if ( c1 ~= c2 )
      value = FALSE;
      return
    end

  end

  for i = lenc + 1 : len1
    if ( s1(i) ~= ' ' )
      value = FALSE;
      return
    end
  end

  for i = lenc + 1 : len2
    if ( s2(i) ~= ' ' )
      value = FALSE;
      return
    end
  end

  value = TRUE;

  return
end
function len = s_len_trim ( s )

%*****************************************************************************80
%
% S_LEN_TRIM returns the length of a character string to the last nonblank.
%
%  Modified:
%
%    14 June 2003
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string S, the string to be measured.
%
%    Output, integer LENGTH, the length of the string up to the last nonblank.
%
  len = length ( s );

  while ( 0 < len )
    if ( s(len) ~= ' ' )
      return
    end
    len = len - 1;
  end

  return
end
function [ r, lchar, ierror ] = s_to_r8 ( s )

%*****************************************************************************80
%
%% S_TO_R8 reads an R8 from a string.
%
%  Discussion:
%
%    This routine will read as many characters as possible until it reaches
%    the end of the string, or encounters a character which cannot be
%    part of the real number.
%
%    Legal input is:
%
%       1 blanks,
%       2 '+' or '-' sign,
%       2.5 spaces
%       3 integer part,
%       4 decimal point,
%       5 fraction part,
%       6 'E' or 'e' or 'D' or 'd', exponent marker,
%       7 exponent sign,
%       8 exponent integer part,
%       9 exponent decimal point,
%      10 exponent fraction part,
%      11 blanks,
%      12 final comma or semicolon.
%
%    with most quantities optional.
%
%  Examples:
%
%    S                 R
%
%    '1'               1.0
%    '     1   '       1.0
%    '1A'              1.0
%    '12,34,56'        12.0
%    '  34 7'          34.0
%    '-1E2ABCD'        -100.0
%    '-1X2ABCD'        -1.0
%    ' 2E-1'           0.2
%    '23.45'           23.45
%    '-4.2E+2'         -420.0
%    '17d2'            1700.0
%    '-14e-2'         -0.14
%    'e2'              100.0
%    '-12.73e-9.23'   -12.73 * 10.0**(-9.23)
%
%  Modified:
%
%    22 November 2003
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string S, the string containing the
%    data to be read.  Reading will begin at position 1 and
%    terminate at the end of the string, or when no more
%    characters can be read to form a legal real.  Blanks,
%    commas, or other nonnumeric data will, in particular,
%    cause the conversion to halt.
%
%    Output, real R, the value that was read from the string.
%
%    Output, integer LCHAR, the number of characters of S that were used to form R.
%
%    Output, integer IERROR, is 0 if no error occurred.
%
  s_length = s_len_trim ( s );
  ierror = 0;
  r = 0.0;
  lchar = -1;
  isgn = 1;
  rtop = 0.0;
  rbot = 1.0;
  jsgn = 1;
  jtop = 0;
  jbot = 1;
  ihave = 1;
  iterm = 0;

  while ( 1 )

    lchar = lchar + 1;
    c = s(lchar+1);
%
%  Blank character.
%
    if ( c == ' ' )

      if ( ihave == 2 )

      elseif ( ihave == 6 | ihave == 7 )
        iterm = 1;
      elseif ( 1 < ihave )
        ihave = 11;
      end
%
%  Comma.
%
    elseif ( c == ',' | c == ';' )

      if ( ihave ~= 1 )
        iterm = 1;
        ihave = 12;
        lchar = lchar + 1;
      end
%
%  Minus sign.
%
    elseif ( c == '-' )

      if ( ihave == 1 );
        ihave = 2;
        isgn = -1;
      elseif ( ihave == 6 )
        ihave = 7;
        jsgn = -1;
      else
        iterm = 1;
      end
%
%  Plus sign.
%
    elseif ( c == '+' )

      if ( ihave == 1 )
        ihave = 2;
      elseif ( ihave == 6 )
        ihave = 7;
      else
        iterm = 1;
      end
%
%  Decimal point.
%
    elseif ( c == '.' )

      if ( ihave < 4 )
        ihave = 4;
      elseif ( 6 <= ihave & ihave <= 8 )
        ihave = 9;
      else
        iterm = 1;
      end
%
%  Exponent marker.
%
    elseif ( ch_eqi ( c, 'E' ) | ch_eqi ( c, 'D' ) )

      if ( ihave < 6 )
        ihave = 6;
      else
        iterm = 1;
      end
%
%  Digit.
%
    elseif ( ihave < 11 & ch_is_digit ( c ) )

      if ( ihave <= 2 )
        ihave = 3;
      elseif ( ihave == 4 )
        ihave = 5;
      elseif ( ihave == 6 | ihave == 7 )
        ihave = 8;
      elseif ( ihave == 9 )
        ihave = 10;
      end

      d = ch_to_digit ( c );

      if ( ihave == 3 )
        rtop = 10.0 * rtop + d;
      elseif ( ihave == 5 )
        rtop = 10.0 * rtop + d;
        rbot = 10.0 * rbot;
      elseif ( ihave == 8 )
        jtop = 10 * jtop + d;
      elseif ( ihave == 10 )
        jtop = 10 * jtop + d;
        jbot = 10 * jbot;
      end
%
%  Anything else is regarded as a terminator.
%
    else
      iterm = 1;
    end
%
%  If we haven't seen a terminator, and we haven't examined the
%  entire string, go get the next character.
%
    if ( iterm == 1 | s_length <= lchar + 1 )
      break;
    end

  end
%
%  If we haven't seen a terminator, and we have examined the
%  entire string, then we're done, and LCHAR is equal to S_LENGTH.
%
  if ( iterm ~= 1 & lchar + 1 == s_length )
    lchar = s_length;
  end
%
%  Number seems to have terminated.  Have we got a legal number?
%  Not if we terminated in states 1, 2, 6 or 7!
%
  if ( ihave == 1 | ihave == 2 | ihave == 6 | ihave == 7 )
    ierror = ihave;
    fprintf ( 1, '\n' );
    fprintf ( 1, 'S_TO_R8 - Fatal error!\n' );
    fprintf ( 1, '  IHAVE = %d\n', ihave );
    error ( 'S_TO_R8 - Fatal error!' );
  end
%
%  Number seems OK.  Form it.
%
  if ( jtop == 0 )
    rexp = 1.0;
  else

    if ( jbot == 1 )
      rexp = 10.0^( jsgn * jtop );
    else
      rexp = jsgn * jtop;
      rexp = rexp / jbot;
      rexp = 10.0^rexp;
    end

  end

  r = isgn * rexp * rtop / rbot;

  return
end
function [ node_xyz, face_node, face_normal ] = stla_read ( ...
  input_file_name, node_num, face_num )

%*****************************************************************************80
%
%% STLA_READ reads graphics information from an ASCII StereoLithography file.
%
%  Modified:
%
%    17 February 2007
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    3D Systems, Inc,
%    Stereolithography Interface Specification,
%    October 1989.
%
%  Parameters:
%
%    Input, string INPUT_FILE_NAME, the name of the input file.
%
%    Input, integer NODE_NUM, the number of vertices defined.
%
%    Input, integer FACE_NUM, the number of faces defined.
%
%    Output, real NODE_XYZ(3,NODE_NUM), the coordinates of points.
%
%    Output, integer FACE_NODE(3,FACE_NUM), the nodes that make up each face.
%
%    Output, real FACE_NORMAL(3,FACE_NUM), the normal vector
%    at each face.
%
  node_xyz = [];
  face_node = [];
  face_normal = [];
%
%  If no file input, try to get one from the user.
%
  if ( nargin < 1 )
    input_file_name = input ( 'Enter the name of the ASCII STL file.' );
    if ( isempty ( input_file_name ) )
      return
    end
  end
%
%  If no size input, scan the file.
%
  if ( nargin < 3 )
    [ solid_num, node_num, face_num, text_num ] = stla_size ( ...
      input_file_name );
  end
%
%  Open the file.
%
  input_file_unit = fopen ( input_file_name, 'r' );

  if ( input_file_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'STLA_READ - Fatal error!\n' );
    fprintf ( 1, '  Could not open the file "%s".\n', input_file_name );
    error ( 'STLA_READ - Fatal error!' )
    return
  end
%
%  Allocate space.
%
  state = 0;
  text_num = 0;

  solid = 0;
  face = 0;
  node = 0;

  node_xyz = zeros ( 3, node_num );
  face_node = zeros ( 3, face_num );
  face_normal = zeros ( 3, face_num );
%
%  Read the next line of text.
%
  while ( 1 )

    text = fgetl ( input_file_unit );
%
%  On end of input, FGETL returns a -1 instead of a character array.
%
    if ( text == -1 )
      if ( state ~= 0 & state ~= 1 )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'STLA_READ - Fatal error!\n' );
        fprintf ( 1, '  File line number = %d\n', text_num );
        fprintf ( 1, '  End-of-file, but model not finished.\n' );
        error ( 'STLA_READ - Fatal error!' );
        return
      end
      break;
    end

    text_num = text_num + 1;
    done = 1;
%
%  Read the first word in the line.
%
    [ word1, done ] = word_next_read ( text, done );

    if ( done )
      break
    end
%
%  "Doctor" the text, changing a beginning occurrence of:
%
%      END FACET to ENDFACET
%      END LOOP to ENDLOOP
%      END SOLID to ENDSOLID
%      FACET NORMAL to FACETNORMAL
%      OUTER LOOP to OUTERLOOP
%
    if ( s_eqi ( word1, 'END' ) )

      [ word2, done ] = word_next_read ( text, done );

      if ( ~s_eqi ( word2, 'FACET' ) & ...
           ~s_eqi ( word2, 'LOOP' ) & ...
           ~s_eqi ( word2, 'SOLID' ) )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'STLA_READ - Fatal error!\n' );
        fprintf ( 1, '  File line number = %d\n', text_num );
        fprintf ( 1, '  The tag END was followed by an illegal\n' );
        fprintf ( 1, '  word: "%s", when expecting\n', word );
        fprintf ( 1, '  "FACET", "LOOP", or "SOLID".\n' );
        error ( 'STLA_READ - Fatal error!' );
        return
      end

      word1 = s_cat ( word1, word2 );

    elseif ( s_eqi ( word1, 'FACET' ) )

      [ word2, done ] = word_next_read ( text, done );

      if ( ~s_eqi ( word2, 'NORMAL' ) )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'STLA_READ - Fatal error!\n' );
        fprintf ( 1, '  File line number = %d\n', text_num );
        fprintf ( 1, '  The tag FACET was followed by an illegal\n' );
        fprintf ( 1, '  word: "%s", when expecting\n', word2 );
        fprintf ( 1, '  "NORMAL".\n' );
        error ( 'STLA_READ - Fatal error!' );
        return
      end

      word1 = s_cat ( word1, word2 );

    elseif ( s_eqi ( word1, 'OUTER' ) )

      [ word2, done ] = word_next_read ( text, done );

      if ( ~s_eqi ( word2, 'LOOP' ) )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'STLA_READ - Fatal error!\n' );
        fprintf ( 1, '  File line number = %d\n', text_num );
        fprintf ( 1, '  The tag OUTER was followed by an illegal\n' );
        fprintf ( 1, '  word: "%s", when expecting\n', word2 );
        fprintf ( 1, '  "LOOP".\n' );
        error ( 'STLA_READ - Fatal error!' );
        return
      end

      word1 = s_cat ( word1, word2 );

    end
%
%  This first word tells us what to do.
%
%  SOLID - begin a new solid.
%    Valid in state 0, moves to state 1.
%  ENDSOLID - end current solid.
%    Valid in state 1, moves to state 0.
%
%  FACETNORMAL - begin a new facet.
%    Valid in state 0 or 1, moves to state 2.
%  ENDFACET - end current facet.
%    Valid in state 2, moves to state 1.
%
%  OUTERLOOP - begin a list of vertices.
%    Valid in state 2, moves to state 3, sets vertex count to 0.
%  ENDLOOP - end vertex list.
%    Valid in state 3, moves to state 2.
%
%  VERTEX - give coordinates of next vertex.
%    Valid in state 3.
%
%  End of file -
%    Valid in state 0 or 1.
%
    if ( s_eqi ( word1, 'SOLID' ) )

      if ( state ~= 0 )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'STLA_READ - Fatal error!\n' );
        fprintf ( 1, '  File line number = %d\n', text_num );
        fprintf ( 1, '  A new SOLID statement was encountered, but we\n' );
        fprintf ( 1, '  have not finished processing the current solid.\n' );
        error ( 'STLA_READ - Fatal error!' );
        return
      end

      state = 1;

    elseif ( s_eqi ( word1, 'ENDSOLID' ) )

      if ( state ~= 1 )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'STLA_READ - Fatal error!\n' );
        fprintf ( 1, '  File line number = %d\n', text_num );
        fprintf ( 1, '  An END SOLID statement was encountered, but\n' );
        fprintf ( 1, '  either we have not begun a solid at all, or we\n' );
        fprintf ( 1, '  are not at an appropriate point to finish the\n' );
        fprintf ( 1, '  current solid.\n' );
        error ( 'STLA_READ - Fatal error!' );
        return
      end

      state = 0;

    elseif ( s_eqi ( word1, 'FACETNORMAL' ) )

      if ( state ~= 0 & state ~= 1 )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'STLA_READ - Fatal error!\n' );
        fprintf ( 1, '  File line number = %d\n', text_num );
        fprintf ( 1, '  Model not in right state for FACET.\n' );
        error ( 'STLA_READ - Fatal error!' );
        return
      end

      state = 2;
      face = face + 1;

      if ( face_num < face )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'STLA_READ - Warning!\n' );
        fprintf ( 1, '  More faces being read than expected.\n' );
        fprintf ( 1, '  File line number = %d\n', text_num );
        error ( 'STLA_READ - Fatal error!' );
        return
      end

      for i = 1 : 3

        face_normal(i,face) = 0.0;

        [ word2, done ] = word_next_read ( text, done );

        if ( done )
          fprintf ( 1, '\n' );
          fprintf ( 1, 'STLA_READ - Fatal error!\n' );
          fprintf ( 1, '  File line number = %d\n', text_num );
          fprintf ( 1, '  End of information while reading a component\n' );
          fprintf ( 1, '  of the normal vector.\n' );
          error ( 'STLA_READ - Fatal error!' );
          return
        end

        [ dval, lchar, ierror ] = s_to_r8 ( word2 );

        if ( ierror ~= 0 )
          fprintf ( 1, '\n' );
          fprintf ( 1, 'STLA_READ - Fatal error!\n' );
          fprintf ( 1, '  File line number = %d\n', text_num );
          fprintf ( 1, '  Reading a component of the normal vector.\n' );
          error ( 'STLA_READ - Fatal error!' );
          return
        end

        face_normal(i,face) = dval;

      end

    elseif ( s_eqi ( word1, 'ENDFACET' ) )

      if ( state ~= 2 )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'STLA_READ - Fatal error!\n' );
        fprintf ( 1, '  File line number = %d\n', text_num );
        fprintf ( 1, '  Model not in right state for ENDFACET.\n' );
        error ( 'STLA_READ - Fatal error!' );
        return
      end

      state = 1;

    elseif ( s_eqi ( word1, 'OUTERLOOP' ) )

      if ( state ~= 2 )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'STLA_READ - Fatal error!\n' );
        fprintf ( 1, '  File line number = %d\n', text_num );
        fprintf ( 1, '  Model not in right state for OUTERLOOP.\n' );
        error ( 'STLA_READ - Fatal error!' );
        return
      end

      state = 3;
      vertex = 0;

    elseif ( s_eqi ( word1, 'ENDLOOP' ) )

      if ( state ~= 3 )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'STLA_READ - Fatal error!\n' );
        fprintf ( 1, '  File line number = %d\n', text_num );
        fprintf ( 1, '  Model not in right state for ENDLOOP.\n' );
        error ( 'STLA_READ - Fatal error!' );
        return
      end

      state = 2;

    elseif ( s_eqi ( word1, 'VERTEX' ) )

      if ( state ~= 3 )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'STLA_READ - Fatal error!\n' );
        fprintf ( 1, '  File line number = %d\n', text_num );
        fprintf ( 1, '  Model not in right state for VERTEX.\n' );
        error ( 'STLA_READ - Fatal error!' );
        return
      end

      if ( 3 <= vertex )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'STLA_READ - Fatal error!\n' );
        fprintf ( 1, '  File line number = %d\n', text_num );
        fprintf ( 1, '  More than 3 vertices specified for a face.\n' );
        error ( 'STLA_READ - Fatal error!' );
        return
      end

      for i = 1 : 3

        [ word2, done ] = word_next_read ( text, done );

        if ( done )
          fprintf ( 1, '\n' );
          fprintf ( 1, 'STLA_READ - Fatal error!\n' );
          fprintf ( 1, '  File line number = %d\n', text_num );
          fprintf ( 1, '  The value of a vertex coordinate is missing.\n' );
          error ( 'STLA_READ - Fatal error!' );
          return
        end

        [ dval, lchar, ierror ] = s_to_r8 ( word2 );

        if ( ierror ~= 0 )
          fprintf ( 1, '\n' );
          fprintf ( 1, 'STLA_READ - Fatal error!\n' );
          fprintf ( 1, '  File line number = %d\n', text_num );
          fprintf ( 1, '  The value of a vertex coordinate makes\n' );
          fprintf ( 1, '  no sense.\n' );
          error ( 'STLA_READ - Fatal error!' );
          return
        end

        temp(i) = dval;

      end

      if ( node_num <= node )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'STLA_READ - Warning!\n' );
        fprintf ( 1, '  More nodes being read than expected.\n' );
        fprintf ( 1, '  File line number = %d\n', text_num );
        error ( 'STLA_READ - Fatal error!' );
        return
      end

      node = node + 1;
      node_xyz(1:3,node) = temp(1:3);

      vertex = vertex + 1;
      face_node(vertex,face) = node;

    else

      fprintf ( 1, '\n' );
      fprintf ( 1, 'STLA_READ - Fatal error!\n' );
      fprintf ( 1, '  File line number = %d\n', text_num );
      fprintf ( 1, '  Unrecognized line in file.\n' );
      error ( 'STLA_READ - Fatal error!' );
      return

    end

  end
%
%  Close the file.
%
  fclose ( input_file_unit );

  return
end
function [ solid_num, node_num, face_num, text_num ] = stla_size ( ...
  input_file_name )

%*****************************************************************************80
%
%% STLA_SIZE determines sizes associated with an STLA file.
%
%  Discussion:
%
%    This routine assumes that the file is a legal STLA file.
%
%    To perform checks on the file, call STLA_CHECK first.
%
%    Note that the counts for the number of nodes and edges are
%    overestimates, since presumably, most nodes will be defined several
%    times, once for each face they are part of, and most edges will
%    be defined twice.
%
%  Modified:
%
%    16 February 2007
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    3D Systems, Inc,
%    Stereolithography Interface Specification,
%    October 1989.
%
%  Parameters:
%
%    Input, string INPUT_FILE_NAME, the name of the input file.
%
%    Output, integer SOLID_NUM, the number of solids defined.
%    Presumably, this is 1.
%
%    Output, integer NODE_NUM, the number of vertices defined.
%
%    Output, integer FACE_NUM, the number of faces defined.
%
%    Output, integer TEXT_NUM, the number of lines of text.
%
  ierror = 0;
  state = 0;

  solid_num = -1;
  node_num = -1;
  face_num = -1;
  text_num = -1;
%
%  If no file input, try to get one from the user.
%
  if ( nargin < 1 )
    input_file_name = input ( 'Enter the name of the ASCII STL file.' );
    if ( isempty ( input_file_name ) )
      return
    end
  end
%
%  Open the file.
%
  input_file_unit = fopen ( input_file_name, 'r' );

  if ( input_file_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'STLA_SIZE - Fatal error!\n' );
    fprintf ( 1, '  Could not open the file "%s".\n', input_file_name );
    error ( 'STLA_SIZE - Fatal error!' );
    return
  end

  solid_num = 0;
  node_num = 0;
  face_num = 0;
  text_num = 0;
%
%  Read the text, one line at a time.
%
  while ( 1 )

    text = fgetl ( input_file_unit );

    if ( text == -1 )
      if ( state ~= 0 & state ~= 1 )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'STLA_SIZE - Fatal error!\n' );
        fprintf ( 1, '  File line number = %d\n', text_num );
        fprintf ( 1, '  End-of-file, but model not finished.\n' );
        return
      end
      break;
    end

    text_num = text_num + 1;

    done = 1;
%
%  Read the first word in the line.
%
    [ word1, done ] = word_next_read ( text, done );

    if ( done )
      break
    end
%
%  "Doctor" the text, changing a beginning occurrence of:
%
%      END FACET to ENDFACET
%      END LOOP to ENDLOOP
%      END SOLID to ENDSOLID
%      FACET NORMAL to FACETNORMAL
%      OUTER LOOP to OUTERLOOP
%
    if ( s_eqi ( word1, 'END' ) )

      [ word2, done ] = word_next_read ( text, done );

      if ( ~s_eqi ( word2, 'FACET' ) & ...
           ~s_eqi ( word2, 'LOOP' ) & ...
           ~s_eqi ( word2, 'SOLID' ) )
        return
      end

      word1 = s_cat ( word1, word2 );

    elseif ( s_eqi ( word1, 'FACET' ) )

      [word2, done ] = word_next_read ( text, done );

      if ( ~s_eqi ( word2, 'NORMAL' ) )
        return
      end

      word1 = s_cat ( word1, word2 );

    elseif ( s_eqi ( word1, 'OUTER' ) )

      [ word2, done ] = word_next_read ( text, done );

      if ( ~s_eqi ( word2, 'LOOP' ) )
        return
      end

      word1 = s_cat ( word1, word2 );

    end
%
%  This first word tells us what to do.
%
%  SOLID - begin a new solid.
%    Valid in state 0, moves to state 1.
%  ENDSOLID - end current solid.
%    Valid in state 1, moves to state 0.
%
%  FACETNORMAL - begin a new facet.
%    Valid in state 0 or 1, moves to state 2.
%  ENDFACET - end current facet.
%    Valid in state 2, moves to state 1.
%
%  OUTERLOOP - begin a list of vertices.
%    Valid in state 2, moves to state 3.
%  ENDLOOP - end vertex list.
%    Valid in state 3, moves to state 2.
%
%  VERTEX - give coordinates of next vertex.
%    Valid in state 3 if current vertex count is 0, 1 or 2.
%
%  End of file -
%    Valid in state 0 or 1.
%
    if ( s_eqi ( word1, 'SOLID' ) )

      if ( state ~= 0 )
        return
      end

      state = 1;

    elseif ( s_eqi ( word1, 'ENDSOLID' ) )

      if ( state ~= 1 )
        return
      end

      state = 0;
      solid_num = solid_num + 1;

    elseif ( s_eqi ( word1, 'FACETNORMAL' ) )

      if ( state ~= 0 & state ~= 1 )
        return
      end

      state = 2;

      for i = 1 : 3

        [ word2, done ] = word_next_read ( text, done );

        if ( done )
          return
        end

        [ dval, lchar, ierror ] = s_to_r8 ( word2 );

        if ( ierror ~= 0 )
          return
        end

      end

    elseif ( s_eqi ( word1, 'ENDFACET' ) )

      if ( state ~= 2 )
        return
      end

      state = 1;

      face_num = face_num + 1;

    elseif ( s_eqi ( word1, 'OUTERLOOP' ) )

      if ( state ~= 2 )
        return
      end

      state = 3;
      vertex = 0;

    elseif ( s_eqi ( word1, 'ENDLOOP' ) )

      if ( state ~= 3 )
        return
      end

      state = 2;

    elseif ( s_eqi ( word1, 'VERTEX' ) )

      if ( state ~= 3 )
        return
      end

      if ( 3 <= vertex )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'STLA_SIZE - Fatal error!\n' );
        fprintf ( 1, '  Too many vertices for a face.\n' );
        ierror = 1;
        return
      end

      for i = 1 : 3

        [ word2, done ] = word_next_read ( text, done );

        if ( done )
          return
        end

        [ dval, lchar, ierror ] = s_to_r8 ( word2 );

        if ( ierror ~= 0 )
          return
        end

      end

      vertex = vertex + 1;
      node_num = node_num + 1;

    else

      return

    end

  end
%
%  Close the file.
%
  fclose ( input_file_unit );

  return
end
function timestamp ( )

%*****************************************************************************80
%
%% TIMESTAMP prints the current YMDHMS date as a timestamp.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 February 2003
%
%  Author:
%
%    John Burkardt
%
  t = now;
  c = datevec ( t );
  s = datestr ( c, 0 );
  fprintf ( 1, '%s\n', s );

  return
end
function tri_surface_write ( node_file_name, triangle_file_name, dim_num, ...
  node_num, order_num, triangle_num, node_xyz, triangle_node )

%*****************************************************************************80
%
%% TRI_SURFACE_WRITE writes graphics information to a pair of TRI_SURFACE files.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    08 August 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string NODE_FILE_NAME, the name of the node file.
%
%    Input, string TRIANGLE_FILE_NAME, the name of the triangle file.
%
%    Input, integer DIM_NUM, the spatial dimension.
%
%    Input, integer NODE_NUM, the number of points.
%
%    Input, integer ORDER_NUM, the order of the triangles.
%
%    Input, integer TRIANGLE_NUM, the number of triangles.
%
%    Input, real NODE_XYZ(DIM_NUM,NODE_NUM), the node coordinates.
%
%    Input, integer TRIANGLE_NODE(ORDER_NUM,TRIANGLE_NUM),
%    the nodes that form the triangles.
%
  r8mat_write0 ( node_file_name, dim_num, node_num, node_xyz );

  i4mat_write0 ( triangle_file_name, order_num, triangle_num, ...
    triangle_node );

  return
end
function [ word, done ] = word_next_read ( s, done )

%*****************************************************************************80
%
%% WORD_NEXT_READ "reads" words from a string, one at a time.
%
%  Special cases:
%
%    The following characters are considered to be a single word,
%    whether surrounded by spaces or not:
%
%      " ( ) { } [ ]
%
%    Also, if there is a trailing comma on the word, it is stripped off.
%    This is to facilitate the reading of lists.
%
%  Modified:
%
%    24 September 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string S, a string, presumably containing words
%    separated by spaces.
%
%    Input, logical DONE.
%    TRUE, if we are beginning a new string;
%    FALSE, if we are continuing to process the current string.
%
%    Output, string WORD.
%    If DONE is FALSE, then WORD contains the "next" word read.
%    If DONE is TRUE, then WORD is blank, because there was no more to read.
%
%    Output, logical DONE.
%      FALSE if another word was read,
%      TRUE if no more words could be read.
%
  persistent lenc;
  persistent next;

  tab = char ( 9 );
%
%  We "remember" LENC and NEXT from the previous call.
%
%  An input value of DONE = TRUE signals a new line of text to examine.
%
  if ( done )

    next = 1;
    done = 0;
    lenc = s_len_trim ( s );

    if ( lenc <= 0 )
      done = 1;
      word = ' ';
      return
    end

  end
%
%  Beginning at index NEXT, search the string for the next nonblank,
%  which signals the beginning of a word.
%
  ilo = next;
%
%  ...S(NEXT:) is blank.  Return with WORD = ' ' and DONE = TRUE.
%
  while ( 1 )

    if ( lenc < ilo )
      word = ' ';
      done = 1;
      next = lenc + 1;
      return
    end
%
%  If the current character is blank, skip to the next one.
%
    if ( s(ilo) ~= ' ' & s(ilo) ~= tab )
      break
    end

    ilo = ilo + 1;

  end
%
%  ILO is the index of the next nonblank character in the string.
%
%  If this initial nonblank is a special character,
%  then that's the whole word as far as we're concerned,
%  so return immediately.
%
  if ( s(ilo) == '"' | ...
       s(ilo) == '(' | ...
       s(ilo) == ')' | ...
       s(ilo) == '{' | ...
       s(ilo) == '}' | ...
       s(ilo) == '[' | ...
       s(ilo) == ']' )

    word = s(ilo);
    next = ilo + 1;
    return

  end
%
%  Now search for the last contiguous character that is not a
%  blank, TAB, or special character.
%
  next = ilo + 1;

  while ( next <= lenc )

    if ( s(next) == ' ' )
      break;
    elseif ( s(next) == tab )
      break;
    elseif ( s(next) == '"' )
      break;
    elseif ( s(next) == '(' )
      break;
    elseif ( s(next) == ')' )
      break;
    elseif ( s(next) == '{' )
      break;
    elseif ( s(next) == '}' )
      break;
    elseif ( s(next) == '[' )
      break;
    elseif ( s(next) == ']' )
      break;
    end

    next = next + 1;

  end

  if ( s(next-1) == ',' )
    word = s(ilo:next-2);
  else
    word = s(ilo:next-1);
  end

  return
end


function evalRP_multicut_waf(expidxs,bSave)

fprintf('evalRP_multicut()\n');

if (nargin < 2)
    bSave = true;
end

fontSize = 18;
% figure(100); clf; hold on;
legendName = cell(0);
set(0,'DefaultAxesFontSize', fontSize)
set(0,'DefaultTextFontSize', fontSize)

prefix = 'pck-head-rpc-';
[~,parts] = util_get_parts24();
nJoints = 14;
pck_thresh = 0.5;

% clusSizeThresh = 15;

rootDir = '/BS/leonid-people-3d/work/data/WeAreFamily_Stickmen_v1.02';
addpath([rootDir '/code']);
addpath([rootDir '/code/utils']);

GTWAF = ReadStickmenAnnotationTxtMulti('/BS/leonid-people-3d/work/data/WeAreFamily_Stickmen_v1.02//data/waf_sticks_all.txt');
annolistWAF_gt = GTWAF(351:end);

for expidx = expidxs
    fprintf('**********************************************************************************\n');
    % load experiment parameters
    p = rcnn_exp_params(expidx);

    if (isfield(p,'nms_thresh_det'))
        nms_thresh_det = p.nms_thresh_det;
    else
        nms_thresh_det = 0.5;
    end

    load(p.testGT);
    annolist_gt = annolist%(1:300);

    mkdir_if_missing(p.latexDir);
    mkdir_if_missing(p.plotsDir);

    assert(length(p.pidxs) == nJoints);

    if (isfield(p,'clusSizeThresh'))
        clusSizeThresh = p.clusSizeThresh;
    else
        clusSizeThresh = 1;
    end

    % load keypoints
    if (isfield(p,'multicut') && p.multicut == true)
        [keypointsAll,imgidxs_missing] = det2keypointsImgMulticutMulti(expidx,parts,annolist_gt,clusSizeThresh);
        annolistWAF_det = backproject_waf(expidx,keypointsAll,annolistWAF_gt);
    end

    annolist_gt(imgidxs_missing) = [];
    keypointsAll(imgidxs_missing) = [];

    assert(length(annolist_gt) == length(keypointsAll));
    [scoresAll, labelsAll, nGTall] = assignGTMulticutMulti(keypointsAll,annolist_gt,p.pidxs,parts,pck_thresh);

%     groups = {0,2,4,5,7,9,12,14,16,17,19,21,22,23};
    partLabels = {'rankle','rknee','rhip','lhip','lknee','lankle','rwrist','relbow','rshoulder','lshoulder','lelbow','lwrist','neck','tophead'};

    apAll = zeros(length(p.pidxs),1);
%     figure(100); clf;

    for i = 1:length(p.pidxs)
        scores = [];
        labels = [];
        for imgidx = 1:length(annolist_gt)
            scores = [scores; scoresAll{i}{imgidx}];
            labels = [labels; labelsAll{i}{imgidx}];
        end
        [precision,recall,sorted_scores,sortidx,sorted_labels] = getRPC(scores,labels,sum(nGTall(i,:)));
        ap = VOCap(recall,precision)*100;
        apAll(i) = ap;
        legendName = sprintf('%s, AP: %1.1f%%', p.name, ap);
        fprintf('%s\n',legendName);

%         plotRPC(precision,recall,p.colorName,'-',partLabels{i});
%         legend(legendName,'Location','NorthWest');
%         if (bSave)
%             print(gcf, '-dpng', [p.plotsDir '/' prefix partLabels{i} '-' 'expidx' num2str(expidx) '.png']);
%             printpdf([p.plotsDir '/' prefix partLabels{i} '-' 'expidx' num2str(expidx) '.pdf']);
%         end
    end
    if (bSave)
        tableFilename = [p.latexDir '/ap-expidx' num2str(expidx) '.tex'];
        apAll(15,:) = mean(apAll(7:14));
        apAll(16,:) = mean(apAll);
        [row, header] = genTable(apAll,p.name);
        fid = fopen(tableFilename,'wt');assert(fid ~= -1);
        fprintf(fid,'%s\n',row{1});fclose(fid);
        fid = fopen([p.latexDir '/ap-header.tex'],'wt');assert(fid ~= -1);
        fprintf(fid,'%s\n',header);fclose(fid);
    end
end
end


function pts = DIR_get_all_points_for_the_case(caseN, basepth)
    cn = num2str(caseN);
    path = [basepth, ...
            '4dCT/Case', cn, 'Pack/Case', cn, 'Pack/ExtremePhases/'];
    pts = struct();
    pts.extreme.b = read_DIR_points_file([path, 'Case', cn, ...
        '_300_T00_xyz.txt']);
    pts.extreme.e = read_DIR_points_file([path, 'Case', cn, ...
        '_300_T50_xyz.txt']);

    path2 = [basepth, ...
            '4dCT/Case', cn, 'Pack/Case', cn, 'Pack/Sampled4D/'];
    for i = 1 : 6
        ni = num2str(i - 1);
        pts.smp{i}.pts = read_DIR_points_file([path2, 'case', cn, ...
            '_4D-75_T', ni, '0.txt']);
    end
end


function isargmatrix(varargin)
%ISARGMATRIX throws an error if not a matrix
%
%   Usage: isargmatrix(arg1,arg2,...)
%
%   Input parameters:
%       args        - list of args
%
%   See also: isargvector, isargscalar

%*****************************************************************************
% The MIT License (MIT)                                                      *
%                                                                            *
% Copyright (c) 2010-2019 SFS Toolbox Developers                             *
%                                                                            *
% Permission is hereby granted,  free of charge,  to any person  obtaining a *
% copy of this software and associated documentation files (the "Software"), *
% to deal in the Software without  restriction, including without limitation *
% the rights  to use, copy, modify, merge,  publish, distribute, sublicense, *
% and/or  sell copies of  the Software,  and to permit  persons to whom  the *
% Software is furnished to do so, subject to the following conditions:       *
%                                                                            *
% The above copyright notice and this permission notice shall be included in *
% all copies or substantial portions of the Software.                        *
%                                                                            *
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
% IMPLIED, INCLUDING BUT  NOT LIMITED TO THE  WARRANTIES OF MERCHANTABILITY, *
% FITNESS  FOR A PARTICULAR  PURPOSE AND  NONINFRINGEMENT. IN NO EVENT SHALL *
% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
% LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT, TORT  OR OTHERWISE, ARISING *
% FROM,  OUT OF  OR IN  CONNECTION  WITH THE  SOFTWARE OR  THE USE  OR OTHER *
% DEALINGS IN THE SOFTWARE.                                                  *
%                                                                            *
% The SFS Toolbox  allows to simulate and  investigate sound field synthesis *
% methods like wave field synthesis or higher order ambisonics.              *
%                                                                            *
% https://sfs.readthedocs.io                            sfstoolbox@gmail.com *
%*****************************************************************************

%% ===== Checking for matrix =============================================
for ii = 1:nargin
    if ~isnumeric(varargin{ii}) || ndims(varargin{ii})~=2
        error('%s need to be a matrix.',inputname(ii));
    end
end


function wfdb2mat(varargin)
%
% wfdm2mat(recordName,signaList,N,N0)
%
%    Wrapper to WFDB WFDB2MAT:
%         http://physionet.org/physiotools/wag/wfdb2m-1.htm
%
% Converts a WFDB-compatible signal file to MATLAB/Octave *.mat file.
% The output files are recordNamem.mat and recordNamem.hea. The standard output of
% WFDB2MAT will be saved in a file recordNamem.info.
%
% Required Parameters:
%
% recorName
%       String specifying the name of the record in the WFDB path or
%       in the current directory.
%
% Optional Parameters are:
%
% signalList
%       A Mx1 array of integers. Read only the signals (columns)
%       named in the signalList (default: read all signals).
% N
%       A 1x1 integer specifying the sample number at which to stop reading the
%       record file (default read all the samples = N).
% N0
%       A 1x1 integer specifying the sample number at which to start reading the
%       record file (default 1 = first sample).
%
%
%
% NOTE:
%       You can use the WFDB2MAT command in order to convert the record data into a *.mat file,
%       which can then be loaded into MATLAB/Octave's workspace using the LOAD command.
%       This will load the signal data in raw units (use RDMAT to load the signal in physical units).
%
%
% Written by Ikaro Silva, 2014
% Last Modified: September 15, 2014
% Version 0.1
%
% Since 0.9.7
%
% %Example:
% wfdb2mat('mitdb/200')
% [tm,signal,Fs,labels]=rdmat('200m');
%
%
% See also RDSAMP, RDMAT

%endOfHelp

[javaWfdbExec,config]=getWfdbClass('wfdb2mat');

%Set default pararameter values
inputs={'recordName','signalList','N','N0'};
signalList=[];
N=[];
N0=1;
for n=1:nargin
    if(~isempty(varargin{n}))
        eval([inputs{n} '=varargin{n};']);
    end
end

wfdb_argument={'-r',recordName,'-f',['s' num2str(N0-1)]};

if(~isempty(N))
    wfdb_argument{end+1}='-t';
    wfdb_argument{end+1}=['s' num2str(N)];
end

if(~isempty(signalList))
    wfdb_argument{end+1}='-s ';
    %-1 is necessary because WFDB is 0 based indexed.
    for sInd=1:length(signalList)
        wfdb_argument{end+1}=[num2str(signalList(sInd)-1)];
    end
end

data=javaWfdbExec.execToStringList(wfdb_argument);


function a = imag(a)
%IMAG         imaginary part of taylor
%
%   c = imag(a)
%
%

% written  05/21/09     S.M. Rump
%

  a.t = imag(a.t);


imgDataDir = ['rgbd'];
imgDataOutDir = ['rgd'];

imgFiles = dir([imgDataDir '/rgb*']);
imgDepthFiles = dir([imgDataDir '/depth*']);

for idx = 1:length(imgFiles)
    display(['processing imgFiles ' int2str(idx)])

    % read rgb
    imgName = imgFiles(idx).name;
    [pathstr,imgname] = fileparts(imgName);
    rgb = imread([imgDataDir '/' imgname '.jpg']);

    % read depth
    imgDepthName = imgDepthFiles(idx).name;
    [pathstr,imgdepthname] = fileparts(imgDepthName);
    depth = imread([imgDataDir '/' imgdepthname '.png']);

    % re-ragne to 0~225
    depth = (double(depth)-500)/(1200-500)*255;
    depthImgUint = uint8(depth);

    % insert depth to th 3rd channel
    rgb(:,:,3) = depthImgUint;

    % saving rgd
    imwrite(rgb, [imgDataOutDir '/rgd' imgname(end-4:end) '.png']);
end


function saveExpression(obj, export_path, varargin)
    % save the symbolic expressions of the constraints matrices to MX
    % binary files
    %
    % Parameters:
    %  export_path: the path to export the file @type char
    %  varargin: variable input parameters @type varargin
    %   ForceExport: force the export @type logical

    cellfun(@(x)save_funcs(x,export_path, varargin{:}), obj.ActualFuncs, ...
        'UniformOutput',false);
    cellfun(@(x)save_funcs(x,export_path, varargin{:}), obj.DesiredFuncs, ...
        'UniformOutput',false);

    %     if ~isempty(obj.OutputFuncs)
    %         cellfun(@(x)save_funcs(x,export_path, varargin{:}), obj.OutputFuncs, ...
    %             'UniformOutput',false);
    %     end

    if ~isempty(obj.tau_)
        cellfun(@(x)save_funcs(x,export_path, varargin{:}), obj.PhaseFuncs, ...
            'UniformOutput',false);
    end

    function save_funcs(x, export_path, varargin)
        if ~isempty(x), save(x,export_path, varargin{:}); end
    end
end


% MIPS
%   Version 1.5         12-Dec-2022
%
%   The MATPOWER Interior Point Solver (MIPS) is a package of MATLAB/Octave
%   M-files for solving non-linear programming problems (NLPs) using a
%   primal dual interior point method. MIPS is based on code written in C
%   language by Hongye Wang as a graduate student at Cornell University
%   for optimal power flow applications. It was later ported to the
%   MATLAB/Octave language by Ray D. Zimmerman for use in MATPOWER.
%
%   The latest version of MIPS can be found on GitHub at:
%
%       https://github.com/MATPOWER/mips
%
%   MIPS is covered by the 3-clause BSD License (see LICENSE for details).

%   MIPS
%   Copyright (c) 2010-2022, Power Systems Engineering Research Center (PSERC)
%   by Ray Zimmerman, PSERC Cornell
%
%   This file is part of MIPS.
%   Covered by the 3-clause BSD License (see LICENSE file for details).
%   See https://github.com/MATPOWER/mips for more info.


classdef PTKAirwaysLabelledByBronchus < PTKPlugin
    % PTKAirwaysLabelledByBronchus. Plugin to visualise the airway tree bronchus by bronchus
    %
    %     This is a plugin for the Pulmonary Toolkit. Plugins can be run using
    %     the gui, or through the interfaces provided by the Pulmonary Toolkit.
    %     See PTKPlugin.m for more information on how to run plugins.
    %
    %     Plugins should not be run directly from your code.
    %
    %     PTKAirwaysLabelledByBronchus calls the PTKAirways plugin to segment the
    %     airway tree. It then cretes an output labelled image where each
    %     bronchus is labelled with contrasting colour values, starting with 1
    %     for the trachea. The child segments of each bronchus are labelled
    %     consecutively starting from the parent bronchus plus 1. Eg. if a
    %     parent is labeled 3, then its children will be labelled 4,5,6 etc.
    %     This makes the heirarcy clear from the image.

    %     The output image is intended to be visualised using the Lines
    %     colourmap; for this reason the grey colours (multiples of 7) are
    %     skipped to avoid confusion when used as an overlay on top of a
    %     greyscale image.
    %
    %
    %     Licence
    %     -------
    %     Part of the TD Pulmonary Toolkit. https://github.com/tomdoel/pulmonarytoolkit
    %     Author: Tom Doel, 2012.  www.tomdoel.com
    %     Distributed under the GNU GPL v3 licence. Please see website for details.
    %

    properties
        ButtonText = 'Airways <BR>by bronchus'
        ToolTip = 'Shows airways coloured by bronchus'
        Category = 'Airways'

        AllowResultsToBeCached = true
        AlwaysRunPlugin = false
        PluginType = 'ReplaceOverlay'
        HidePluginInDisplay = false
        FlattenPreviewImage = true
        PTKVersion = '1'
        ButtonWidth = 6
        ButtonHeight = 2
        GeneratePreview = true
        Visibility = 'Developer'
    end

    methods (Static)
        function results = RunPlugin(dataset, ~)
            results = dataset.GetTemplateImage(PTKContext.LungROI);
            airway_results = dataset.GetResult('PTKAirways');
            labeled_region = PTKAirwaysLabelledByBronchus.GetLabeledSegmentedImageFromAirwayTree(airway_results.AirwayTree, results);
            results.ChangeRawImage(labeled_region);
            results.ImageType = PTKImageType.Colormap;
        end
    end

    methods (Static, Access = private)

        function segmented_image = GetLabeledSegmentedImageFromAirwayTree(airway_tree, template)
            airway_tree.AddColourValues(1);
            segmented_image = zeros(template.ImageSize, 'uint8');

            segments_to_do = airway_tree;

            while ~isempty(segments_to_do)
                segment = segments_to_do(end);
                segments_to_do(end) = [];
                segmented_image(template.GlobalToLocalIndices(segment.GetAllAirwayPoints)) = segment.Colour;
                segments_to_do = [segments_to_do segment.Children];
            end
        end
    end
end


function varargout = imarray(varargin)
% VL_IMARRAY  Flattens image array
%   J=VL_IMARRAY(A) creates a mosaic J from the array of images A. A
%   can be either a M*N*K array, storing one gray-scale image per
%   slice, or a M*N*3*K or M*N*K*3 array, storing a true color RGB
%   image per slice. The function returns an image J which is a tiling
%   of the images in the array. Tiles are filled from left to right
%   and top to bottom.
%
%   VL_IMARRAY(...) displays the image J rather than returning it.
%
%   VL_IMARRAY() accepts the following options:
%
%   Spacing:: 0
%     Separate the images by a border of the specified width (the
%     border is assigned 0 value, which usually corresponds to black).
%
%   Layout:: empty
%     Specify a vector [TM TN] with the number of rows and columns of
%     the tiling. If equal to [] the layout is computed automatically.
%
%   Movie:: false
%     Display or return a movie instead of generating a tiling.
%
%   CMap:: []
%     Specify a colormap to construct a movie when the input is an
%     indexed image array. If not specified, MATLAB default colormap
%     is used.
%
%   Reverse:: true
%     Start filling the mosaic tiles from the bottom rather than from
%     the top.
%
%   See also:VL_IMARRAYSC(), VL_HELP().
[varargout{1:nargout}] = vl_imarray(varargin{:});


%SerialLink.issym Test if SerialLink object is a symbolic model
%
% res = R.issym() is true if the SerialLink manipulator R has symbolic parameters
%
%
% Authors::
%  Joern Malzahn, (joern.malzahn@tu-dortmund.de)

% Copyright (C) 1993-2015, by Peter I. Corke
%
% This file is part of The Robotics Toolbox for MATLAB (RTB).
%
% RTB is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% RTB 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 Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with RTB.  If not, see <http://www.gnu.org/licenses/>.
%
% http://www.petercorke.com
function res = issym(l)

	res = issym(l.links(1));

end


1     % GMRES/Bicgstab(2)
1e-6  % tolerance
100   % maximum number of iterations
3     % lst sqrs commutator preconditioner
1     % ideal
5     % Print to (new) Figure 4
3     % Color

% Data file for it_solve for NS2


% Type information on a property.
% This class encapsulates type, shape and domain constraints on property
% values.
%
% Examples:
% PropertyType('denserealsingle', 'scalar')
%    creates a non-sparse single real scalar with unrestricted value
% PropertyType('denserealdouble', 'scalar', [-1,1])
%    creates a non-sparse double real scalar with value in range -1 to 1
% PropertyType('char', 'row', {'spring','summer','fall','winter'})
%    creates a character array which may be either be 'spring', 'summer',
%    'fall' or 'winter'
% PropertyType('logical', 'column', {'A','B','C'})
%    creates a set whose elements are 'A', 'B' and 'C'; the logical vector
%    is an indexer into this set, e.g. [1 1 0] maps to the set {'A','B'}
%
% See also: PropertyGridField

% Copyright 2010 Levente Hunyadi
classdef PropertyType
    properties
        % The underlying MatLab type for the property.
        PrimitiveType = 'denserealdouble';
        % The expected dimensions for the property.
        Shape = 'scalar';
        % A cell array of possible property values (or {} if unrestricted).
        Domain = [];
    end
    properties (Access = protected)
        ObjectType = '';
    end
    methods
        function self = PropertyType(type, shape, domain)
            self.PrimitiveType = type;
            self.Shape = shape;
            if nargin > 2
                self.Domain = domain;
            end
        end

        function s = char(self)
        % Compact textual representation of property type information.
            if ~isempty(self.Shape)
                s = sprintf('%s/%s', self.PrimitiveType, self.Shape);
            else
                s = self.PrimitiveType;
            end
            if ~isempty(self.Domain)
                if iscellstr(self.Domain)
                    s = [s ' ' strjoin(',', self.Domain)];
                elseif isnumeric(self.Domain)
                    s = [s ' ' mat2str(self.Domain)];
                end
            end
        end

        function tf = islogical(self)
            tf = strcmp(self.PrimitiveType, 'logical');
        end

        function tf = isinteger(self)
            tf = any(strmatch(self.PrimitiveType, {'int8','uint8','int16','uint16','int32','uint32','int64','uint64'}, 'exact'));
        end

        function tf = isfloat(self)
            tf = any(strmatch(self.PrimitiveType, {'denserealsingle','denserealdouble','densecomplexsingle','densecomplexdouble','sparserealsingle','sparserealdouble','sparsecomplexsingle','sparsecomplexdouble'}, 'exact'));
        end

        function tf = isnumeric(self)
            tf = isinteger(self) || isfloat(self);
        end

        function tf = isreal(self)
            tf = any(strmatch(self.PrimitiveType, {'denserealsingle','denserealdouble','sparserealsingle','sparserealdouble'}, 'exact'));
        end

        function tf = is2d(self)
            tf = any(strmatch(self.Shape, {'row','column','matrix'}, 'exact'));
        end

        function tf = isvector(self)
            tf = any(strmatch(self.Shape, {'row','column'}, 'exact'));
        end

        function tf = isstring(self)
            tf = strcmp(self.PrimitiveType, 'char') && strcmp(self.Shape, 'row');
        end

        function tf = isset(self)
            tf = islogical(self) && isvector(self) && ~isempty(self.Domain);
        end

        function self = set.PrimitiveType(self, type)
            validateattributes(type, {'char'}, {'nonempty','row'});
            self.PrimitiveType = validatestring(type, { ...
                'logical', ...
                'char', ...
                'int8','uint8','int16','uint16','int32','uint32','int64','uint64', ...
                'denserealsingle','denserealdouble', ...
                'densecomplexsingle','densecomplexdouble', ...
                'sparserealsingle','sparserealdouble', ...
                'sparsecomplexsingle','sparsecomplexdouble', ...
                'cellstr', ...
                'object'});
        end

        function self = set.Shape(self, shape)
            validateattributes(shape, {'char'}, {'nonempty','row'});
            self.Shape = validatestring(shape, {'scalar','row','column','matrix','empty'});  % 'empty' is a pseudo-shape for the 0-by-0 empty matrix
        end

        function self = set.Domain(self, domain)
            if isempty(domain)
                self.Domain = [];
                return;
            end
            if ~isscalar(self) && ~isstring(self) && ~(islogical(self) && isvector(self))
                error('PropertyType:InvalidArgumentValue', ...
                    'Domain can be set only for scalars, strings or logical vectors.');
            end
            if iscell(domain)
                validateattributes(domain, {'cell'}, {'vector'});
                if ~(islogical(self) && isvector(self))  % interpret as exhaustive enumeration of domain elements
                    for k = 1 : numel(domain)
                        assert(self.CanAccept(domain{k}), ...
                            'PropertyType:InvalidArgumentValue', ...
                            'Invalid value specified for property domain.');
                    end
                end
            elseif isnumeric(domain)  % interpret as numeric range for domain elements
                validateattributes(domain, {'numeric'}, {'vector'});
                assert(isnumeric(self), 'PropertyType:ArgumentTypeMismatch', ...
                    'Closed interval domain is meaningful only for numeric data.');
                assert(length(domain) == 2, 'PropertyType:InvalidArgumentValue', ...
                    'Closed interval data is expected in the form [a,b] where a and b are numbers.');
                domain = [min(domain) max(domain)];
            else
                error('PropertyType:InvalidArgumentValue', ...
                    'Closed interval specification [a,b] or explicit enumeration {a,b,c,...} is expected.');
            end
            self.Domain = domain;
        end

        function tf = CanAccept(self, value, precisionloss)
        % Whether the property can accept the given value.
        %
        % Output arguments:
        % tf:
        %    false if any of the property constaints (type, shape or
        %    domain) would be violated
            validateattributes(self, {'PropertyType'}, {'scalar'});
            if nargin < 3
                precisionloss = false;
            end
            if isobject(value)
                tf = ~isempty(self.ObjectType) && metaclass(value) <= meta.class.fromName(self.ObjectType);
            elseif (isnumeric(value) || islogical(value) || ischar(value)) && any(isnan(value(:)));
                tf = false;
            else
                type = PropertyType.AutoDiscoverType(value);
                shape = PropertyType.AutoDiscoverShape(value);
                tf = PropertyType.CanAcceptType(self.PrimitiveType, type, precisionloss) ...
                    && PropertyType.CanAcceptShape(self.Shape, shape) ...
                    && self.CanAcceptValue(value);
            end
        end

        function clazz = GetPrimitiveMatLabType(self)
            validateattributes(self, {'PropertyType'}, {'scalar'});
            switch (self.PrimitiveType)
                case {'logical','char','int8','uint8','int16','uint16','int32','uint32','int64','uint64'}
                    clazz = self.PrimitiveType;
                case {'denserealsingle','densecomplexsingle','sparserealsingle','sparsecomplexsingle'}
                    clazz = 'single';
                case {'denserealdouble','densecomplexdouble','sparserealdouble','sparsecomplexdouble'}
                    clazz = 'double';
                case 'cellstr'
                    clazz = 'cell';
            end
        end

        function javatype = GetPrimitiveJavaType(self)
            validateattributes(self, {'PropertyType'}, {'scalar'});
            switch self.PrimitiveType
                case {'denserealdouble','sparserealdouble'}  % add a double-precision floating point property
                    matlabtype = 'double';  % MatLab type that is marshalled to Java
                case {'denserealsingle','sparserealsingle'}  % add a single-precision floating point property
                    matlabtype = 'single';
                case {'int8','uint8','int16'}
                    matlabtype = 'int16';
                case {'uint16','int32'}  % add an integer property
                    matlabtype = 'int32';
                case {'uint32','int64'}
                    matlabtype = 'int64';
                case 'logical'  % add a logical property
                    matlabtype = 'logical';
                case {'densecomplexdouble','sparsecomplexdouble','densecomplexsingle','sparsecomplexsingle'}
                    matlabtype = 'cellstr';
                otherwise
                    error('MatrixEditor:ArgumentTypeMismatch', 'Type %s is not supported.', self.PrimitiveType);
            end
            javatype = javaclass(matlabtype);
        end

        function javavalue = GetPrimitiveJavaValue(self, value)
            validateattributes(self, {'PropertyType'}, {'scalar'});
            switch self.PrimitiveType
                case {'denserealdouble','sparserealdouble'}  % add a double-precision floating point property
                    javavalue = java.lang.Double(value);
                case {'denserealsingle','sparserealsingle'}  % add a single-precision floating point property
                    javavalue = java.lang.Float(value);
                case {'int8','uint8','int16'}
                    javavalue = java.lang.Short(value);
                case {'uint16','int32'}  % add an integer property
                    javavalue = java.lang.Integer(value);
                case {'uint32','int64'}
                    javavalue = java.lang.Long(value);
                case 'logical'  % add a logical property
                    javavalue = java.lang.Boolean(value);
                case {'densecomplexdouble','sparsecomplexdouble','densecomplexsingle','sparsecomplexsingle'}
                    javavalue = java.lang.String(mat2str(value));
                otherwise
                    if isnumeric(value) || islogical(value)
                        javavalue = mat2str(value);
                    else
                        javavalue = char(value);
                    end
                    %error('PropertyType:ArgumentTypeMismatch', 'Type %s is not supported.', self.PrimitiveType);
            end
        end

        function javamatrix = GetJavaVectorOfVectors(self, matrix)
            assert(isnumeric(self) || islogical(self), 'PropertyType:InvalidOperation', ...
                'Operation supported on numeric and logical matrices only.');
            javamatrix = java.util.Vector(int32(size(matrix,1)));
            for m = 1 : size(matrix,1)
                javarow = java.util.Vector(int32(size(matrix,2)));
                javamatrix.add(javarow);
                for n = 1 : size(matrix,2)
                    javarow.add(self.GetPrimitiveJavaValue(matrix(m,n)));
                end
            end
        end

        function javamatrix = GetJavaMatrix(self, matrix)
        % Get MatLab value as Java 2d array of proper type.
            assert(isnumeric(self), 'PropertyType:InvalidOperation', ...
                'Operation supported on numeric matrices only.');
            assert(numel(matrix) > 0, 'PropertyType:InvalidOperation', ...
                'Empty values are not supported.');
            javatype = self.GetPrimitiveJavaType();
            javamatrix = javaArray(char(javatype.getName()), size(matrix,1), size(matrix,2));
            for m = 1 : size(matrix,1)
                for n = 1 : size(matrix,2)
                    javamatrix(m,n) = self.GetPrimitiveJavaValue(matrix(m,n));
                end
            end
        end

        function javavector = GetJavaVector(self, vector)
        % Get MatLab value as a Java vector of proper type.
            assert(isnumeric(self), 'PropertyType:InvalidOperation', ...
                'Operation supported on numeric matrices only.');
            assert(numel(vector) > 0, 'PropertyType:InvalidOperation', ...
                'Empty values are not supported.');
            javatype = self.GetPrimitiveJavaType();
            javavector = javaArray(char(javatype.getName()), numel(vector));
            for k = 1 : numel(vector)
                javavector(k) = self.GetPrimitiveJavaValue(vector(k));
            end
        end

        function javavalue = ConvertToJava(self, value)
        % Converts a MatLab value into the appropriate Java object.
            switch self.Shape
                case 'scalar'
                    javavalue = self.GetPrimitiveJavaValue(value);
                case {'row','column'}
                    switch self.PrimitiveType
                        case 'char'  % add a string property
                            if strcmp(self.Shape, 'row')
                                javavalue = value;
                            else
                                javavalue = mat2str(value);
                            end
                        case 'cellstr'
                            javavalue = java.lang.String(strjoin(sprintf('\n'), value));
                        case 'logical'
                            if ~isempty(self.Domain)
                                javavalue = javaStringArray(self.Domain(value));  % value is an indicator vector
                            else
                                javavalue = mat2str(value);
                            end
                        otherwise
                            if isnumeric(value) || islogical(value)
                                javavalue = mat2str(value);
                            else
                                javavalue = char(value);
                            end
                    end
                case 'empty'
                    javavalue = [];
                otherwise
                    if isnumeric(value) || islogical(value)
                        javavalue = mat2str(value);
                    else
                        javavalue = char(value);
                    end
            end
        end

        function [value,stringconversion] = ConvertFromJava(self, javavalue)
        % Converts a Java object into the appropriate MatLab value.
            stringconversion = false;
            switch self.Shape
                case 'scalar'
                    switch self.PrimitiveType
                        case 'denserealdouble'
                            value = full(double(javavalue));
                        case 'sparserealdouble'
                            value = sparse(double(javavalue));
                        case 'denserealsingle'
                            value = full(single(javavalue));
                        case 'sparserealsingle'
                            value = sparse(single(javavalue));
                        case {'int8','uint8','int16','uint16','int32','uint32','int64','logical'}
                            value = cast(javavalue, self.PrimitiveType);
                        case {'densecomplexdouble','sparsecomplexdouble','densecomplexsingle','sparsecomplexsingle'}
                            value = self.ConvertFromString(javavalue);
                            stringconversion = true;
                    end
                case {'row','column'}
                    switch self.PrimitiveType
                        case 'char'  % add a string property
                            if strcmp(self.Shape, 'row')
                                value = char(javavalue);
                            else
                                value = self.ConvertFromString(javavalue);
                                stringconversion = true;
                                return;
                            end
                        case 'cellstr'
                            value = strsplit(javavalue);
                        case 'logical'
                            if ~isempty(self.Domain)
                                value = strsetmatch(cell(javavalue), self.Domain);
                            else
                                value = self.ConvertFromString(javavalue);
                                stringconversion = true;
                                return;
                            end
                        case {...
                                'denserealdouble','sparserealdouble','denserealsingle','sparserealsingle',...
                                'densecomplexdouble','sparsecomplexdouble','densecomplexsingle','sparsecomplexsingle',...
                                'int8','uint8','int16','uint16','int32','uint32','int64','uint64'}
                            value = self.ConvertFromString(javavalue);
                            stringconversion = true;
                    end
                    switch self.Shape
                        case 'row'
                            value = reshape(value, 1, numel(value));
                        case 'column'
                            value = reshape(value, numel(value), 1);
                    end
                case 'matrix'
                    switch self.PrimitiveType
                        case {...
                                'denserealdouble','sparserealdouble','denserealsingle','sparserealsingle',...
                                'densecomplexdouble','sparsecomplexdouble','densecomplexsingle','sparsecomplexsingle',...
                                'char','int8','uint8','int16','uint16','int32','uint32','int64','uint64','logical'}
                            value = self.ConvertFromString(javavalue);
                            stringconversion = true;
                    end
            end
        end

        function value = ConvertFromString(self, text)
        % Converts matrix string representation to its numeric value.
        %
        % Input arguments:
        % text:
        %    a textual representation of a numeric scalar, vector or matrix
        %
        % Output arguments:
        % value:
        %    a numeric value satisfying all type constraints, or NaN if the
        %    string cannot be converted or the value cannot be coerced into
        %    the appropriate type
            text = char(text);
            switch self.Shape
                case 'scalar'
                    value = str2double(text);
                    status = ~isnan(value);
                otherwise
                    [value,status] = str2num(text); %#ok<ST2NM>
            end
            if all(int32(value(:)) == value(:))  % all numbers are integers
                value = int32(value);            % cast to integer
            end
            if ~status || ~self.CanAccept(value, true)
                value = NaN;
                return;
            end
            value = self.ConvertFromMatLab(value);
        end

        function value = ConvertFromMatLab(self, value)
        % Casts a MatLab value to the prescribed property type.
            if ~isreal(value) && isnumeric(self) && isreal(self)
                error('PropertyType:ArgumentTypeMismatch', 'Complex value cannot be coerced into a real type.');
            end
            if iscellstr(value) && strcmp(self.PrimitiveType, 'cellstr') || isobject(value) && strcmp(self.PrimitiveType, 'object')
                return
            end
            switch self.PrimitiveType
                case {'denserealdouble','densecomplexdouble'}
                    value = full(double(value));
                case {'sparserealdouble','sparsecomplexdouble'}
                    value = sparse(double(value));
                case {'denserealsingle','densecomplexsingle'}
                    value = full(single(value));
                case {'sparserealsingle','sparsecomplexsingle'}
                    value = sparse(single(value));
                case {'int8','uint8','int16','uint16','int32','uint32','int64','logical'}
                    value = cast(value, self.PrimitiveType);
                case {'char'}
                    value = char(value);
                otherwise
                    error('PropertyType:ArgumentTypeMismatch', 'Cannot coerce type %s into type %s.', class(value), self.PrimitiveType);
            end
        end
    end
    methods (Access = private)
        function tf = CanAcceptValue(self, value)
        % Whether the property constraints allow the value to be accepted.
            if islogical(self) && isvector(self)  % interpret logical vector as a set
                tf = isempty(self.Domain) || numel(value) == numel(self.Domain);  % size of logical vector corresponds to size of universe
            else  % test whether domain contains value
                tf = PropertyType.IsInDomain(self.Domain, value);
            end
        end
    end
    methods (Static)
        function obj = AutoDiscover(value)
        % Constructs a property type instance based on a value.
        % The property type is chosen to be the most specific possible that
        % fits the given value.
            if isobject(value)
                obj = PropertyType('object', PropertyType.AutoDiscoverShape(value));
                obj.ObjectType = class(value);
            else
                obj = PropertyType(PropertyType.AutoDiscoverType(value), PropertyType.AutoDiscoverShape(value));
            end
        end

        function type = AutoDiscoverType(value)
            clazz = class(value);
            switch clazz
                case {'logical','char','int8','uint8','int16','uint16','int32','uint32','int64','uint64'}
                    type = clazz;
                case {'single','double'}
                    if issparse(value)
                        sparsity = 'sparse';
                    else
                        sparsity = 'dense';
                    end
                    if isreal(value)
                        complexity = 'real';
                    else
                        complexity = 'complex';
                    end
                    type = [ sparsity complexity clazz ];
                case 'cell'
                    if iscellstr(value)
                        type = 'cellstr';
                    else
                        error('PropertyType:InvalidArgumentValue', ...
                            'Cell arrays other than cell array of strings are not supported.');
                    end
                otherwise
                    error('PropertyType:InvalidArgumentValue', ...
                        'Argument type "%s" is not supported.', class(value));
            end
        end

        function shape = AutoDiscoverShape(value)
            if ndims(value) > 2
                error('PropertyType:InvalidArgumentValue', ...
                    'Dimensions higher than 2 are not supported.');
            end
            if size(value,1) == 1 && size(value,2) == 1
                shape = 'scalar';
            elseif size(value,1) == 1
                shape = 'row';
            elseif size(value,2) == 1
                shape = 'column';
            elseif size(value,1) == 0 && size(value,2) == 0
                shape = 'empty';  % no dimensions
            else
                shape = 'matrix';
            end
        end

        function tf = CanAcceptType(generaltype, specifictype, precisionloss)
        % Type assignment check.
        %
        % Output arguments:
        % tf:
        %    true if a variable of the specific type could be assigned to a
        %    variable of the general type
            validateattributes(generaltype, {'char'}, {'nonempty','row'});
            validateattributes(specifictype, {'char'}, {'nonempty','row'});
            if nargin < 3
                precisionloss = false;
            end
            if strcmp(generaltype, specifictype)
                tf = true;
                return;
            end
            switch generaltype
                case {'densecomplexdouble','sparsecomplexdouble'}
                    type = {...
                        'int8','uint8','int16','uint16','int32','uint32','int64','uint64', ...
                        'denserealsingle','denserealdouble', ...
                        'densecomplexsingle','densecomplexdouble', ...
                        'sparserealsingle','sparserealdouble', ...
                        'sparsecomplexsingle','sparsecomplexdouble'};
                case {'denserealdouble','sparserealdouble'}
                    type = {...
                        'int8','uint8','int16','uint16','int32','uint32','int64','uint64', ...
                        'denserealsingle','denserealdouble', ...
                        'sparserealsingle','sparserealdouble'};
                case {'densecomplexsingle','sparsecomplexsingle'}
                    type = {...
                        'int8','uint8','int16','uint16','int32','uint32','int64','uint64', ...
                        'denserealsingle','densecomplexsingle','sparserealsingle','sparsecomplexsingle'};
                    if precisionloss  % permit loss of precision
                        type = [type {'denserealdouble','densecomplexdouble','sparserealdouble','sparsecomplexdouble'}];
                    end
                case {'denserealsingle','sparserealsingle'}
                    type = {...
                        'int8','uint8','int16','uint16','int32','uint32','int64','uint64', ...
                        'denserealsingle','sparserealsingle'};
                    if precisionloss  % permit loss of precision
                        type = [type {'denserealdouble','sparserealdouble'}];
                    end
                case {'int64','uint64'}
                    type = {'int8','uint8','int16','uint16','int32','uint32'};
                case {'int32','uint32'}
                    type = {'int8','uint8','int16','uint16'};
                case {'int16','uint16'}
                    type = {'int8','uint8'};
                case {'int8','uint8'}
                    type = {};
                case 'char'
                    type = {};
                case 'logical'
                    type = {'int8','uint8','int16','uint16','int32','uint32'};
                case 'cellstr'
                    type = {};
                otherwise
                    type = {};
            end
            tf = any(strmatch(specifictype, type, 'exact'));
        end

        function tf = CanAcceptShape(generalshape, specificshape)
        % Shape assignment check.
        %
        % Output arguments:
        % tf:
        %    true if a variable of the specific shape could be assigned to
        %    a variable of the general shape
            validateattributes(generalshape, {'char'}, {'nonempty','row'});
            validateattributes(specificshape, {'char'}, {'nonempty','row'});
            if strcmp(generalshape, specificshape)
                tf = true;
                return;
            end
            switch generalshape
                case 'matrix'
                    shape = {'scalar','row','column','empty'};
                case 'row'
                    shape = {'scalar','empty'};
                case 'column'
                    shape = {'scalar','empty'};
                case 'scalar'
                    shape = {};
                case 'empty'
                    shape = {};
                otherwise
                    shape = {};
            end
            tf = any(strmatch(specificshape, shape, 'exact'));
        end

        function tf = IsInDomain(domain, value)
            if isempty(domain)
                tf = true;
            elseif iscellstr(domain)
                tf = any(strcmp(value, domain));
            elseif iscell(domain)
                tf = any(cellfun(@(v) v==value, domain));
            elseif isnumeric(domain) && length(domain) == 2
                tf = value >= min(domain) && value <= max(domain);
            end
        end
    end
end


function [data] = spm2fieldtrip(D)

% SPM2FIELDTRIP converts an SPM8 meeg object into a FieldTrip raw data structure
%
% Use as
%   data = spm2fieldtrip(D)
% where D is the SPM meeg object which you can load in with SPM_EEG_LOAD
% and where data is a FieldTrip raw data structure as if it were returned
% by FT_PREPROCESSING.
%
% See also FT_PREPROCESSING, SPM_EEG_LOAD

if ~ft_hastoolbox('spm8up')
  % it should be version spm8 or higher, since spm99, spm2 and spm5 did not yet the "meeg" object
  ft_error('this requires SPM8 or later to be on your MATLAB path');
end

if ~isa(D, 'meeg')
  ft_error('this requires an SPM "meeg" object as input')
end

% this is how SPM8 represents it
data = D.ftraw(0);

clist      = D.condlist;
conditions = D.conditions;

data.trialinfo = zeros(D.ntrials,1);
for k = 1:numel(clist)
  fprintf('mapping condition label "%s" to condition code %d\n', clist{k}, k);
  sel=strcmp(clist{k}, conditions);
  data.trialinfo(sel) = k;
end

% FIXME the following is not correct
%
% data.sampleinfo = zeros(ntrials,2);
% for i=1:ntrials
%   data.sampleinfo(i,1) = D.indsample(i);
%   data.sampleinfo(i,2) = D.indsample(i) + D.nsamples;
% end


function C = mrdivide(W,B)
   %MRDIVIDE (/) Slash or right matrix divide for WAVEFORMS.

   % VERSION: 1.0 of waveform objects
   % AUTHOR: Celso Reyes (celso@gi.alaska.edu)
   % LASTUPDATE: 3/15/2009

   if ~(isnumeric(B))
      error('Waveform:mrdivide:invalidNumeratorClass',...
         'Cannot divide by a %s, must be numeric', class(B));
   end

   C = set(W, 'data', get(W,'data') / double(B));
end


function outputStruct = runAlignment(fileName,outputPath,startImage,finalImage,parameters)
%runAlignment runs the alignment and segmentation routines on a .avi file
%   and saves the output files to a directorty
%
%   Input variables:
%
%       fileName -> avi file to be analyzed
%       outputPath -> path to which files are saved
%       startImage -> first image in path to be analyzed
%       finalImage -> last image in path to be analyzed
%       parameters -> struct containing non-default choices for parameters
%
%
%   Output variable:
%
%       outputStruct -> struct containing found alignment variables
%
% (C) Gordon J. Berman, 2014
%     Princeton University

    if ~exist(outputPath,'dir')
        mkdir(outputPath);
    end

    if nargin < 3 || isempty(startImage)
        startImage = 1;
    end

    if nargin < 4 || isempty(finalImage)
        finalImage = [];
    end

    if nargin < 5 || isempty(parameters)
        parameters = [];
    end

    parameters = setRunParameters(parameters);

    setup_parpool(parameters.numProcessors)

    [Xs,Ys,angles,areas,~,framesToCheck,svdskipped,areanorm] = ...
        alignImages_Radon_parallel_avi(fileName,startImage,finalImage,...
                                        outputPath,parameters);

    %See alignImages_Radon_parallel_avi for definitions of these variables
    outputStruct.Xs = Xs;
    outputStruct.Ys = Ys;
    outputStruct.angles = angles;
    outputStruct.areas = areas;
    outputStruct.parameters = parameters;
    outputStruct.framesToCheck = framesToCheck;
    outputStruct.svdskipped = svdskipped;
    outputStruct.areanorm = areanorm;

    if parameters.numProcessors > 1 && parameters.closeMatPool
        close_parpool
    end


function [ ALL_SCENE ] = packupScene( ALL_HYPS, CAN_POOL )
%PACKUPSCENE Summary of this function goes here
%   Detailed explanation goes here
global config

[H,W] = size(ALL_HYPS);
ALL_SCENE = cell(H,W);
all_objects = CAN_POOL.sel_hyps.objects;
room_obj.out_points_w = CAN_POOL.room.out_points_w;
room_obj.name = CAN_POOL.room.name;
room_obj.type = CAN_POOL.room.type;
room_obj.points = CAN_POOL.room.points;
room_obj.x_w = CAN_POOL.room.x_w;
room_obj = addBoundingBox(room_obj,'both');
room_obj.objtype = config.roomtypeid; % change this to be room id
for i = 1:H*W
    local = room_obj;
    sel_hyps = ALL_HYPS(i).sel_hyps;
    for j = 1:length(sel_hyps)
        if sel_hyps(j).fixed
            newObj = all_objects(sel_hyps(j).selID);
%             name = get_object_type_livingroom(j); % change this to be function
%             name = get_object_type(j); % change this to be function
            name = feval(config.typefunc, j);
            for k = 1:length(newObj)
                newObj(k).name = name{1};
                newObj(k).objtype = j;
            end
            local = [local; newObj];
        end
    end
    ALL_SCENE{i} = local;
end

end


function res = demo_DCFNet()
addpath(fullfile('..','DCFNet'));

init_rect = [129,80,64,78];
img_file = dir('./David/img/*.jpg');
img_file = fullfile('./David/img/', {img_file.name});
subS.init_rect = init_rect;
subS.s_frames = img_file;

param = [];
param.gpu = true;
gpuDevice(1);
param.visual = true;

res = run_DCFNet(subS,0,0,param);
disp(['fps: ',res.fps]);

end


function cl = atlas_spmanatomy_get_cluster(region_name)
% cl = atlas_spmanatomy_get_cluster(region_name)
%
% Returns a REGION object, cl, so that a named area from the SPM anatomy
% toolbox can be visualized.
%
% Requires SPM ANATOMY TOOLBOX V1.7 by Eickhoff (see code to update this.)
%
% For a list of valid region names, do not enter region_name:
% atlas_spmanatomy_get_cluster
%
% Example:
% ba44_cl = atlas_spmanatomy_get_cluster('Area 44');
%
% Visualize:
% cluster_orthviews(ba44_cl, {[0 0 1]}, 'add');
%
% Tor wager, Jan 2011

cl = region;

basename = 'AllAreas_v17_MPM.mat';
filename = which(basename);

if ~exist(filename, 'file')
    fprintf('Looking for atlas filename %s\nCannot find it.\n', basename)
    error('Exiting.')
end

load(filename)

imagename = which('AllAreas_v17.img');

if ~exist(imagename, 'file')
    fprintf('Looking for %s\nCannot find it.\n', imagename)
    error('Exiting.')
end

volInfo = iimg_read_img(imagename, 2);

names = char(MAP.name);

if nargin < 1 || isempty(region_name)
   disp('Run this function and enter a region name:')
   disp(names);
   return

end

%% Get info about chosen region

wh = strmatch(region_name, names, 'exact');

if isempty(wh)
    disp('Warning! No match.')
    return
end

info = MAP(wh);

% Transfer info
N = fieldnames(cl);
M = fieldnames(info);
for i = 1:length(M)
    iname = M{i};
    if any(strmatch(iname, N))
        cl.(iname) = info.(iname);
    end
end

% Add other info

cl.M = volInfo.mat;
cl.dim = volInfo.dim;
cl.voxSize = diag(volInfo.mat(1:3, 1:3));
cl.center = mean(cl.XYZ', 1);
cl.mm_center = mean(cl.XYZmm', 1);
cl.source_images = imagename;
cl.numVox = size(cl.XYZ, 2);
cl.shorttitle = sprintf('%s', region_name);
cl.title = sprintf('%s from %s', region_name, filename);
cl.descrip1 = sprintf('%s, entry %3.0f in %s, mapped using %s', region_name, wh, filename, imagename);

end


function drawText(x,y, drawString, fontSize, fontStyle, color, font, fontWeight, flagCenter)
%drawText Draws text to figure
%
% drawText(x,y, drawString, fontSize, fontStyle, color, font, fontWeight, flagCenter)
%
%INPUTS
% x             x coordinate
% y             y coordinate
% drawString    String to draw
%
%OPTIONAL INPUTS
% fontSize      Font size (Default = 12)
% fontStyle     Font style (Default = 'normal')
% color         Font color (Default = [0 0 0])
% font          Font (Default = 'sans-serif')
% fontWeight    Font weight (Default = 'normal')
% flagCenter    Center text on coordinate (Default = false)
%
global CB_MAP_OUTPUT
global mapHandle

if nargin < 4
    fontSize = 12;
end
if nargin < 5
    fontStyle = 'normal';
end
if nargin < 6
    color = [0 0 0];
end
if nargin < 7
    font = 'sans-serif';
end
if nargin <8
    fontWeight = 'normal';
end
if nargin < 9
    flagCenter = false;
end

if length(fontSize)>1
    error('Fontsize should be a scalar')
end

if iscell(drawString)
    display ('whoops - this shouldnt happen.  drawText.m')
%     drawString
%     whos('drawString')
    drawString = drawString{1};
end
if isnan(x) | isnan(y) | isnan(fontSize)
%     display ('whoops - this shouldnt happen.  drawText.m')
    return;
end
if strcmp(CB_MAP_OUTPUT, 'matlab')
    if find(color>1)
        color = color/255;
    end
    if flagCenter
        text(x,-y,drawString, 'FontSize', fontSize/2, 'color', color,'HorizontalAlignment','center');
    else
        text(x,-y,drawString, 'FontSize', fontSize/2, 'color', color);
    end
elseif strcmp(CB_MAP_OUTPUT, 'java')
    % need to insert code
elseif strcmp(CB_MAP_OUTPUT, 'svg')
    %determine type of color input
    if ischar(color)
        if color=='k'
            colorStroke = 'rgb(0,0,0)';
        else
            colorStroke = color;
        end
    else if isvector(color)
            colorStroke = strcat('rgb(',num2str(color(1)),',',num2str(color(2)),',',num2str(color(3)),')');
        end
    end
    drawString = regexprep(drawString,'&','&');
    fprintf(mapHandle, '<g style="font-family: %s; font-style: %s; font-weight: %s; stroke: none;">\n',font,fontStyle, fontWeight);
    if flagCenter
        %fprintf('<text style="fill: %s; text-rendering: optimizeLegibility;" x="%.2f" y="%.2f" font-size="%dpx">%s</text>\n</g>\n',colorStroke,x-(length(drawString)*fontSize*1.25),y+(5*fontSize),5*fontSize,drawString);
        fprintf(mapHandle,'<text style="fill: %s; text-rendering: optimizeLegibility;" x="%.2f" y="%.2f" font-size="%dpx">%s</text>\n</g>\n',colorStroke,x-(length(drawString)*fontSize*1.25),y+(5*fontSize),5*fontSize,drawString);
    else
        %code for debugging
%         fprintf('<text style="fill: %s; text-rendering: optimizeLegibility;" x="%.2f" y="%.2f" font-size="%dpx">%s</text>\n</g>\n',colorStroke,x,y,5*fontSize,drawString);
%         fprintf('\n%s\n','----')
%         disp(colorStroke)
%         class(colorStroke)
%         fprintf('%s\n','----')
%         disp(x)
%         class(x)
%         fprintf('%s\n','----')
%         disp(y)
%         class(y)
%         fprintf('%s\n','----')
%         disp(5*fontSize)
%         class(5*fontSize)
%         fprintf('%s\n','----')
%         disp(drawString)
%         class(drawString)
        fprintf(mapHandle,'<text style="fill: %s; text-rendering: optimizeLegibility;" x="%.2f" y="%.2f" font-size="%dpx">%s</text>\n</g>\n',colorStroke,x,y,5*fontSize,drawString);
    end
%     fprintf(mapHandle,'<text style="stroke: none;" x="%8.2f" y="%8.2f">%s</text>\n',x,-y,drawString);
else
    display('error CB_MAP_OUTPUT in drawText');
end