Browse Source

rm vector overloads and simplify api (#2290) [ci skip]

Alec Jacobson 2 years ago
parent
commit
1b07ebcf9e

+ 53 - 113
include/igl/copyleft/tetgen/mesh_to_tetgenio.cpp

@@ -13,154 +13,94 @@
 // STL includes
 #include <cassert>
 
-
-IGL_INLINE bool igl::copyleft::tetgen::mesh_to_tetgenio(
-  const std::vector<std::vector<REAL > > & V,
-  const std::vector<std::vector<int> > & F,
-  const std::vector<std::vector<REAL> > & H, 
-  const std::vector<std::vector<REAL> > & R, 
+template <
+  typename DerivedV, 
+  typename DerivedF, 
+  typename DerivedH, 
+  typename DerivedVM, 
+  typename DerivedFM, 
+  typename DerivedR>
+IGL_INLINE void igl::copyleft::tetgen::mesh_to_tetgenio(
+  const Eigen::MatrixBase<DerivedV>& V,
+  const Eigen::MatrixBase<DerivedF>& F,
+  const Eigen::MatrixBase<DerivedH>& H,
+  const Eigen::MatrixBase<DerivedVM>& VM,
+  const Eigen::MatrixBase<DerivedFM>& FM,
+  const Eigen::MatrixBase<DerivedR>& R,
   tetgenio & in)
 {
   using namespace std;
+  assert(V.cols() == 3 && "V should have 3 columns");
+  assert((VM.size() == 0 || VM.size() == V.rows()) && "VM should be empty or #V by 1");
+  assert((FM.size() == 0 || FM.size() == F.rows()) && "FM should be empty or #F by 1");
   in.firstnumber = 0;
-  in.numberofpoints = V.size();
+  in.numberofpoints = V.rows();
   in.pointlist = new REAL[in.numberofpoints * 3];
+  if(VM.size())
+  {
+    in.pointmarkerlist = new int[VM.size()];
+  }
   //loop over points
-  for(size_t i = 0; i < (size_t)V.size(); i++)
+  for(int i = 0; i < V.rows(); i++)
   {
-    assert(V[i].size() == 3);
-    in.pointlist[i*3+0] = V[i][0];
-    in.pointlist[i*3+1] = V[i][1];
-    in.pointlist[i*3+2] = V[i][2];    
+    in.pointlist[i*3+0] = V(i,0);
+    in.pointlist[i*3+1] = V(i,1);
+    in.pointlist[i*3+2] = V(i,2);    
+    if(VM.size())
+    {
+      in.pointmarkerlist[i] = VM(i);
+    }
   }
-  in.numberoffacets = F.size();
+  in.numberoffacets = F.rows();
   in.facetlist = new tetgenio::facet[in.numberoffacets];
   in.facetmarkerlist = new int[in.numberoffacets];
 
   // loop over face
-  for(size_t i = 0;i < (size_t)F.size(); i++)
+  for(int i = 0;i < F.rows(); i++)
   {
-    in.facetmarkerlist[i] = i;
+    in.facetmarkerlist[i] = FM.size() ? FM(i) : i;
     tetgenio::facet * f = &in.facetlist[i];
     f->numberofpolygons = 1;
     f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
     f->numberofholes = 0;
     f->holelist = NULL;
     tetgenio::polygon * p = &f->polygonlist[0];
-    p->numberofvertices = F[i].size();
+    p->numberofvertices = F.cols();
     p->vertexlist = new int[p->numberofvertices];
     // loop around face
-    for(int j = 0;j < (int)F[i].size(); j++)
+    for(int j = 0;j < F.cols(); j++)
     {
-      p->vertexlist[j] = F[i][j];
+      p->vertexlist[j] = F(i,j);
     }
   }
   
-  in.numberofholes = H.size(); 
-  in.holelist = new double[3 * in.numberofholes];
+  in.numberofholes = H.rows(); 
+  in.holelist = new REAL[3 * in.numberofholes];
   // loop over holes
-  for(size_t holeID = 0, nHoles = H.size(); holeID < nHoles; holeID++)
+  for(int holeID = 0; holeID < H.rows(); holeID++)
   {
-    in.holelist[holeID * 3 + 0] = H[holeID][0]; 
-    in.holelist[holeID * 3 + 1] = H[holeID][1];
-    in.holelist[holeID * 3 + 2] = H[holeID][2];
-  }	  
+    in.holelist[holeID * 3 + 0] = H(holeID,0); 
+    in.holelist[holeID * 3 + 1] = H(holeID,1);
+    in.holelist[holeID * 3 + 2] = H(holeID,2);
+  }  
 
-  in.numberofregions = R.size();
+  in.numberofregions = R.rows();
   in.regionlist = new REAL[ 5 * in.numberofregions];
   // loop over regions
-  for(size_t regionID = 0, nRegions = R.size(); regionID < nRegions; regionID++)
+  for(int regionID = 0; regionID < R.rows(); regionID++)
   {
-    in.regionlist[regionID * 5 + 0] = R[regionID][0]; 
-    in.regionlist[regionID * 5 + 1] = R[regionID][1];
-    in.regionlist[regionID * 5 + 2] = R[regionID][2];
-    in.regionlist[regionID * 5 + 3] = R[regionID][3];
-    in.regionlist[regionID * 5 + 4] = R[regionID][4];
-  }	  
-
-  return true;
-    
-}	
+    in.regionlist[regionID * 5 + 0] = R(regionID,0); 
+    in.regionlist[regionID * 5 + 1] = R(regionID,1);
+    in.regionlist[regionID * 5 + 2] = R(regionID,2);
+    in.regionlist[regionID * 5 + 3] = R(regionID,3);
+    in.regionlist[regionID * 5 + 4] = R(regionID,4);
+  }  
 
-template <typename DerivedV, typename DerivedF, typename DerivedH, typename DerivedR>
-IGL_INLINE bool igl::copyleft::tetgen::mesh_to_tetgenio(
-  const Eigen::PlainObjectBase<DerivedV>& V,
-  const Eigen::PlainObjectBase<DerivedF>& F,
-  const Eigen::PlainObjectBase<DerivedH>& H,
-  const Eigen::PlainObjectBase<DerivedR>& R,
-  tetgenio & in)
-{
-  using namespace std;
-  vector<vector<REAL> > vV, vH, vR;
-  vector<vector<int> > vF;
-  matrix_to_list(V,vV);
-  matrix_to_list(F,vF);
-  matrix_to_list(H, vH);
-  matrix_to_list(R, vR);
-  return mesh_to_tetgenio(vV,vF,vH,vR,in);
 }
 
 
