瀏覽代碼

write TGF graphs, mesh with sampled skeleton edges, tiny xml

Former-commit-id: 2622ef92ff1e5ed03bdc0226aac96ae8964fdb56
Alec Jacobson (jalec 12 年之前
父節點
當前提交
020369bc7e

+ 8 - 91
examples/bbw/main.cpp

@@ -3,11 +3,9 @@
 #include <igl/readOBJ.h>
 #include <igl/readOFF.h>
 #include <igl/readMESH.h>
-#include <igl/sample_edges.h>
-#include <igl/cat.h>
+#include <igl/tetgen/mesh_with_skeleton.h>
 #include <igl/faces_first.h>
 #include <igl/readTGF.h>
-#include <igl/tetgen/tetrahedralize.h>
 #include <igl/launch_medit.h>
 #include <igl/boundary_conditions.h>
 #include <igl/mosek/bbw.h>
@@ -119,93 +117,6 @@ bool load_skeleton_from_file(
   return success;
 }
 
-// Mesh the interior of a given surface with tetrahedra which are graded (tend
-// to be small near the surface and large inside) and conform to the given
-// handles and samplings thereof.
-//
-// Inputs:
-//  V  #V by 3 list of mesh vertex positions
-//  F  #F by 3 list of triangle indices
-//  C  #C by 3 list of vertex positions
-//  P  #P list of point handle indices
-//  BE #BE by 2 list of bone-edge indices
-//  CE #CE by 2 list of cage-edge indices
-// Outputs:
-//  VV  #VV by 3 list of tet-mesh vertex positions
-//  TT  #TT by 4 list of tetrahedra indices
-//  FF  #FF by 3 list of surface triangle indices
-// Returns true only on success
-bool mesh_with_skeleton(
-  const Eigen::MatrixXd & V,
-  const Eigen::MatrixXi & F,
-  const Eigen::MatrixXd & C,
-  const Eigen::VectorXi & /*P*/,
-  const Eigen::MatrixXi & BE,
-  const Eigen::MatrixXi & CE,
-  Eigen::MatrixXd & VV,
-  Eigen::MatrixXi & TT,
-  Eigen::MatrixXi & FF)
-{
-  using namespace Eigen;
-  using namespace igl;
-  using namespace std;
-  // Collect all edges that need samples:
-  MatrixXi BECE = cat(1,BE,CE);
-  MatrixXd S;
-  // Sample each edge with 10 samples. (Choice of 10 doesn't seem to matter so
-  // much, but could under some circumstances)
-  sample_edges(C,BECE,10,S);
-  // Vertices we'll constrain tet mesh to meet
-  MatrixXd VS = cat(1,V,S);
-  // Boundary faces
-  MatrixXi BF;
-  // Use tetgen to mesh the interior of surface, this assumes surface:
-  //   * has no holes
-  //   * has no non-manifold edges or vertices
-  //   * has consistent orientation
-  //   * has no self-intersections
-  //   * has no 0-volume pieces
-  // Default settings pq100 tell tetgen to mesh interior of triangle mesh and
-  // to produce a graded tet mesh
-  cerr<<"tetgen begin()"<<endl;
-  int status = tetrahedralize( VS,F,"pq100",VV,TT,FF);
-  cerr<<"tetgen end()"<<endl;
-  if(FF.rows() != F.rows())
-  {
-    // Issue a warning if the surface has changed
-    cerr<<"mesh_with_skeleton: Warning: boundary faces != input faces"<<endl;
-  }
-  if(status != 0)
-  {
-    cerr<<
-      "***************************************************************"<<endl<<
-      "***************************************************************"<<endl<<
-      "***************************************************************"<<endl<<
-      "***************************************************************"<<endl<<
-      "* mesh_with_skeleton: tetgen failed. Just meshing convex hull *"<<endl<<
-      "***************************************************************"<<endl<<
-      "***************************************************************"<<endl<<
-      "***************************************************************"<<endl<<
-      "***************************************************************"<<endl;
-    // If meshing convex hull then use more regular mesh
-    status = tetrahedralize(VS,F,"q1.414",VV,TT,FF);
-    // I suppose this will fail if the skeleton is outside the mesh
-    assert(FF.maxCoeff() < VV.rows());
-    if(status != 0)
-    {
-      cerr<<"mesh_with_skeleton: tetgen failed again."<<endl;
-      return false;
-    }
-  }
-  // If you have medit installed then it's convenient to visualize the tet mesh
-  // at this point
-  if(WITH_MEDIT)
-  {
-    launch_medit(VV,TT,FF,false);
-  }
-  return true;
-}
-
 // Writes output files to /path/to/input/mesh-skeleton.dmat,
 // mesh-volume.dmat, mesh-volume.mesh if input mesh was
 // located at /path/to/input/mesh.obj and input skeleton was at
@@ -313,10 +224,16 @@ int main(int argc, char * argv[])
   MatrixXi TT;
   // New surface faces FF
   MatrixXi FF;
-  if(!mesh_with_skeleton(V,F,C,P,BE,CE,VV,TT,FF))
+  if(!mesh_with_skeleton(V,F,C,P,BE,CE,10,VV,TT,FF))
   {
     return 1;
   }
+  // If you have medit installed then it's convenient to visualize the tet mesh
+  // at this point
+  if(WITH_MEDIT)
+  {
+    launch_medit(VV,TT,FF,false);
+  }
   // Compute boundary conditions (aka fixed value constraints)
   // List of boundary indices (aka fixed value indices into VV)
   VectorXi b;

+ 1 - 1
include/igl/cotmatrix.h

@@ -20,7 +20,7 @@ namespace igl
   //
   // Templates:
   //   DerivedV  derived type of eigen matrix for V (e.g. derived from
-  //     MatirxXd)
+  //     MatrixXd)
   //   DerivedF  derived type of eigen matrix for F (e.g. derived from
   //     MatrixXi)
   //   Scalar  scalar type for eigen sparse matrix (e.g. double)

+ 4 - 4
include/igl/doublearea.h

@@ -8,11 +8,11 @@ namespace igl
   //
   // Templates:
   //   DerivedV  derived type of eigen matrix for V (e.g. derived from
-  //     MatirxXd)
+  //     MatrixXd)
   //   DerivedF  derived type of eigen matrix for F (e.g. derived from
   //     MatrixXi)
   //   DeriveddblA  derived type of eigen matrix for dblA (e.g. derived from
-  //     MatirxXd)
+  //     MatrixXd)
   // Inputs:
   //   V  #V by dim list of mesh vertex positions
   //   F  #F by simplex_size list of mesh faces (must be triangles)
@@ -26,11 +26,11 @@ namespace igl
   // Same as above but use instrinsic edge lengths rather than (V,F) mesh
   // Templates:
   //   DerivedV  derived type of eigen matrix for V (e.g. derived from
-  //     MatirxXd)
+  //     MatrixXd)
   //   DerivedF  derived type of eigen matrix for F (e.g. derived from
   //     MatrixXi)
   //   DeriveddblA  derived type of eigen matrix for dblA (e.g. derived from
-  //     MatirxXd)
+  //     MatrixXd)
   // Inputs:
   //   l  #F by dim list of edge lengths using 
   //     for triangles, columns correspond to edges 23,31,12

+ 1 - 1
include/igl/massmatrix.h

@@ -21,7 +21,7 @@ namespace igl
   //
   // Templates:
   //   DerivedV  derived type of eigen matrix for V (e.g. derived from
-  //     MatirxXd)
+  //     MatrixXd)
   //   DerivedF  derived type of eigen matrix for F (e.g. derived from
   //     MatrixXi)
   //   Scalar  scalar type for eigen sparse matrix (e.g. double)

+ 4 - 4
include/igl/mosek/bbw.h

@@ -30,11 +30,11 @@ namespace igl
   // set of boundary conditions
   //
   // Templates
-  //   DerivedV  derived type of eigen matrix for V (e.g. MatirxXd)
-  //   DerivedF  derived type of eigen matrix for F (e.g. MatirxXi)
+  //   DerivedV  derived type of eigen matrix for V (e.g. MatrixXd)
+  //   DerivedF  derived type of eigen matrix for F (e.g. MatrixXi)
   //   Derivedb  derived type of eigen matrix for b (e.g. VectorXi)
-  //   Derivedbc  derived type of eigen matrix for bc (e.g. MatirxXd)
-  //   DerivedW  derived type of eigen matrix for W (e.g. MatirxXd)
+  //   Derivedbc  derived type of eigen matrix for bc (e.g. MatrixXd)
+  //   DerivedW  derived type of eigen matrix for W (e.g. MatrixXd)
   // Inputs:
   //   V  #V by dim vertex positions
   //   Ele  #Elements by simplex-size list of element indices

+ 77 - 0
include/igl/tetgen/mesh_with_skeleton.cpp

@@ -0,0 +1,77 @@
+#include "mesh_with_skeleton.h"
+
+#include <igl/sample_edges.h>
+#include <igl/cat.h>
+#include <igl/tetgen/tetrahedralize.h>
+#include <igl/writeOFF.h>
+
+#include <iostream>
+
+bool igl::mesh_with_skeleton(
+  const Eigen::MatrixXd & V,
+  const Eigen::MatrixXi & F,
+  const Eigen::MatrixXd & C,
+  const Eigen::VectorXi & /*P*/,
+  const Eigen::MatrixXi & BE,
+  const Eigen::MatrixXi & CE,
+  const int samples_per_bone,
+  Eigen::MatrixXd & VV,
+  Eigen::MatrixXi & TT,
+  Eigen::MatrixXi & FF)
+{
+  using namespace Eigen;
+  using namespace igl;
+  using namespace std;
+  // Collect all edges that need samples:
+  MatrixXi BECE = cat(1,BE,CE);
+  MatrixXd S;
+  // Sample each edge with 10 samples. (Choice of 10 doesn't seem to matter so
+  // much, but could under some circumstances)
+  sample_edges(C,BECE,samples_per_bone,S);
+  // Vertices we'll constrain tet mesh to meet
+  MatrixXd VS = cat(1,V,S);
+  // Boundary faces
+  MatrixXi BF;
+  // Use tetgen to mesh the interior of surface, this assumes surface:
+  //   * has no holes
+  //   * has no non-manifold edges or vertices
+  //   * has consistent orientation
+  //   * has no self-intersections
+  //   * has no 0-volume pieces
+  // Default settings pq100 tell tetgen to mesh interior of triangle mesh and
+  // to produce a graded tet mesh
+  writeOFF("mesh_with_skeleton.off",VS,F);
+  cerr<<"tetgen begin()"<<endl;
+  int status = tetrahedralize( VS,F,"pq100Y",VV,TT,FF);
+  cerr<<"tetgen end()"<<endl;
+  if(FF.rows() != F.rows())
+  {
+    // Issue a warning if the surface has changed
+    cerr<<"mesh_with_skeleton: Warning: boundary faces != input faces"<<endl;
+  }
+  if(status != 0)
+  {
+    cerr<<
+      "***************************************************************"<<endl<<
+      "***************************************************************"<<endl<<
+      "***************************************************************"<<endl<<
+      "***************************************************************"<<endl<<
+      "* mesh_with_skeleton: tetgen failed. Just meshing convex hull *"<<endl<<
+      "***************************************************************"<<endl<<
+      "***************************************************************"<<endl<<
+      "***************************************************************"<<endl<<
+      "***************************************************************"<<endl;
+    // If meshing convex hull then use more regular mesh
+    status = tetrahedralize(VS,F,"q1.414",VV,TT,FF);
+    // I suppose this will fail if the skeleton is outside the mesh
+    assert(FF.maxCoeff() < VV.rows());
+    if(status != 0)
+    {
+      cerr<<"mesh_with_skeleton: tetgen failed again."<<endl;
+      return false;
+    }
+  }
+
+  return true;
+}
+

+ 43 - 0
include/igl/tetgen/mesh_with_skeleton.h

@@ -0,0 +1,43 @@
+#ifndef IGL_MESH_WITH_SKELETON_H
+#define IGL_MESH_WITH_SKELETON_H
+#include "../igl_inline.h"
+#include <Eigen/Dense>
+
+namespace igl
+{
+// Mesh the interior of a given surface with tetrahedra which are graded (tend
+// to be small near the surface and large inside) and conform to the given
+// handles and samplings thereof.
+//
+// Inputs:
+//  V  #V by 3 list of mesh vertex positions
+//  F  #F by 3 list of triangle indices
+//  C  #C by 3 list of vertex positions
+//  P  #P list of point handle indices
+//  BE #BE by 2 list of bone-edge indices
+//  CE #CE by 2 list of cage-edge indices
+//  samples_per_bone  #samples to add per bone
+// Outputs:
+//  VV  #VV by 3 list of tet-mesh vertex positions
+//  TT  #TT by 4 list of tetrahedra indices
+//  FF  #FF by 3 list of surface triangle indices
+// Returns true only on success
+bool mesh_with_skeleton(
+  const Eigen::MatrixXd & V,
+  const Eigen::MatrixXi & F,
+  const Eigen::MatrixXd & C,
+  const Eigen::VectorXi & /*P*/,
+  const Eigen::MatrixXi & BE,
+  const Eigen::MatrixXi & CE,
+  const int samples_per_bone,
+  Eigen::MatrixXd & VV,
+  Eigen::MatrixXi & TT,
+  Eigen::MatrixXi & FF);
+}
+
+
+#ifdef IGL_HEADER_ONLY
+#  include "mesh_with_skeleton.cpp"
+#endif
+
+#endif

+ 66 - 0
include/igl/writeTGF.cpp

@@ -0,0 +1,66 @@
+#include "writeTGF.h"
+
+IGL_INLINE bool igl::writeTGF(
+  const std::string tgf_filename,
+  const std::vector<std::vector<double> > & C,
+  const std::vector<std::vector<int> > & E)
+{
+  FILE * tgf_file = fopen(tgf_filename.c_str(),"w");
+  if(NULL==tgf_file)
+  {
+    printf("IOError: %s could not be opened\n",tgf_filename.c_str());
+    return false;  
+  }
+  // Loop over vertices
+  for(int i = 0; i<(int)C.size();i++)
+  {
+    assert(C[i].size() == 3);
+    // print a line with vertex number then "description"
+    // Where "description" in our case is the 3d position in space
+    // 
+    fprintf(tgf_file,
+      "%4d "
+      "%10.17g %10.17g %10.17g " // current location
+      // All others are not needed for this legacy support
+      "\n",
+      i+1,
+      C[i][0], C[i][1], C[i][2]);
+  }
+
+  // print a comment to separate vertices and edges
+  fprintf(tgf_file,"#\n");
+
+  // loop over edges
+  for(int i = 0;i<(int)E.size();i++)
+  {
+    assert(E[i].size()==2);
+    fprintf(tgf_file,"%4d %4d\n",
+      E[i][0]+1,
+      E[i][1]+1);
+  }
+
+  // print a comment to separate edges and faces
+  fprintf(tgf_file,"#\n");
+
+  fclose(tgf_file);
+
+  return true;
+}
+
+#ifndef IGL_NO_EIGEN
+#include "matrix_to_list.h"
+
+IGL_INLINE bool igl::writeTGF(
+  const std::string tgf_filename,
+  const Eigen::MatrixXd & C,
+  const Eigen::MatrixXi & E)
+{
+  using namespace igl;
+  using namespace std;
+  vector<vector<double> > vC;
+  vector<vector<int> > vE;
+  matrix_to_list(C,vC);
+  matrix_to_list(E,vE);
+  return writeTGF(tgf_filename,vC,vE);
+}
+#endif

+ 41 - 0
include/igl/writeTGF.h

@@ -0,0 +1,41 @@
+#ifndef IGL_WRITETGF_H
+#define IGL_WRITETGF_H
+#include "igl_inline.h"
+
+#include <vector>
+#include <string>
+#ifndef IGL_NO_EIGEN
+#include <Eigen/Dense>
+#endif
+
+namespace igl
+{
+  // WRITETGF
+  //
+  // Write a graph to a .tgf file
+  //
+  // Input:
+  //  filename  .tgf file name
+  //  V  # vertices by 3 list of vertex positions
+  //  E  # edges by 2 list of edge indices
+  // 
+  // Assumes that graph vertices are 3 dimensional
+  IGL_INLINE bool writeTGF(
+    const std::string tgf_filename,
+    const std::vector<std::vector<double> > & C,
+    const std::vector<std::vector<int> > & E);
+
+  #ifndef IGL_NO_EIGEN
+  IGL_INLINE bool writeTGF(
+    const std::string tgf_filename,
+    const Eigen::MatrixXd & C,
+    const Eigen::MatrixXi & E);
+  #endif
+}
+
+#ifdef IGL_HEADER_ONLY
+#  include "writeTGF.cpp"
+#endif
+
+#endif
+