فهرست منبع

Handle degenerated edge properly in outer hull computation.

Former-commit-id: 45140664c10fc0e33c3fd6f53146dd128ae57ca4
Qingnan Zhou 10 سال پیش
والد
کامیت
644ac5962b
1فایلهای تغییر یافته به همراه51 افزوده شده و 1 حذف شده
  1. 51 1
      include/igl/outer_hull.cpp

+ 51 - 1
include/igl/outer_hull.cpp

@@ -61,6 +61,7 @@ IGL_INLINE void igl::outer_hull(
 #endif
   typedef Matrix<typename DerivedF::Scalar,Dynamic,2> MatrixX2I;
   typedef Matrix<typename DerivedF::Index,Dynamic,1> VectorXI;
+  typedef Matrix<typename DerivedV::Scalar, 3, 1> Vector3F;
   MatrixX2I E,uE;
   VectorXI EMAP;
   vector<vector<typename DerivedF::Index> > uE2E;
@@ -85,10 +86,59 @@ IGL_INLINE void igl::outer_hull(
     const RowVector3N & eVp = N.row(fe0%m);
     MatrixXd di_I(uE2E[ui].size(),2);
 
+    const typename DerivedF::Scalar o = F(fe0%m, fe0/m);
     const typename DerivedF::Scalar d = F(fe0%m,((fe0/m)+2)%3);
     const typename DerivedF::Scalar s = F(fe0%m,((fe0/m)+1)%3);
     // Edge vector
-    const auto & eV = (V.row(d)-V.row(s)).normalized();
+    auto eV = (V.row(d)-V.row(s)).normalized();
+    auto edge_len = (V.row(d) - V.row(s)).norm();
+    auto edge_valance = uE2E[ui].size();
+    bool degenerated = !eV.allFinite() || edge_len < 1e-12;
+#ifdef IGL_OUTER_HULL_DEBUG
+    if (degenerated && edge_valance > 2) {
+        cerr.precision(30);
+        std::cerr << ui << ": " << (V.row(d) - V.row(s)).norm() << std::endl;
+        std::cerr << "Edge valance: " << edge_valance << std::endl;
+        std::cerr << V.row(d) << std::endl;
+        std::cerr << V.row(s) << std::endl;
+    }
+#endif
+    if (degenerated) {
+        const size_t num_adj_faces = uE2E[ui].size();
+        Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 3>
+            normals(num_adj_faces, 3);
+        for (size_t fei=0; fei<num_adj_faces; fei++) {
+            const auto & fe = uE2E[ui][fei];
+            const auto f = fe % m;
+            const RowVector3N & n = N.row(f);
+            normals.row(fei) = n;
+        }
+        for (size_t i=0; i<num_adj_faces; i++) {
+            size_t j = (i+1) % num_adj_faces;
+            eV = normals.row(i).cross(normals.row(j));
+            auto length = eV.norm();
+            if (length > 1e-12) {
+                eV /= length;
+                break;
+            }
+        }
+    }
+    if (!eV.allFinite() || eV.norm() < 1e-12) {
+        //cerr << "This is bad... all adj face normals are colinear" << std::endl;
+        eV.setZero();
+    } 
+    if (degenerated){
+        // Adjust edge direction.
+        Vector3F in_face_vec = V.row(o) - V.row(s);
+        Vector3F edge = eV;
+        if (edge.cross(in_face_vec).dot(eVp) < 0) {
+#ifdef IGL_OUTER_HULL_DEBUG
+            cerr << "Flipping edge..." << std::endl;
+#endif
+            eV *= -1;
+        }
+        //cerr << "Resolved: " << eV << std::endl;
+    }
 
     vector<bool> cons(uE2E[ui].size());
     // Loop over incident face edges