-IGL_INLINE bool igl::copyleft::tetgen::mesh_to_tetgenio(
-  const std::vector<std::vector<REAL > > & V, 
-  const std::vector<std::vector<int> > & F, 
-  tetgenio & in)
-{
-  using namespace std;
-  // all indices start from 0
-  in.firstnumber = 0;
-
-  in.numberofpoints = V.size();
-  in.pointlist = new REAL[in.numberofpoints * 3];
-  // loop over points
-  for(int i = 0; i < (int)V.size(); i++)
-  {
-    assert(V[i].size() == 3);
-    in.pointlist[i*3+0] = V[i][0];
-    in.pointlist[i*3+1] = V[i][1];
-    in.pointlist[i*3+2] = V[i][2];
-  }
-
-  in.numberoffacets = F.size();
-  in.facetlist = new tetgenio::facet[in.numberoffacets];
-  in.facetmarkerlist = new int[in.numberoffacets];
-
-  // loop over face
-  for(int i = 0;i < (int)F.size(); i++)
-  {
-    in.facetmarkerlist[i] = i;
-    tetgenio::facet * f = &in.facetlist[i];
-    f->numberofpolygons = 1;
-    f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
-    f->numberofholes = 0;
-    f->holelist = NULL;
-    tetgenio::polygon * p = &f->polygonlist[0];
-    p->numberofvertices = F[i].size();
-    p->vertexlist = new int[p->numberofvertices];
-    // loop around face
-    for(int j = 0;j < (int)F[i].size(); j++)
-    {
-      p->vertexlist[j] = F[i][j];
-    }
-  }
-  return true;
-}
-
-template <typename DerivedV, typename DerivedF>
-IGL_INLINE bool igl::copyleft::tetgen::mesh_to_tetgenio(
-  const Eigen::PlainObjectBase<DerivedV>& V,
-  const Eigen::PlainObjectBase<DerivedF>& F,
-  tetgenio & in)
-{
-  using namespace std;
-  vector<vector<REAL> > vV;
-  vector<vector<int> > vF;
-  matrix_to_list(V,vV);
-  matrix_to_list(F,vF);
-  return mesh_to_tetgenio(vV,vF,in);
-}
-
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
-template bool igl::copyleft::tetgen::mesh_to_tetgenio<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, tetgenio&);
+// generated by autoexplicit.sh
+template void igl::copyleft::tetgen::mesh_to_tetgenio<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const&, tetgenio&);
 #endif

+ 15 - 25
include/igl/copyleft/tetgen/mesh_to_tetgenio.h

@@ -28,32 +28,22 @@ namespace igl
       /// @param[in] F  #F list of polygon face indices into V (0-indexed)
       /// @param[out] in  tetgenio input object
       ///  @param[out] H  #H list of seed point inside each hole
-      ///  @param[out] R  #R list of seed point inside each region	
-      /// @return true on success, false on error
-      IGL_INLINE bool mesh_to_tetgenio(
-        const std::vector<std::vector<REAL> > & V,
-	const std::vector<std::vector<int> > & F,
-	const std::vector<std::vector<REAL > > & H, 
-	const std::vector<std::vector<REAL > > & R, 
-	tetgenio & in);	
-      IGL_INLINE bool mesh_to_tetgenio(
-        const std::vector<std::vector<REAL > > & V, 
-        const std::vector<std::vector<int> > & F, 
+      ///  @param[out] R  #R list of seed point inside each region  
+      template <
+        typename DerivedV, 
+        typename DerivedF, 
+        typename DerivedH, 
+        typename DerivedVM, 
+        typename DerivedFM, 
+        typename DerivedR>
+      IGL_INLINE void mesh_to_tetgenio(
+        const Eigen::MatrixBase<DerivedV>& V,
+        const Eigen::MatrixBase<DerivedF>& F,
+        const Eigen::MatrixBase<DerivedH>& H,
+        const Eigen::MatrixBase<DerivedVM>& VM,
+        const Eigen::MatrixBase<DerivedFM>& FM,
+        const Eigen::MatrixBase<DerivedR>& R,
         tetgenio & in);
-      /// \overload
-      template <typename DerivedV, typename DerivedF>
-      IGL_INLINE bool mesh_to_tetgenio(
-        const Eigen::PlainObjectBase<DerivedV>& V,
-        const Eigen::PlainObjectBase<DerivedF>& F,
-        tetgenio & in);
-      /// \overload
-      template <typename DerivedV, typename DerivedF, typename DerivedH, typename DerivedR>
-      IGL_INLINE bool mesh_to_tetgenio(
-	const Eigen::PlainObjectBase<DerivedV>& V,
-	const Eigen::PlainObjectBase<DerivedF>& F,
-	const Eigen::PlainObjectBase<DerivedH>& H, 
-	const Eigen::PlainObjectBase<DerivedR>& R, 
-	tetgenio& in);	
     }
   }
 }

+ 0 - 74
include/igl/copyleft/tetgen/read_into_tetgenio.cpp

@@ -1,74 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2013 Alec Jacobson <[email protected]>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#include "read_into_tetgenio.h"
-#include "mesh_to_tetgenio.h"
-
-// IGL includes
-#include "../../pathinfo.h"
-#ifndef IGL_NO_EIGEN
-#  define IGL_NO_EIGEN_WAS_NOT_ALREADY_DEFINED
-#  define IGL_NO_EIGEN
-#endif 
-// Include igl headers without including Eigen
-#include "../../readOBJ.h"
-#ifdef IGL_NO_EIGEN_WAS_NOT_ALREADY_DEFINED
-#  undef IGL_NO_EIGEN
-#endif
-
-// STL includes
-#include <algorithm>
-#include <iostream>
-#include <vector>
-
-IGL_INLINE bool igl::copyleft::tetgen::read_into_tetgenio(
-  const std::string & path,
-  tetgenio & in)
-{
-  using namespace std;
-  // get file extension
-  string dirname,basename,ext,filename;
-  pathinfo(path,dirname,basename,ext,filename);
-  // convert to lower case for easy comparison
-  transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
-  bool success = false;
-
-  char basename_char[1024];
-  strcpy(basename_char,basename.c_str());
-
-  if(ext == "obj")
-  {
-    // read obj into vertex list and face list
-    vector<vector<REAL> > V,TC,N;
-    vector<vector<int>  > F,FTC,FN;
-    success = readOBJ(path,V,TC,N,F,FTC,FN);
-    success &= mesh_to_tetgenio(V,F,in);
-  }else if(ext == "off")
-  {
-    success = in.load_off(basename_char);
-  }else if(ext == "node")
-  {
-    success = in.load_node(basename_char);
-  }else 
-  {
-    if(ext.length() > 0)
-    {
-      cerr<<"^read_into_tetgenio Warning: Unsupported extension ("<<ext<<
-        "): try to load as basename..."<<endl;
-    }
-    // This changed as of (the so far unreleased) tetgen 1.5
-    //success = in.load_tetmesh(basename_char);
-    //int object = tetgenbehavior::NODES;
-    //if(ext == "mesh")
-    //{
-    //  object = tetgenbehavior::MEDIT;
-    //}
-    success = in.load_tetmesh(basename_char,!tetgenbehavior::MEDIT);
-  }
-
-  return success;
-}

+ 0 - 60
include/igl/copyleft/tetgen/read_into_tetgenio.h

