Просмотр исходного кода

boolean input validation as stand-alone functions

Former-commit-id: 836029c03561a1ea78abd8d26b519b1c01736c69
Alec Jacobson 9 лет назад
Родитель
Сommit
e6536d3355

+ 29 - 0
include/igl/copyleft/cgal/piecewise_constant_winding_number.cpp

@@ -0,0 +1,29 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson
+// 
+// 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 "piecewise_constant_winding_number.h"
+#include "../../piecewise_constant_winding_number.h"
+#include "remesh_self_intersections.h"
+#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+#include <algorithm>
+
+template < typename DerivedV, typename DerivedF>
+IGL_INLINE bool igl::piecewise_constant_winding_number(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::PlainObjectBase<DerivedF> & F)
+{
+  Eigen::Matrix<CGAL::Epeck::FT,Eigen::Dynamic,3> VV;
+  Eigen::Matrix<typename DerivedF::Scalar,Eigen::Dynamic,3> FF;
+  Eigen::Matrix<typename DerivedF::Index,Eigen::Dynamic,2> IF;
+  Eigen::Matrix<typename DerivedF::Index,Eigen::Dynamic,1> J;
+  Eigen::Matrix<typename DerivedV::Index,Eigen::Dynamic,1> UIM,IM;
+  // resolve intersections
+  remesh_self_intersections(V,F,{},VV,FF,IF,J,IM);
+  // _apply_ duplicate vertex mapping IM to FF
+  for_each(FF.data(),FF.data()+FF.size(),[&IM](int & a){a=IM(a);});
+  return piecewise_constant_winding_number(FF);
+}

+ 41 - 0
include/igl/copyleft/cgal/piecewise_constant_winding_number.h

@@ -0,0 +1,41 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson
+// 
+// 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_CGAL_PIECEWISE_CONSTANT_WINDING_NUMBER_H
+#define IGL_COPYLEFT_CGAL_PIECEWISE_CONSTANT_WINDING_NUMBER_H
+#include "../../igl_inline.h"
+#include <Eigen/Core>
+#include <vector>
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // PIECEWISE_CONSTANT_WINDING_NUMBER Determine if a given mesh induces a
+      // piecewise constant winding number field: Is this mesh valid input to
+      // solid set operations.
+      // 
+      // Inputs:
+      //   V  #V by 3 list of mesh vertex positions
+      //   F  #F by 3 list of triangle indices into V
+      // Returns true if the mesh _combinatorially_ induces a piecewise
+      // constant winding number field.
+      template <
+        typename DerivedV,
+        typename DerivedF>
+      IGL_INLINE bool piecewise_constant_winding_number(
+        const Eigen::PlainObjectBase<DerivedV> & V,
+        const Eigen::PlainObjectBase<DerivedF>& F);
+    }
+  }
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "piecewise_constant_winding_number.cpp"
+#endif
+#endif
+

+ 4 - 43
include/igl/copyleft/cgal/propagate_winding_numbers.cpp

@@ -11,6 +11,7 @@
 #include "../../extract_non_manifold_edge_curves.h"
 #include "../../facet_components.h"
 #include "../../unique_edge_map.h"
+#include "../../piecewise_constant_winding_number.h"
 #include "../../writeOBJ.h"
 #include "../../writePLY.h"
 #include "../../get_seconds.h"
@@ -28,47 +29,6 @@
 
 //#define PROPAGATE_WINDING_NUMBER_TIMING
 
-namespace propagate_winding_numbers_helper {
-  template<
-    typename DerivedF,
-    typename DeriveduE,
-    typename uE2EType >
-  bool is_orientable(
-      const Eigen::PlainObjectBase<DerivedF>& F,
-      const Eigen::PlainObjectBase<DeriveduE>& uE,
-      const std::vector<std::vector<uE2EType> >& uE2E) {
-    const size_t num_faces = F.rows();
-    const size_t num_edges = uE.rows();
-    auto edge_index_to_face_index = [&](size_t ei) {
-      return ei % num_faces;
-    };
-    auto is_consistent = [&](size_t fid, size_t s, size_t d) {
-      if ((size_t)F(fid, 0) == s && (size_t)F(fid, 1) == d) return true;
-      if ((size_t)F(fid, 1) == s && (size_t)F(fid, 2) == d) return true;
-      if ((size_t)F(fid, 2) == s && (size_t)F(fid, 0) == d) return true;
-
-      if ((size_t)F(fid, 0) == d && (size_t)F(fid, 1) == s) return false;
-      if ((size_t)F(fid, 1) == d && (size_t)F(fid, 2) == s) return false;
-      if ((size_t)F(fid, 2) == d && (size_t)F(fid, 0) == s) return false;
-      throw "Invalid face!!";
-    };
-    for (size_t i=0; i<num_edges; i++) {
-      const size_t s = uE(i,0);
-      const size_t d = uE(i,1);
-      int count=0;
-      for (const auto& ei : uE2E[i]) {
-        const size_t fid = edge_index_to_face_index(ei);
-        if (is_consistent(fid, s, d)) count++;
-        else count--;
-      }
-      if (count != 0) {
-        return false;
-      }
-    }
-    return true;
-  }
-}
-
 template<
   typename DerivedV,
   typename DerivedF,
