瀏覽代碼

more agressive handling of co-planar/duplicate facets

Former-commit-id: c51eaa71b7db6c9584f41941ad4f63333847c58d
Alec Jacobson 10 年之前
父節點
當前提交
168e528acc
共有 2 個文件被更改,包括 47 次插入12 次删除
  1. 1 1
      include/igl/boolean/mesh_boolean.cpp
  2. 46 11
      include/igl/outer_hull.cpp

+ 1 - 1
include/igl/boolean/mesh_boolean.cpp

@@ -169,7 +169,7 @@ IGL_INLINE void igl::mesh_boolean(
     return;
   }
   MatrixX3S N,CN;
-  per_face_normals(V,F,N);
+  per_face_normals_stable(V,F,N);
   CN.resize(CF.rows(),3);
   for(size_t f = 0;f<(size_t)CN.rows();f++)
   {

+ 46 - 11
include/igl/outer_hull.cpp

@@ -42,6 +42,17 @@ IGL_INLINE void igl::outer_hull(
   typedef Matrix<typename DerivedN::Scalar,1,3> RowVector3N;
   const Index m = F.rows();
 
+  const auto & duplicate_simplex = [&F](const int f, const int g)->bool
+  {
+    return 
+      (F(f,0) == F(g,0) && F(f,1) == F(g,1) && F(f,2) == F(g,2)) ||
+      (F(f,1) == F(g,0) && F(f,2) == F(g,1) && F(f,0) == F(g,2)) ||
+      (F(f,2) == F(g,0) && F(f,0) == F(g,1) && F(f,1) == F(g,2)) ||
+      (F(f,0) == F(g,2) && F(f,1) == F(g,1) && F(f,2) == F(g,0)) ||
+      (F(f,1) == F(g,2) && F(f,2) == F(g,1) && F(f,0) == F(g,0)) ||
+      (F(f,2) == F(g,2) && F(f,0) == F(g,1) && F(f,1) == F(g,0));
+  };
+
 #ifdef IGL_OUTER_HULL_DEBUG
   cout<<"outer hull..."<<endl;
 #endif
@@ -107,11 +118,32 @@ IGL_INLINE void igl::outer_hull(
       // duplicate faces the same way, regardless of their orientations
       di_I(fei,1) = (cons[fei]?1.:-1.)*f;
     }
-    VectorXi IM;
 
+    // Despite the effort to get stable normals the atan2 up doesn't
+    // compute (exactly) -θ for -n if it computes θ for n. So just
+    // explicitly check if there's a duplicate face
+    // Shitty O(val^2) implementation
+    for(size_t fei = 0;fei<uE2E[ui].size();fei++)
+    {
+      const auto & fe = uE2E[ui][fei];
+      const auto f = fe % m;
+      for(size_t gei = fei+1;gei<uE2E[ui].size();gei++)
+      {
+        const auto & ge = uE2E[ui][gei];
+        const auto g = ge % m;
+        if(duplicate_simplex(f,g))
+        {
+#ifdef IGL_OUTER_HULL_DEBUG
+          cout<<"Forcing duplicate: "<<(f+1)<<","<<(g+1)<<endl;
+#endif
+          di_I(gei,0) = di_I(fei,0);
+        }
+      }
+    }
+    VectorXi IM;
     //igl::sort(di[ui],true,di[ui],IM);
-    // Sort, but break ties using index to ensure that duplicates always show
-    // up in same order.
+    // Sort, but break ties using "signed index" to ensure that duplicates
+    // always show up in same order.
     MatrixXd s_di_I;
     igl::sortrows(di_I,true,s_di_I,IM);
     di[ui].resize(uE2E[ui].size());
@@ -247,16 +279,19 @@ IGL_INLINE void igl::outer_hull(
         const int nfei_new = (diIM(e) + 2*val + e_cons*step*(flip(f)?-1:1))%val;
         const int nf = uE2E[EMAP(e)][nfei_new] % m;
         // Don't consider faces with identical dihedral angles
-        if(di[EMAP(e)][diIM(e)] != di[EMAP(e)][nfei_new])
+        if((di[EMAP(e)][diIM(e)] != di[EMAP(e)][nfei_new]))
 //#warning "THIS IS HACK, FIX ME"
 //        if( abs(di[EMAP(e)][diIM(e)] - di[EMAP(e)][nfei_new]) < 1e-16 )
         {
-//#ifdef IGL_OUTER_HULL_DEBUG
-//        cout<<"Next facet: "<<(f+1)<<" --> "<<(nf+1)<<", |"<<
-//          di[EMAP(e)][diIM(e)]<<" - "<<di[EMAP(e)][nfei_new]<<"| = "<<
-//            abs(di[EMAP(e)][diIM(e)] - di[EMAP(e)][nfei_new])
-//            <<endl;
-//#endif
+#ifdef IGL_OUTER_HULL_DEBUG
+        cout<<"Next facet: "<<(f+1)<<" --> "<<(nf+1)<<", |"<<
+          di[EMAP(e)][diIM(e)]<<" - "<<di[EMAP(e)][nfei_new]<<"| = "<<
+            abs(di[EMAP(e)][diIM(e)] - di[EMAP(e)][nfei_new])
+            <<endl;
+#endif
+        
+
+
           // Only use this face if not already seen
           if(!FH[nf])
           {
@@ -517,7 +552,7 @@ IGL_INLINE void igl::outer_hull(
   Eigen::PlainObjectBase<Derivedflip> & flip)
 {
   Eigen::Matrix<typename DerivedV::Scalar,DerivedF::RowsAtCompileTime,3> N;
-  per_face_normals(V,F,N);
+  per_face_normals_stable(V,F,N);
   return outer_hull(V,F,N,G,J,flip);
 }