@@ -1,60 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2013 Alec Jacobson <[email protected]>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_COPYLEFT_TETGEN_READ_INTO_TETGENIO_H
-#define IGL_COPYLEFT_TETGEN_READ_INTO_TETGENIO_H
-#include "../../igl_inline.h"
-
-#include <string>
-#ifndef TETLIBRARY
-#define TETLIBRARY 
-#endif
-#include "tetgen.h" // Defined tetgenio, REAL
-
-namespace igl
-{
-  namespace copyleft
-  {
-    namespace tetgen
-    {
-      /// Read a mesh or point set into tetgenio (input object for calling
-      /// tetgen).  Many file formats are already supported by tetgen:
-      ///   .off
-      ///   .ply
-      ///   .node
-      ///   .ply
-      ///   .medit
-      ///   .vtk
-      ///   etc.
-      /// Notably it does not support .obj which is loaded by hand here (also
-      /// demonstrating how to load points/faces programmatically)
-      ///
-      /// If the file extension is not recognized the filename is assumed to be
-      /// the basename of a collection describe a tetmesh, (of which at least
-      /// the .node file must exist):
-      ///   [filename].node
-      ///   [filename].ele
-      ///   [filename].face
-      ///   [filename].edge
-      ///   [filename].vol
-      ///
-      /// @param[in] path  path to file or basename to files
-      /// @param[out] in  tetgenio input object
-      /// @return true on success, false on error
-      IGL_INLINE bool read_into_tetgenio(
-        const std::string & path, 
-        tetgenio & in);
-    }
-  }
-}
-
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "read_into_tetgenio.cpp"
-#endif
-
-#endif

+ 61 - 180
include/igl/copyleft/tetgen/tetgenio_to_tetmesh.cpp

@@ -13,255 +13,135 @@
 // STL includes
 #include <iostream>
 
