Browse Source

fix bug in cut_mesh; improve documentation; add test (#2315)

Alec Jacobson 1 year ago
parent
commit
37f3b1d821
3 changed files with 38 additions and 16 deletions
  1. 7 2
      include/igl/cut_mesh.cpp
  2. 7 11
      include/igl/cut_mesh.h
  3. 24 3
      tests/include/igl/cut_mesh.cpp

+ 7 - 2
include/igl/cut_mesh.cpp

@@ -75,9 +75,14 @@ IGL_INLINE void igl::cut_mesh(
     for(Index k=0;k<3;k++){
       Index u = F(i,k);
       Index v = F(i,(k+1)%3);
-      if(FF(i,k) == -1){ // add one extra occurance for boundary vertices
+      if(FF(i,k) == -1){ 
+        // add one extra occurance for boundary vertices
         eventual(u) += 1;
-      }else if(C(i,k) == 1 && u < v){ // only compute every (undirected) edge ones
+      }else if( 
+          (u < v) && 
+          (C(i,k) || C(FF(i,k),FFi(i,k))) )
+      { 
+        // only compute every (undirected) edge ones
         eventual(u) += 1;
         eventual(v) += 1;
       }

+ 7 - 11
include/igl/cut_mesh.h

@@ -21,9 +21,14 @@ namespace igl
   ///
   /// @param[in,out] V  #V by 3 list of the vertex positions
   /// @param[in,out] F  #F by 3 list of the faces
-  /// @param[in] cuts  #F by 3 list of boolean flags, indicating the edges that need to
-  ///     be cut (has 1 at the face edges that are to be cut, 0 otherwise)
+  /// @param[in] cuts  #F by 3 list of boolean flags, so that cuts(i,j)
+  ///   indicates that the edge from F(i,j) to F(i,j+1%3) should be cut. A true
+  ///   value on either incident face will result in a cut.
   /// @param[out]  I   #V by 1 list of the map between Vn to original V index.
+  ///
+  /// \note `cuts` assumes the ordering convention from the array-based
+  /// triangle_triangle_adjacency which is DIFFERENT from
+  /// cotmatrix_entries,edge_lengths/etc.
   template <typename DerivedV, typename DerivedF, typename DerivedC, typename DerivedI>
   IGL_INLINE void cut_mesh(
     Eigen::PlainObjectBase<DerivedV>& V,
@@ -37,15 +42,10 @@ namespace igl
   ///
   /// \note Assumes mesh is edge-manifold.
   ///
-  /// @param[in,out] V  #V by 3 list of the vertex positions
-  /// @param[in,out] F  #F by 3 list of the faces
   /// @param[in,out] FF   #F by #3 adjacent matrix, the element i,j is the id of the triangle
   ///        adjacent to the j edge of triangle i
   /// @param[in,out] FFi  #F by #3 adjacent matrix, the element i,j is the id of edge of the
   ///        triangle TT(i,j) that is adjacent with triangle i
-  /// @param[in] C #F by 3 list of boolean flags, indicating the edges that need to
-  ///     be cut (has 1 at the face edges that are to be cut, 0 otherwise)
-  /// @param[out]  I   #V by 1 list of the map between Vn to original V index.
   ///
   /// \see triangle_triangle_adjacency
   template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedFFi, typename DerivedC, typename DerivedI>
@@ -63,10 +63,6 @@ namespace igl
   ///
   ///
   /// \note Assumes mesh is edge-manifold.
-  /// @param[in,out] V  #V by 3 list of the vertex positions
-  /// @param[in,out] F  #F by 3 list of the faces
-  /// @param[in] cuts  #F by 3 list of boolean flags, indicating the edges that need to
-  ///     be cut (has 1 at the face edges that are to be cut, 0 otherwise)
   /// @param[out]  Vn  #V by 3 list of the vertex positions of the cut mesh. This matrix
   ///     will be similar to the original vertices except some rows will be
   ///     duplicated.

+ 24 - 3
tests/include/igl/cut_mesh.cpp

@@ -3,7 +3,7 @@
 #include <igl/vertex_components.h>
 #include <igl/edges.h>
 
-TEST_CASE("seperate mesh", "[igl]") {
+TEST_CASE("cut_mesh: seperate mesh", "[igl]") {
   
   Eigen::MatrixXd V(9,3);
   V << 0,0,0,
@@ -42,7 +42,7 @@ TEST_CASE("seperate mesh", "[igl]") {
 
 }
 
-TEST_CASE("single edge", "[igl]") {
+TEST_CASE("cut_mesh: single edge", "[igl]") {
   
   Eigen::MatrixXd V(9,3);
   V << 0,0,0,
@@ -83,4 +83,25 @@ TEST_CASE("single edge", "[igl]") {
   const auto euler = V.rows() - E.rows() + F.rows();
   REQUIRE ( 1 == euler );
 
-}
+}
+
+TEST_CASE("cut_mesh: two triangles", "[igl]") {
+
+  Eigen::MatrixXd V(4,3);
+  V << 0,0,0,
+       0,1,0,
+       1,0,0,
+       1,1,0;
+  Eigen::MatrixXi F(2,3);
+  F << 0,1,2,
+       2,1,3;
+  // Only mark one side of the internal edge to cut. This should still work.
+  Eigen::MatrixXi C(2,3);
+  C << 0,0,0,
+       1,0,0;
+
+  Eigen::MatrixXd VCut;
+  Eigen::MatrixXi FCut;
+  igl::cut_mesh(V,F,C,VCut,FCut);
+  REQUIRE( VCut.rows() == 6 );
+}