@@ -96,8 +56,9 @@ IGL_INLINE void igl::copyleft::cgal::propagate_winding_numbers(
   Eigen::VectorXi EMAP;
   std::vector<std::vector<size_t> > uE2E;
   igl::unique_edge_map(F, E, uE, EMAP, uE2E);
-  if (!propagate_winding_numbers_helper::is_orientable(F, uE, uE2E)) {
-      std::cerr << "Input mesh is not orientable!" << std::endl;
+  if (!piecewise_constant_winding_number(F, uE, uE2E)) 
+  {
+    std::cerr << "Input mesh is not orientable!" << std::endl;
   }
 
   Eigen::VectorXi P;

+ 70 - 0
include/igl/piecewise_constant_winding_number.cpp

@@ -0,0 +1,70 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson
+// 
+// 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 "piecewise_constant_winding_number.h"
+#include "unique_edge_map.h"
+
+template <
+  typename DerivedF,
+  typename DeriveduE,
+  typename uE2EType>
+IGL_INLINE bool igl::piecewise_constant_winding_number(
+  const Eigen::PlainObjectBase<DerivedF>& F,
+  const Eigen::PlainObjectBase<DeriveduE>& uE,
+  const std::vector<std::vector<uE2EType> >& uE2E)
+{
+  const size_t num_faces = F.rows();
+  const size_t num_edges = uE.rows();
+  const auto edge_index_to_face_index = [&](size_t ei)
+  {
+    return ei % num_faces;
+  };
+  const auto is_consistent = [&](size_t fid, size_t s, size_t d)
+  {
+    if ((size_t)F(fid, 0) == s && (size_t)F(fid, 1) == d) return true;
+    if ((size_t)F(fid, 1) == s && (size_t)F(fid, 2) == d) return true;
+    if ((size_t)F(fid, 2) == s && (size_t)F(fid, 0) == d) return true;
+
+    if ((size_t)F(fid, 0) == d && (size_t)F(fid, 1) == s) return false;
+    if ((size_t)F(fid, 1) == d && (size_t)F(fid, 2) == s) return false;
+    if ((size_t)F(fid, 2) == d && (size_t)F(fid, 0) == s) return false;
+    throw "Invalid face!!";
+  };
+  for (size_t i=0; i<num_edges; i++)
+  {
+    const size_t s = uE(i,0);
+    const size_t d = uE(i,1);
+    int count=0;
+    for (const auto& ei : uE2E[i])
+    {
+      const size_t fid = edge_index_to_face_index(ei);
+      if (is_consistent(fid, s, d))
+      {
+        count++;
+      }
+      else
+      {
+        count--;
+      }
+    }
+    if (count != 0)
+    {
+      return false;
+    }
+  }
+  return true;
+}
+template <typename DerivedF>
+IGL_INLINE bool igl::piecewise_constant_winding_number(
+  const Eigen::PlainObjectBase<DerivedF>& F)
+{
+  Eigen::Matrix<typename DerivedF::Scalar,Eigen::Dynamic,2> E, uE;
+  Eigen::Matrix<typename DerivedF::Scalar,Eigen::Dynamic,1> EMAP;
+  std::vector<std::vector<size_t> > uE2E;
+  unique_edge_map(F, E, uE, EMAP, uE2E);
+  return piecewise_constant_winding_number(F,uE,uE2E);
+}

+ 49 - 0
include/igl/piecewise_constant_winding_number.h

@@ -0,0 +1,49 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson
+// 
+// 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_PIECEWISE_CONSTANT_WINDING_NUMBER_H
+#define IGL_PIECEWISE_CONSTANT_WINDING_NUMBER_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+#include <vector>
+namespace igl
+{
+  // PIECEWISE_CONSTANT_WINDING_NUMBER Determine if a given mesh induces a
+  // piecewise constant winding number field: Is this mesh valid input to solid
+  // set operations.  **Assumes** that `(V,F)` contains no self-intersections
+  // (including degeneracies and co-incidences).  If there are co-planar and
+  // co-incident vertex placements, a mesh could _fail_ this combinatorial test
+  // but still induce a piecewise-constant winding number _geometrically_. For
+  // example, consider a hemisphere with boundary and then pinch the boundary
+  // "shut" along a line segment. The **_bullet-proof_** check is to first
+  // resolve all self-intersections in `(V,F) -> (SV,SF)` (i.e. what the
+  // `igl::copyleft::cgal::piecewise_constant_winding_number` overload does).
+  //
+  // Inputs:
+  //   F  #F by 3 list of triangle indices into some (abstract) list of
+  //     vertices V
+  //   uE  #uE by 2 list of unique edges indices into V
+  //   uE2E  #uE list of lists of indices into directed edges (#F * 3)
+  // Returns true if the mesh _combinatorially_ induces a piecewise constant
+  // winding number field.
+  //
+  template <
+    typename DerivedF,
+    typename DeriveduE,
+    typename uE2EType>
+  IGL_INLINE bool piecewise_constant_winding_number(
+    const Eigen::PlainObjectBase<DerivedF>& F,
+    const Eigen::PlainObjectBase<DeriveduE>& uE,
+    const std::vector<std::vector<uE2EType> >& uE2E);
+  template <typename DerivedF>
+  IGL_INLINE bool piecewise_constant_winding_number(
+    const Eigen::PlainObjectBase<DerivedF>& F);
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "piecewise_constant_winding_number.cpp"
+#endif
+#endif