-IGL_INLINE bool igl::copyleft::tetgen::tetgenio_to_tetmesh(
-  const tetgenio & out,
-  std::vector<std::vector<REAL > > & V,
-  std::vector<std::vector<int> > & T,
-  std::vector<std::vector<int> > & F)
-{
-  using namespace std;
-  // process points
-  if(out.pointlist == NULL)
-  {
-    cerr<<"^tetgenio_to_tetmesh Error: point list is NULL\n"<<endl;
-    return false;
-  }
-  V.resize(out.numberofpoints,vector<REAL>(3));
-  // loop over points
-  for(int i = 0;i < out.numberofpoints; i++)
-  {
-    V[i][0] = out.pointlist[i*3+0];
-    V[i][1] = out.pointlist[i*3+1];
-    V[i][2] = out.pointlist[i*3+2];
-  }
-
-
-  // process tets
-  if(out.tetrahedronlist == NULL)
-  {
-    cerr<<"^tetgenio_to_tetmesh Error: tet list is NULL\n"<<endl;
-    return false;
-  }
-
-  // When would this not be 4?
-  assert(out.numberofcorners == 4);
-  T.resize(out.numberoftetrahedra,vector<int>(out.numberofcorners));
-  int min_index = 1e7;
-  int max_index = -1e7;
-  // loop over tetrahedra
-  for(int i = 0; i < out.numberoftetrahedra; i++)
-  {
-    for(int j = 0; j<out.numberofcorners; j++)
-    {
-      int index = out.tetrahedronlist[i * out.numberofcorners + j];
-      T[i][j] = index;
-      min_index = (min_index > index ? index : min_index);
-      max_index = (max_index < index ? index : max_index);
-    }
-  }
-  assert(min_index >= 0);
-  assert(max_index >= 0);
-  assert(max_index < (int)V.size());
-
-  // When would this not be 4?
-  F.clear();
-  // loop over tetrahedra
-  for(int i = 0; i < out.numberoftrifaces; i++)
-  {
-    vector<int> face(3);
-    for(int j = 0; j<3; j++)
-    {
-      face[j] = out.trifacelist[i * 3 + j];
-    }
-    F.push_back(face);
-  }
-
-  return true;
-}
-
-template <typename DerivedV, typename DerivedT>
-IGL_INLINE bool igl::copyleft::tetgen::tetgenio_to_tetmesh(
-  const tetgenio & out,
-  Eigen::PlainObjectBase<DerivedV>& V,
-  Eigen::PlainObjectBase<DerivedT>& T)
-{
-  Eigen::Matrix<typename DerivedT::Scalar,Eigen::Dynamic,3> F;
-  return tetgenio_to_tetmesh(out,V,T,F);
-}
-
-template <typename DerivedV, typename DerivedT, typename DerivedF>
+template <
+  typename DerivedV, 
+  typename DerivedT,
+  typename DerivedF,
+  typename DerivedTM,
+  typename DerivedR,
+  typename DerivedN,
+  typename DerivedPT,
+  typename DerivedFT>
 IGL_INLINE bool igl::copyleft::tetgen::tetgenio_to_tetmesh(
   const tetgenio & out,
   Eigen::PlainObjectBase<DerivedV>& V,
   Eigen::PlainObjectBase<DerivedT>& T,
-  Eigen::PlainObjectBase<DerivedF>& F)
+  Eigen::PlainObjectBase<DerivedF>& F,
+  Eigen::PlainObjectBase<DerivedTM>& TM,
+  Eigen::PlainObjectBase<DerivedR>& R,
+  Eigen::PlainObjectBase<DerivedN>& N,
+  Eigen::PlainObjectBase<DerivedPT>& PT,
+  Eigen::PlainObjectBase<DerivedFT>& FT,
+  int & num_regions)
 {
-  using namespace std;
-  vector<vector<REAL> > vV;
-  vector<vector<int> > vT;
-  vector<vector<int> > vF;
-  bool success = tetgenio_to_tetmesh(out,vV,vT,vF);
-  if(!success)
-  {
-    return false;
-  }
-  bool V_rect = list_to_matrix(vV,V);
-  if(!V_rect)
-  {
-    // igl::list_to_matrix(vV,V) already printed error message to std err
-    return false;
-  }
-  bool T_rect = list_to_matrix(vT,T);
-  if(!T_rect)
-  {
-    // igl::list_to_matrix(vT,T) already printed error message to std err
-    return false;
-  }
-  bool F_rect = list_to_matrix(vF,F);
-  if(!F_rect)
-  {
-    return false;
-  }
-
-  return true;
-}
-
-IGL_INLINE bool igl::copyleft::tetgen::tetgenio_to_tetmesh(
-  const tetgenio & out,
-  std::vector<std::vector<REAL > > & V,
-  std::vector<std::vector<int> > & T)
-{
-  std::vector<std::vector<int> > F;
-  return tetgenio_to_tetmesh(out,V,T,F);
-}
-
-IGL_INLINE bool igl::copyleft::tetgen::tetgenio_to_tetmesh(
-  const tetgenio & out,
-  std::vector<std::vector<REAL > > & V,
-  std::vector<std::vector<int> > & T,
-  std::vector<std::vector<int > > & F,
-  std::vector<std::vector<REAL > >&  R,
-  std::vector<std::vector<int > >& N,
-  std::vector<std::vector<int > >& PT,
-  std::vector<std::vector<int > >& FT,
-  size_t & nR )
-{
-  using namespace std;
   // process points
   if(out.pointlist == NULL)
   {
-    cerr<<"^tetgenio_to_tetmesh Error: point list is NULL\n"<<endl;
+    std::cerr<<"^tetgenio_to_tetmesh Error: point list is NULL\n"<<std::endl;
     return false;
   }
-  V.resize(out.numberofpoints,vector<REAL>(3));
+  V.resize(out.numberofpoints,3);
   // loop over points
   for(int i = 0;i < out.numberofpoints; i++)
   {
-    V[i][0] = out.pointlist[i*3+0];
-    V[i][1] = out.pointlist[i*3+1];
-    V[i][2] = out.pointlist[i*3+2];
+    V(i,0) = out.pointlist[i*3+0];
+    V(i,1) = out.pointlist[i*3+1];
+    V(i,2) = out.pointlist[i*3+2];
   }
 
   // process tets
   if(out.tetrahedronlist == NULL)
   {
-    cerr<<"^tetgenio_to_tetmesh Error: tet list is NULL\n"<<endl;
+    std::cerr<<"^tetgenio_to_tetmesh Error: tet list is NULL\n"<<std::endl;
     return false;
   }
 
   // When would this not be 4?
   assert(out.numberofcorners == 4);
-  T.resize(out.numberoftetrahedra,vector<int>(out.numberofcorners));
-  int min_index = 1e7;
-  int max_index = -1e7;
+  T.resize(out.numberoftetrahedra,out.numberofcorners);
   // loop over tetrahedra
   for(int i = 0; i < out.numberoftetrahedra; i++)
   {
     for(int j = 0; j<out.numberofcorners; j++)
     {
-      int index = out.tetrahedronlist[i * out.numberofcorners + j];
-      T[i][j] = index;
-      min_index = (min_index > index ? index : min_index);
-      max_index = (max_index < index ? index : max_index);
+      T(i,j) = out.tetrahedronlist[i * out.numberofcorners + j];
     }
   }
 
-  assert(min_index >= 0);
-  assert(max_index >= 0);
-  assert(max_index < (int)V.size());
+  assert(T.maxCoeff() >= 0);
+  assert(T.minCoeff() >= 0);
+  assert(T.maxCoeff() < V.rows());
 
-  // When would this not be 4?
-  F.clear();
+  F.resize(out.numberoftrifaces,3);
   // loop over tetrahedra
   for(int i = 0; i < out.numberoftrifaces; i++)
   {
-    vector<int> face(3);
-    for(int j = 0; j<3; j++)
+    F(i,0) = out.trifacelist[i * 3 + 0];
+    F(i,1) = out.trifacelist[i * 3 + 1];
+    F(i,2) = out.trifacelist[i * 3 + 2];
+  }
+
+  if(out.pointmarkerlist)
+  {
+    assert(out.numberofpoints == out.numberofpointmarkers);
+    TM.resize(out.numberofpoints);
+    for (int i = 0; i < out.numberofpoints; ++i) 
     {
-      face[j] = out.trifacelist[i * 3 + j];
+    	TM(i) = out.pointmarkerlist[i];
     }
-    F.push_back(face);
   }
 
   if(out.tetrahedronattributelist)
   {
-    R.resize(out.numberoftetrahedra, vector<REAL>(1));
-    unordered_map<REAL, REAL> hashUniqueRegions;
-    for(size_t i = 0; i < out.numberoftetrahedra; i++)
+    R.resize(out.numberoftetrahedra);
+    std::unordered_map<REAL, REAL> hashUniqueRegions;
+    for(int i = 0; i < out.numberoftetrahedra; i++)
     {
-         R[i][0] = out.tetrahedronattributelist[i];
-         hashUniqueRegions[R[i][0]] = i;
+         R(i) = out.tetrahedronattributelist[i];
+         hashUniqueRegions[R(i)] = i;
     }
     // extract region marks
-    nR = hashUniqueRegions.size();
+    num_regions = hashUniqueRegions.size();
   }else
   {
-    R.clear();
-    nR = 0;
+    num_regions = 0;
   }
 
   // extract neighbor list
   if(out.neighborlist)
   {
-    N.resize(out.numberoftetrahedra, vector<int>(4));
-    for (size_t i = 0; i < out.numberoftetrahedra; i++)
+    N.resize(out.numberoftetrahedra, 4);
+    for (int i = 0; i < out.numberoftetrahedra; i++)
     {
-      for (size_t j = 0; j < 4; j++)
-        N[i][j] = out.neighborlist[i * 4 + j];
+      for (int j = 0; j < 4; j++)
+      {
+        N(i,j) = out.neighborlist[i * 4 + j];
+      }
     }
-  }else
-  {
-    N.clear();
   }
 
   // extract point 2 tetrahedron list
   if(out.point2tetlist)
   {
-    PT.resize(out.numberofpoints, vector<int>(1));
-    for (size_t i = 0; i < out.numberofpoints; i++)
+    PT.resize(out.numberofpoints);
+    for (int i = 0; i < out.numberofpoints; i++)
     {
-      PT[i][0] = out.point2tetlist[i];
+      PT(i) = out.point2tetlist[i];
     }
-  }else
-  {
-    PT.clear();
   }
 
   //extract face to tetrahedron list
   if(out.face2tetlist)
   {
-    FT.resize(out.numberoftrifaces, vector<int>(2));
+    FT.resize(out.numberoftrifaces,2);
     int triface;
-    for (size_t i = 0; i < out.numberoftrifaces; i++)
+    for (int i = 0; i < out.numberoftrifaces; i++)
     {
-      for (size_t j = 0; j < 2; j++)
+      for (int j = 0; j < 2; j++)
       {
-        FT[i][j] = out.face2tetlist[0];
+        FT(i,j) = out.face2tetlist[i * 2 + j];
       }
     }
-  }else
-  {
-    FT.clear();
   }
 
   return true;
@@ -270,5 +150,6 @@ IGL_INLINE bool igl::copyleft::tetgen::tetgenio_to_tetmesh(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
-template bool igl::copyleft::tetgen::tetgenio_to_tetmesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(tetgenio const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+// generated by autoexplicit.sh
+template bool igl::copyleft::tetgen::tetgenio_to_tetmesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>>(tetgenio const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, int&);
 #endif

+ 17 - 44
include/igl/copyleft/tetgen/tetgenio_to_tetmesh.h

@@ -22,54 +22,27 @@ namespace igl
   {
     namespace tetgen
     {
-      /// Extract a tetrahedral mesh from a tetgenio object
-      ///
-      /// @param[in] out tetgenio output object
-      /// @param[out] V  #V by 3 vertex position list
-      /// @param[out] T  #T by 4 list of tetrahedra indices into V
-      /// @param[out] F  #F by 3 list of marked facets
-      /// @param[out] R  #T list of region IDs for tetrahedra
-      /// @param[out] N  #T by 2 list of neighbors for each tetrahedron
-      /// @param[out] PT #V list of incident tetrahedron for each vertex
-      /// @param[out] FT #F by 2 list of tetrahedra sharing each face 
-      /// @param[out] nR number of regions in output mesh
-      /// @return true on success, false on error
-      IGL_INLINE bool tetgenio_to_tetmesh(
-        const tetgenio & out,
-	std::vector<std::vector<REAL > > & V,
-	std::vector<std::vector<int> > & T,
-        std::vector<std::vector<int> > & F, 
-	std::vector<std::vector<REAL> > & R,// region marks for tetrahedrons
-	std::vector<std::vector<int > > &N, // neighborlist per tet
-	std::vector<std::vector<int > >	&PT, // Point to tet list per point
-	std::vector<std::vector<int > > &FT, // face to tet list
-	size_t & nR); // number of regions    
-      /// \overload
-      IGL_INLINE bool tetgenio_to_tetmesh(
-        const tetgenio & out,
-        std::vector<std::vector<REAL > > & V, 
-        std::vector<std::vector<int> > & T,
-        std::vector<std::vector<int> > & F);
-      /// \overload
-      IGL_INLINE bool tetgenio_to_tetmesh(
-        const tetgenio & out,
-        std::vector<std::vector<REAL > > & V, 
-        std::vector<std::vector<int> > & T);
-      /// \overload
-      template <typename DerivedV, typename DerivedT, typename DerivedF>
+      template <
+        typename DerivedV, 
+        typename DerivedT,
+        typename DerivedF,
+        typename DerivedTM,
+        typename DerivedR,
+        typename DerivedN,
+        typename DerivedPT,
+        typename DerivedFT>
       IGL_INLINE bool tetgenio_to_tetmesh(
         const tetgenio & out,
         Eigen::PlainObjectBase<DerivedV>& V,
         Eigen::PlainObjectBase<DerivedT>& T,
-        Eigen::PlainObjectBase<DerivedF>& F);
-      /// \overload
-      template <typename DerivedV, typename DerivedT>
-      IGL_INLINE bool tetgenio_to_tetmesh(
-        const tetgenio & out,
-        Eigen::PlainObjectBase<DerivedV>& V,
-        Eigen::PlainObjectBase<DerivedT>& T);
-
-  }
+        Eigen::PlainObjectBase<DerivedF>& F,
+        Eigen::PlainObjectBase<DerivedTM>& TM,
+        Eigen::PlainObjectBase<DerivedR>& R,
+        Eigen::PlainObjectBase<DerivedN>& N,
+        Eigen::PlainObjectBase<DerivedPT>& PT,
+        Eigen::PlainObjectBase<DerivedFT>& FT,
+        int & num_regions);
+    }
   }
 }
 

+ 44 - 272
include/igl/copyleft/tetgen/tetrahedralize.cpp

@@ -18,172 +18,43 @@
 #include <cassert>
 #include <iostream>
 
-IGL_INLINE int igl::copyleft::tetgen::tetrahedralize(
-  const std::vector<std::vector<REAL > > & V,
-  const std::vector<std::vector<int> > & F,
-  const std::string switches,
-  std::vector<std::vector<REAL > > & TV,
-  std::vector<std::vector<int > > & TT,
-  std::vector<std::vector<int> > & TF)
-{
-  using namespace std;
-  tetgenio in,out;
-  bool success;
-  success = mesh_to_tetgenio(V,F,in);
-  if(!success)
-  {
-    return -1;
-  }
-  try
-  {
-    char * cswitches = new char[switches.size() + 1];
-    std::strcpy(cswitches,switches.c_str());
-    ::tetrahedralize(cswitches,&in, &out);
-    delete[] cswitches;
-  }catch(int e)
-  {
-    cerr<<"^"<<__FUNCTION__<<": TETGEN CRASHED... KABOOOM!!!"<<endl;
-    return 1;
-  }
-  if(out.numberoftetrahedra == 0)
-  {
-    cerr<<"^"<<__FUNCTION__<<": Tetgen failed to create tets"<<endl;
-    return 2;
-  }
-  success = tetgenio_to_tetmesh(out,TV,TT,TF);
-  if(!success)
-  {
-    return -1;
-  }
-  boundary_facets(TT,TF);
-  return 0;
-}
-
-template <
-  typename DerivedV,
-  typename DerivedF,
-  typename DerivedTV,
-  typename DerivedTT,
-  typename DerivedTF>
-IGL_INLINE int igl::copyleft::tetgen::tetrahedralize(
-  const Eigen::MatrixBase<DerivedV>& V,
-  const Eigen::MatrixBase<DerivedF>& F,
-  const std::string switches,
-  Eigen::PlainObjectBase<DerivedTV>& TV,
-  Eigen::PlainObjectBase<DerivedTT>& TT,
-  Eigen::PlainObjectBase<DerivedTF>& TF)
-{
-  using namespace std;
-  vector<vector<REAL> > vV,vTV;
-  vector<vector<int> > vF,vTT,vTF;
-  matrix_to_list(V,vV);
-  matrix_to_list(F,vF);
-  int e = tetrahedralize(vV,vF,switches,vTV,vTT,vTF);
-  if(e == 0)
-  {
-    bool TV_rect = list_to_matrix(vTV,TV);
-    if(!TV_rect)
-    {
-      return 3;
-    }
-    bool TT_rect = list_to_matrix(vTT,TT);
-    if(!TT_rect)
-    {
-      return 3;
-    }
-    bool TF_rect = list_to_matrix(vTF,TF);
-    if(!TF_rect)
-    {
-      return 3;
-    }
-  }
-  return e;
-}
-
 template <
   typename DerivedV,
   typename DerivedF,
+  typename DerivedH,
   typename DerivedVM,
   typename DerivedFM,
+  typename DerivedR,
   typename DerivedTV,
   typename DerivedTT,
   typename DerivedTF,
-  typename DerivedTM>
+  typename DerivedTM,
+  typename DerivedTR,
+  typename DerivedTN,
+  typename DerivedPT,
+  typename DerivedFT>
 IGL_INLINE int igl::copyleft::tetgen::tetrahedralize(
   const Eigen::MatrixBase<DerivedV>& V,
   const Eigen::MatrixBase<DerivedF>& F,
+  const Eigen::MatrixBase<DerivedH>& H,
   const Eigen::MatrixBase<DerivedVM>& VM,
   const Eigen::MatrixBase<DerivedFM>& FM,
+  const Eigen::MatrixBase<DerivedR>& R,
   const std::string switches,
   Eigen::PlainObjectBase<DerivedTV>& TV,
   Eigen::PlainObjectBase<DerivedTT>& TT,
   Eigen::PlainObjectBase<DerivedTF>& TF,
-  Eigen::PlainObjectBase<DerivedTM>& TM)
-{
-  using namespace std;
-  vector<vector<REAL> > vV,vTV;
-  vector<vector<int> > vF,vTT,vTF;
-  vector<int> vTM;
-
-  matrix_to_list(V,vV);
-  matrix_to_list(F,vF);
-  vector<int> vVM = matrix_to_list(VM);
-  vector<int> vFM = matrix_to_list(FM);
-  int e = tetrahedralize(vV,vF,vVM,vFM,switches,vTV,vTT,vTF,vTM);
-  if(e == 0)
-  {
-    bool TV_rect = list_to_matrix(vTV,TV);
-    if(!TV_rect)
-    {
-      return false;
-    }
-    bool TT_rect = list_to_matrix(vTT,TT);
-    if(!TT_rect)
-    {
-      return false;
-    }
-    bool TF_rect = list_to_matrix(vTF,TF);
-    if(!TF_rect)
-    {
-      return false;
-    }
-    bool TM_rect = list_to_matrix(vTM,TM);
-    if(!TM_rect)
-    {
-      return false;
-    }
-  }
-  return e;
-}
-
-IGL_INLINE int igl::copyleft::tetgen::tetrahedralize(
-  const std::vector<std::vector<REAL > > & V,
-  const std::vector<std::vector<int> > & F,
-  const std::vector<int> & VM,
-	const std::vector<int> & FM,
-  const std::string switches,
-  std::vector<std::vector<REAL > > & TV,
-  std::vector<std::vector<int > > & TT,
-  std::vector<std::vector<int> > & TF,
-  std::vector<int> & TM)
+  Eigen::PlainObjectBase<DerivedTM>& TM,
+  Eigen::PlainObjectBase<DerivedTR>& TR, 
+  Eigen::PlainObjectBase<DerivedTN>& TN, 
+  Eigen::PlainObjectBase<DerivedPT>& PT, 
+  Eigen::PlainObjectBase<DerivedFT>& FT, 
+  int & num_regions)
 {
-  using namespace std;
+  // REAL is what tetgen is using as floating point precision
+  // Prepare input
   tetgenio in,out;
-  bool success;
-  success = mesh_to_tetgenio(V,F,in);
-  if(!success)
-  {
-    return -1;
-  }
-	in.pointmarkerlist = new int[VM.size()];
-	for (int i = 0; i < VM.size(); ++i) {
-		in.pointmarkerlist[i] = VM[i];
-	}
-  // These have already been created in mesh_to_tetgenio.
-  // Reset them here.
-	for (int i = 0; i < FM.size(); ++i) {
-		in.facetmarkerlist[i] = FM[i];
-	}
+  mesh_to_tetgenio(V,F,H,VM,FM,R,in);
   try
   {
     char * cswitches = new char[switches.size() + 1];
@@ -192,155 +63,56 @@ IGL_INLINE int igl::copyleft::tetgen::tetrahedralize(
     delete[] cswitches;
   }catch(int e)
   {
-    cerr<<"^"<<__FUNCTION__<<": TETGEN CRASHED... KABOOOM!!!"<<endl;
+    std::cerr<<"^"<<__FUNCTION__<<": TETGEN CRASHED... KABOOOM!!!"<<std::endl;
     return 1;
   }
   if(out.numberoftetrahedra == 0)
   {
-    cerr<<"^"<<__FUNCTION__<<": Tetgen failed to create tets"<<endl;
+    std::cerr<<"^"<<__FUNCTION__<<": Tetgen failed to create tets"<<std::endl;
     return 2;
   }
-  success = tetgenio_to_tetmesh(out,TV,TT,TF);
-  if(!success)
-  {
-    return -1;
-  }
-	TM.resize(out.numberofpoints);
-	for (int i = 0; i < out.numberofpoints; ++i) {
-		TM[i] = out.pointmarkerlist[i];
-	}
-  boundary_facets(TT,TF);
-  return 0;
-}
 
-IGL_INLINE int igl::copyleft::tetgen::tetrahedralize(
-  const std::vector<std::vector<REAL > > & V,
-  const std::vector<std::vector<int> > & F,
-  const std::vector<std::vector<REAL > > & H,
-  const std::vector<std::vector<REAL > > & R,
-  const std::string switches,
-  std::vector<std::vector<REAL > > & TV,
-  std::vector<std::vector<int > > & TT,
-  std::vector<std::vector<int > > & TF,
-  std::vector<std::vector<REAL > > &TR,
-  std::vector<std::vector<int > > & TN, 
-  std::vector<std::vector<int > > & PT,
-  std::vector<std::vector<int > > & FT,
-  size_t & numRegions)
-{
-  using namespace std;
-  tetgenio in,out;
-  bool success;
-  success = mesh_to_tetgenio(V, F, H, R, in);
-  if(!success)
+  // Prepare output
+  bool ret = tetgenio_to_tetmesh(out,TV,TT,TF,TM,TR,TN,PT,FT,num_regions);
+  if(!ret)
   {
     return -1;
   }
-  try 
-  {
-    char * cswitches = new char[switches.size() + 1];
-    strcpy(cswitches, switches.c_str());
-    
-    ::tetrahedralize(cswitches, &in, &out); 
-    delete[] cswitches;
-}catch(int e)
-  {
-    cerr <<"^"<<__FUNCTION__<<": TETGEN CRASHED...KABOOM!!"<<endl;
-    return 1;
-  }
-  if(out.numberoftetrahedra == 0)
-  {
-    cerr<<"^"<<__FUNCTION__<<": Tetgen failed to create tets"<<endl;
-    return 2;	  
-  }
-   success = tetgenio_to_tetmesh(out, TV, TT, TF, TR, TN, PT, FT, numRegions
-);
-  if(!success)
+
+  if(TF.size() == 0)
   {
-    return -1;
+    boundary_facets(TT,TF);
   }
-    return 0;
+
+  return 0;
 }
 
 template <
-  typename DerivedV, 
-  typename DerivedF, 
-  typename DerivedH,
-  typename DerivedR,
-  typename DerivedTV, 
-  typename DerivedTT, 
-  typename DerivedTF,
-  typename DerivedTR>
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedTV,
+  typename DerivedTT,
+  typename DerivedTF>
 IGL_INLINE int igl::copyleft::tetgen::tetrahedralize(
   const Eigen::MatrixBase<DerivedV>& V,
   const Eigen::MatrixBase<DerivedF>& F,
-  const Eigen::MatrixBase<DerivedH>& H,
-  const Eigen::MatrixBase<DerivedR>& R,
   const std::string switches,
   Eigen::PlainObjectBase<DerivedTV>& TV,
   Eigen::PlainObjectBase<DerivedTT>& TT,
-  Eigen::PlainObjectBase<DerivedTF>& TF,
-  Eigen::PlainObjectBase<DerivedTR>& TR,
-  Eigen::PlainObjectBase<DerivedTT>& TN,
-  Eigen::PlainObjectBase<DerivedTT>& PT,
-  Eigen::PlainObjectBase<DerivedTT>& FT,
-  size_t & numRegions)
+  Eigen::PlainObjectBase<DerivedTF>& TF)
 {
-  using namespace std;
-  vector<vector<REAL> > vV, vH, vR, vTV, vTR;
-  vector<vector<int> > vF,vTT,vTF, vTN, vPT, vFT;
-  matrix_to_list(V,vV);
-  matrix_to_list(F,vF);	
-  matrix_to_list(H, vH);
-  matrix_to_list(R, vR);
-  
-  int e = tetrahedralize(vV,vF,vH,vR,switches,vTV,vTT,vTF,vTR,vTN,vPT,vFT, numRegions);
-  
-  if(e == 0)
-  {
-    bool TV_rect = list_to_matrix(vTV,TV);
-    if(!TV_rect)
-    {
-      return 3;
-    }
-    bool TT_rect = list_to_matrix(vTT,TT);
-    if(!TT_rect)
-    {
-      return 3;
-    }
-    bool TF_rect = list_to_matrix(vTF,TF);
-    if(!TF_rect)
-    {
-      return 3;
-    }
-    bool TR_rect = list_to_matrix(vTR, TR);
-    if(!TR_rect)
-    {
-      return 3;	    
-    }
-    bool TN_rect = list_to_matrix(vTN, TN);
-    if(!TN_rect)
-    {
-      return 3;	
-    }	    
-    bool PT_rect = list_to_matrix(vPT, PT);
-    if(!PT_rect)
-    {
-      return 3;	    
-    }	    
-    bool FT_rect = list_to_matrix(vFT, FT);
-    if(!FT_rect)
-    {
-      return 3;	    
-    }	    
-  }
-  return e;
+  Eigen::VectorXi VM,FM;
+  Eigen::MatrixXd H,R;
+  Eigen::VectorXi TM,TR,PT;
+  Eigen::MatrixXi FT,TN;
+  int numRegions;
+  return tetrahedralize(V,F,H,VM,FM,R,switches,TV,TT,TF,TM,TR,TN,PT,FT,numRegions);
 }
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
-template int igl::copyleft::tetgen::tetrahedralize<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
-template int igl::copyleft::tetgen::tetrahedralize<Eigen::Matrix<double, -1, -1, 0, -1, -1>,Eigen::Matrix<int, -1, -1, 0, -1, -1>,Eigen::Matrix<int, -1, 1, 0, -1, 1>,Eigen::Matrix<int, -1, 1, 0, -1, 1>,Eigen::Matrix<double, -1, -1, 0, -1, -1>,Eigen::Matrix<int, -1, -1, 0, -1, -1>,Eigen::Matrix<int, -1, -1, 0, -1, -1>,Eigen::Matrix<int, -1, 1, 0, -1, 1> >(const Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > &,const Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > &,const Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > &,const Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > &,const std::basic_string<char, std::char_traits<char>, std::allocator<char> >,Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > &,Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > &,Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > &, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > &);
-template int igl::copyleft::tetgen::tetrahedralize<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
-template int igl::copyleft::tetgen::tetrahedralize<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, unsigned long&);
+// generated by autoexplicit.sh
+template int igl::copyleft::tetgen::tetrahedralize<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, std::basic_string<char, std::char_traits<char>, std::allocator<char>>, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&);
+// generated by autoexplicit.sh
+template int igl::copyleft::tetgen::tetrahedralize<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const&, std::basic_string<char, std::char_traits<char>, std::allocator<char>>, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, int&);
 #endif

+ 30 - 72
include/igl/copyleft/tetgen/tetrahedralize.h

@@ -28,6 +28,8 @@ namespace igl
       /// @param[in] V  #V by 3 vertex position list
       /// @param[in] F  #F list of polygon face indices into V (0-indexed)
       /// @param[in] H  #H by 3 list of seed points inside holes
+      /// @param[in] VM  #VM list of vertex markers
+      /// @param[in] FM  #FM list of face markers
       /// @param[in] R  #R by 5 list of region attributes            
       /// @param[in] switches  string of tetgen options (See tetgen documentation) e.g.
       ///     "pq1.414a0.01" tries to mesh the interior of a given surface with
@@ -35,109 +37,65 @@ namespace igl
       ///     "" will mesh the convex hull constrained to pass through V (ignores F)
       /// @param[out] TV  #TV by 3 vertex position list
       /// @param[out] TT  #TT by 4 list of tet face indices
-      /// @param[out] TF  #TF by 3 list of triangle face indices
+      /// @param[out] TF  #TF by 3 list of triangle face indices ('f', else
+      ///   `boundary_facets` is called on TT)
       /// @param[out] TR  #TT list of region ID for each tetrahedron      
-      /// @param[out] TN  #TT by 4 list of indices neighbors for each tetrahedron
-      /// @param[out] PT  #TV list of incident tetrahedron for a vertex
-      /// @param[out] FT  #TF by 2 list of tetrahedrons sharing a triface      
-      /// @param[out] numRegions Number of regions in output mesh
+      /// @param[out] TN  #TT by 4 list of indices neighbors for each tetrahedron ('n')
+      /// @param[out] PT  #TV list of incident tetrahedron for a vertex ('m')
+      /// @param[out] FT  #TF by 2 list of tetrahedrons sharing a triface ('nn')
+      /// @param[out] num_regions Number of regions in output mesh
       /// @return status:
       ///   0 success
       ///   1 tetgen threw exception
       ///   2 tetgen did not crash but could not create any tets (probably there are
       ///     holes, duplicate faces etc.)
       ///   -1 other error
-      IGL_INLINE int tetrahedralize(
-        const std::vector<std::vector<REAL> > &V, 
-        const std::vector<std::vector<int> >  &F, 
-        const std::vector<std::vector<REAL> > &H, 
-        const std::vector<std::vector<REAL> > &R, 
-        const std::string switches, 
-        std::vector<std::vector<REAL > > & TV,
-        std::vector<std::vector<int > >  & TT,
-        std::vector<std::vector<int > >  & TF,
-        std::vector<std::vector<REAL > > &TR,  
-        std::vector<std::vector<int > > &TN, 
-        std::vector<std::vector<int > > &PT, 
-        std::vector<std::vector<int > > &FT, 
-        size_t & numRegions);           
-      /// \overload
-      IGL_INLINE int tetrahedralize(
-        const std::vector<std::vector<REAL > > & V, 
-        const std::vector<std::vector<int> > & F, 
-        const std::string switches,
-        std::vector<std::vector<REAL > > & TV, 
-        std::vector<std::vector<int > > & TT, 
-        std::vector<std::vector<int> > & TF);
-      /// \overload
       template <
-        typename DerivedV, 
-        typename DerivedF, 
-        typename DerivedTV, 
-        typename DerivedTT, 
-        typename DerivedTF>
-      IGL_INLINE int tetrahedralize(
-        const Eigen::MatrixBase<DerivedV>& V,
-        const Eigen::MatrixBase<DerivedF>& F,
-        const std::string switches,
-        Eigen::PlainObjectBase<DerivedTV>& TV,
-        Eigen::PlainObjectBase<DerivedTT>& TT,
-        Eigen::PlainObjectBase<DerivedTF>& TF);
-      /// \overload
-      IGL_INLINE int tetrahedralize(
-        const std::vector<std::vector<REAL > > & V, 
-        const std::vector<std::vector<int> > & F, 
-        const std::vector<int> & VM,
-        const std::vector<int> & FM,
-        const std::string switches,
-        std::vector<std::vector<REAL > > & TV, 
-        std::vector<std::vector<int > > & TT, 
-        std::vector<std::vector<int> > & TF,
-        std::vector<int> & TM);
-      /// \overload
-      template <
-        typename DerivedV, 
-        typename DerivedF, 
+        typename DerivedV,
+        typename DerivedF,
+        typename DerivedH,
         typename DerivedVM,
         typename DerivedFM,
-        typename DerivedTV, 
-        typename DerivedTT, 
-        typename DerivedTF, 
-        typename DerivedTM>
+        typename DerivedR,
+        typename DerivedTV,
+        typename DerivedTT,
+        typename DerivedTF,
+        typename DerivedTM,
+        typename DerivedTR,
+        typename DerivedTN,
+        typename DerivedPT,
+        typename DerivedFT>
       IGL_INLINE int tetrahedralize(
         const Eigen::MatrixBase<DerivedV>& V,
         const Eigen::MatrixBase<DerivedF>& F,
+        const Eigen::MatrixBase<DerivedH>& H,
         const Eigen::MatrixBase<DerivedVM>& VM,
         const Eigen::MatrixBase<DerivedFM>& FM,
+        const Eigen::MatrixBase<DerivedR>& R,
         const std::string switches,
         Eigen::PlainObjectBase<DerivedTV>& TV,
         Eigen::PlainObjectBase<DerivedTT>& TT,
         Eigen::PlainObjectBase<DerivedTF>& TF,
-        Eigen::PlainObjectBase<DerivedTM>& TM);
+        Eigen::PlainObjectBase<DerivedTM>& TM,
+        Eigen::PlainObjectBase<DerivedTR>& TR, 
+        Eigen::PlainObjectBase<DerivedTN>& TN, 
+        Eigen::PlainObjectBase<DerivedPT>& PT, 
+        Eigen::PlainObjectBase<DerivedFT>& FT, 
+        int & num_regions);
       /// \overload
       template <
         typename DerivedV,
         typename DerivedF,
-        typename DerivedH,
-        typename DerivedR,
         typename DerivedTV,
         typename DerivedTT,
-        typename DerivedTF,
-        typename DerivedTR>      
+        typename DerivedTF>
       IGL_INLINE int tetrahedralize(
         const Eigen::MatrixBase<DerivedV>& V,
         const Eigen::MatrixBase<DerivedF>& F,
-        const Eigen::MatrixBase<DerivedH>& H,
-        const Eigen::MatrixBase<DerivedR>& R,
         const std::string switches,
         Eigen::PlainObjectBase<DerivedTV>& TV,
         Eigen::PlainObjectBase<DerivedTT>& TT,
-        Eigen::PlainObjectBase<DerivedTF>& TF,
-        Eigen::PlainObjectBase<DerivedTR>& TR, 
-        Eigen::PlainObjectBase<DerivedTT>& TN, 
-        Eigen::PlainObjectBase<DerivedTT>& PT, 
-        Eigen::PlainObjectBase<DerivedTT>& FT, 
-        size_t & numRegions);            
+        Eigen::PlainObjectBase<DerivedTF>& TF);
    }
   }
 }

+ 52 - 0
tests/include/igl/copyleft/tetgen/tetrahedralize.cpp

@@ -2,6 +2,9 @@
 
 #include <igl/setxor.h>
 #include <igl/copyleft/tetgen/tetrahedralize.h>
+#include <igl/unique_simplices.h>
+#include <igl/matlab_format.h>
+#include <iostream>
 
 TEST_CASE("tetrahedralize: single_tet", "[igl/copyleft/tetgen]")
 {
@@ -14,6 +17,7 @@ TEST_CASE("tetrahedralize: single_tet", "[igl/copyleft/tetgen]")
   Eigen::MatrixXd TV;
   Eigen::MatrixXi TT,TF;
   igl::copyleft::tetgen::tetrahedralize(V,F,"cpQ",TV,TT,TF);
+
   REQUIRE (4 == TV.rows());
   REQUIRE (1 == TT.rows());
   REQUIRE (4 == TF.rows());
@@ -26,6 +30,54 @@ TEST_CASE("tetrahedralize: single_tet", "[igl/copyleft/tetgen]")
   test_common::assert_eq(TV,V);
 }
 
+TEST_CASE("tetrahedralize: two_tets", "[igl/copyleft/tetgen]")
+{
+  const Eigen::MatrixXd V = (Eigen::MatrixXd(5,3)<<
+    2,1,0,
+    1,-1,0,
+    -1,-1,0,
+    -1,1,0,
+     0,0,1 ).finished();
+  Eigen::MatrixXi F(0,3);
+  Eigen::MatrixXd TV;
+  Eigen::MatrixXi TT,TF;
+  Eigen::MatrixXd H,R;
+  Eigen::VectorXi FM,PT,TM,TR;
+  Eigen::VectorXi VM = (Eigen::VectorXi(5)<< 0, 1, 2, 3, 4).finished();
+  Eigen::MatrixXi TN,FT;
+  int num_regions;
+  igl::copyleft::tetgen::tetrahedralize(
+    V,F,H,VM,FM,R,"cpnnfmQ",TV,TT,TF,TM,TR,TN,PT,FT,num_regions);
+
+  REQUIRE (5 == TV.rows());
+  REQUIRE (2 == TT.rows());
+  REQUIRE (7 == TF.rows());
+  REQUIRE (TV.rows() == TM.rows());
+  REQUIRE (TN.rows() == TT.rows());
+  REQUIRE (TN.cols() == 4);
+  REQUIRE((TN.row(0).array() == 1).any());
+  REQUIRE((TN.row(1).array() == 0).any());
+  REQUIRE(FT.rows() == TF.rows());
+
+
+  REQUIRE(PT.size() == TV.rows());
+  REQUIRE(PT(0) == 0);
+  REQUIRE(PT(2) == 1);
+
+  Eigen::MatrixXi TTcorrect(2,4);
+  TTcorrect<< 
+    4,0,1,3,
+    4,3,1,2;
+  {
+    Eigen::MatrixXi TT_combined = Eigen::MatrixXi(TT.rows()+TTcorrect.rows(),TT.cols());
+    TT_combined<<TT,TTcorrect;
+    Eigen::MatrixXi TT_unique;
+    igl::unique_simplices(TT_combined,TT_unique);
+    REQUIRE(TT_unique.rows() == TT.rows());
+  }
+  test_common::assert_eq(TV,V);
+}
+
 TEST_CASE("tetrahedralize: schoenhardt", "[igl/copyleft/tetgen]")
 {
   const Eigen::MatrixXd V = (Eigen::MatrixXd(6,3)<<