Pārlūkot izejas kodu

merge

Former-commit-id: 061e126b6c1b87493a8626d3a24f15df91ba69c3
Alec Jacobson 9 gadi atpakaļ
vecāks
revīzija
b14f79e050

+ 1 - 1
include/igl/copyleft/boolean/CSGTree.h

@@ -98,7 +98,7 @@ namespace igl
             mesh_boolean(A.V(),A.F(),B.V(),B.F(),type,m_V,m_F,m_J);
             // reindex m_J
             std::for_each(m_J.data(),m_J.data()+m_J.size(),
-              [&](typename VectorJ::Scalar & j)
+              [&](typename VectorJ::Scalar & j) -> void
               {
                 if(j < A.F().rows())
                 {

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

@@ -20,6 +20,8 @@
 #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
 #include <algorithm>
 
+//#define MESH_BOOLEAN_TIMING
+
 template <
   typename DerivedVA,
   typename DerivedFA,
@@ -43,6 +45,21 @@ IGL_INLINE void igl::copyleft::boolean::mesh_boolean(
     Eigen::PlainObjectBase<DerivedFC > & FC,
     Eigen::PlainObjectBase<DerivedJ > & J) {
 
+#ifdef MESH_BOOLEAN_TIMING
+  const auto & tictoc = []() -> double
+  {
+    static double t_start = igl::get_seconds();
+    double diff = igl::get_seconds()-t_start;
+    t_start += diff;
+    return diff;
+  };
+  const auto log_time = [&](const std::string& label) -> void {
+    std::cout << "mesh_boolean." << label << ": "
+      << tictoc() << std::endl;
+  };
+  tictoc();
+#endif
+
   typedef typename DerivedVC::Scalar Scalar;
   //typedef typename DerivedFC::Scalar Index;
   typedef CGAL::Epeck Kernel;
@@ -84,6 +101,9 @@ IGL_INLINE void igl::copyleft::boolean::mesh_boolean(
       //}
       resolve_fun(VV, FF, V, F, CJ);
   }
+#ifdef MESH_BOOLEAN_TIMING
+  log_time("resolve_self_intersection");
+#endif
 
   // Compute winding numbers on each side of each facet.
   const size_t num_faces = F.rows();
@@ -91,7 +111,11 @@ IGL_INLINE void igl::copyleft::boolean::mesh_boolean(
   Eigen::VectorXi labels(num_faces);
   std::transform(CJ.data(), CJ.data()+CJ.size(), labels.data(),
       [&](int i) { return i<FA.rows() ? 0:1; });
-  igl::copyleft::cgal::propagate_winding_numbers(V, F, labels, W);
+  if (num_faces > 0) {
+    igl::copyleft::cgal::propagate_winding_numbers(V, F, labels, W);
+  } else {
+    W.resize(0, 4);
+  }
   assert((size_t)W.rows() == num_faces);
   if (W.cols() == 2) {
     assert(FB.rows() == 0);
@@ -101,6 +125,9 @@ IGL_INLINE void igl::copyleft::boolean::mesh_boolean(
   } else {
     assert(W.cols() == 4);
   }
+#ifdef MESH_BOOLEAN_TIMING
+  log_time("propagate_input_winding_number");
+#endif
 
   // Compute resulting winding number.
   Eigen::MatrixXi Wr(num_faces, 2);
@@ -111,6 +138,9 @@ IGL_INLINE void igl::copyleft::boolean::mesh_boolean(
     Wr(i,0) = wind_num_op(w_out);
     Wr(i,1) = wind_num_op(w_in);
   }
+#ifdef MESH_BOOLEAN_TIMING
+  log_time("compute_output_winding_number");
+#endif
 
   // Extract boundary separating inside from outside.
   auto index_to_signed_index = [&](size_t i, bool ori) -> int{
@@ -141,6 +171,9 @@ IGL_INLINE void igl::copyleft::boolean::mesh_boolean(
     }
     kept_face_indices(i, 0) = CJ[idx];
   }
+#ifdef MESH_BOOLEAN_TIMING
+  log_time("extract_output");
+#endif
 
   // Finally, remove duplicated faces and unreferenced vertices.
   {
@@ -160,6 +193,9 @@ IGL_INLINE void igl::copyleft::boolean::mesh_boolean(
     Eigen::VectorXi newIM;
     igl::remove_unreferenced(Vs,G,VC,FC,newIM);
   }
+#ifdef MESH_BOOLEAN_TIMING
+  log_time("clean_up");
+#endif
 }
 
 template <

+ 150 - 128
include/igl/copyleft/cgal/SelfIntersectMesh.h

@@ -15,6 +15,8 @@
 #include <list>
 #include <map>
 #include <vector>
+#include <thread>
+#include <mutex>
 
 //#define IGL_SELFINTERSECTMESH_DEBUG
 #ifndef IGL_FIRST_HIT_EXCEPTION
@@ -90,14 +92,14 @@ namespace igl
           // Number of self-intersecting triangle pairs
           typedef typename DerivedF::Index Index;
           Index count;
-          typedef std::vector<CGAL::Object> ObjectList;
+          typedef std::vector<std::pair<Index, CGAL::Object>> ObjectList;
           // Using a vector here makes this **not** output sensitive
           Triangles T;
           typedef std::vector<Index> IndexList;
           IndexList lIF;
           // #F-long list of faces with intersections mapping to the order in
           // which they were first found
-          std::map<Index,std::pair<Index,ObjectList> > offending;
+          std::map<Index,ObjectList> offending;
           // Make a short name for the edge map's key
           typedef std::pair<Index,Index> EMK;
           // Make a short name for the type stored at each edge, the edge map's
@@ -107,6 +109,8 @@ namespace igl
           typedef std::map<EMK,EMV> EdgeMap;
           // Maps edges of offending faces to all incident offending faces
           EdgeMap edge2faces;
+          std::vector<std::pair<const Box, const Box> > candidate_box_pairs;
+
         public:
           RemeshSelfIntersectionsParam params;
         public:
@@ -143,7 +147,7 @@ namespace igl
           //   A  triangle in 3D
           //   B  triangle in 3D
           //   fa  index of A in F (and key into offending)
-          //   fb  index of A in F (and key into offending)
+          //   fb  index of B in F (and key into offending)
           // Returns true only if A intersects B
           //
           inline bool intersect(
@@ -200,6 +204,7 @@ namespace igl
           //   a  box containing a triangle
           //   b  box containing a triangle
           inline void box_intersect(const Box& a, const Box& b);
+          inline void process_intersecting_boxes();
         private:
           // Compute 2D delaunay triangulation of a given 3d triangle and a list of
           // intersection objects (points,segments,triangles). CGAL uses an affine
@@ -219,6 +224,8 @@ namespace igl
             SelfIntersectMesh * SIM, 
             const Box &a, 
             const Box &b);
+        private:
+          std::mutex m_offending_lock;
       };
     }
   }
@@ -330,20 +337,24 @@ inline igl::copyleft::cgal::SelfIntersectMesh<
   using namespace Eigen;
 
 #ifdef IGL_SELFINTERSECTMESH_DEBUG
-  const auto & tictoc = []()
+  const auto & tictoc = []() -> double
   {
     static double t_start = igl::get_seconds();
     double diff = igl::get_seconds()-t_start;
     t_start += diff;
     return diff;
   };
+  const auto log_time = [&](const std::string& label) -> void{
+    std::cout << "SelfIntersectMesh." << label << ": "
+      << tictoc() << std::endl;
+  };
   tictoc();
 #endif
 
   // Compute and process self intersections
   mesh_to_cgal_triangle_list(V,F,T);
 #ifdef IGL_SELFINTERSECTMESH_DEBUG
-  cout<<"mesh_to_cgal_triangle_list: "<<tictoc()<<endl;
+  log_time("convert_to_triangle_list");
 #endif
   // http://www.cgal.org/Manual/latest/doc_html/cgal_manual/Box_intersection_d/Chapter_main.html#Section_63.5 
   // Create the corresponding vector of bounding boxes
@@ -367,7 +378,7 @@ inline igl::copyleft::cgal::SelfIntersectMesh<
       std::placeholders::_1,
       std::placeholders::_2);
 #ifdef IGL_SELFINTERSECTMESH_DEBUG
-  cout<<"boxes and bind: "<<tictoc()<<endl;
+  log_time("box_and_bind");
 #endif
   // Run the self intersection algorithm with all defaults
   try{
@@ -381,8 +392,9 @@ inline igl::copyleft::cgal::SelfIntersectMesh<
     }
     // Otherwise just fall through
   }
+  process_intersecting_boxes();
 #ifdef IGL_SELFINTERSECTMESH_DEBUG
-  cout<<"box_self_intersection_d: "<<tictoc()<<endl;
+  log_time("box_intersection_d");
 #endif
 
   // Convert lIF to Eigen matrix
@@ -403,7 +415,7 @@ inline igl::copyleft::cgal::SelfIntersectMesh<
     }
   }
 #ifdef IGL_SELFINTERSECTMESH_DEBUG
-  cout<<"IF: "<<tictoc()<<endl;
+  log_time("store_intersecting_face_pairs");
 #endif
 
   if(params.detect_only)
@@ -414,7 +426,7 @@ inline igl::copyleft::cgal::SelfIntersectMesh<
   remesh_intersections(V,F,T,offending,edge2faces,VV,FF,J,IM);
 
 #ifdef IGL_SELFINTERSECTMESH_DEBUG
-  cout<<"remesh intersection: "<<tictoc()<<endl;
+  log_time("remesh_intersection");
 #endif
 
   // Q: Does this give the same result as TETGEN?
@@ -455,8 +467,7 @@ inline void igl::copyleft::cgal::SelfIntersectMesh<
   if(offending.count(f) == 0)
   {
     // first time marking, initialize with new id and empty list
-    const Index id = offending.size();
-    offending[f] = {id,{}};
+    offending[f] = {};
     for(Index e = 0; e<3;e++)
     {
       // append face to edge's list
@@ -488,6 +499,7 @@ inline void igl::copyleft::cgal::SelfIntersectMesh<
   const Index fa,
   const Index fb)
 {
+  std::lock_guard<std::mutex> guard(m_offending_lock);
   mark_offensive(fa);
   mark_offensive(fb);
   this->count++;
@@ -531,8 +543,9 @@ inline bool igl::copyleft::cgal::SelfIntersectMesh<
   {
     // Construct intersection
     CGAL::Object result = CGAL::intersection(A,B);
-    offending[fa].second.push_back(result);
-    offending[fb].second.push_back(result);
+    std::lock_guard<std::mutex> guard(m_offending_lock);
+    offending[fa].push_back({fb, result});
+    offending[fb].push_back({fa, result});
   }
   return true;
 }
@@ -630,8 +643,9 @@ inline bool igl::copyleft::cgal::SelfIntersectMesh<
         A.vertex(va),
         *p));
       count_intersection(fa,fb);
-      offending[fa].second.push_back(seg);
-      offending[fb].second.push_back(seg);
+      std::lock_guard<std::mutex> guard(m_offending_lock);
+      offending[fa].push_back({fb, seg});
+      offending[fb].push_back({fa, seg});
       return true;
     }else if(CGAL::object_cast<Segment_3 >(&result))
     {
@@ -688,6 +702,8 @@ inline bool igl::copyleft::cgal::SelfIntersectMesh<
 {
   using namespace std;
 
+  {
+    std::lock_guard<std::mutex> guard(m_offending_lock);
   // must be co-planar
   if(
     A.supporting_plane() != B.supporting_plane() &&
@@ -695,6 +711,7 @@ inline bool igl::copyleft::cgal::SelfIntersectMesh<
   {
     return false;
   }
+  }
   // Since A and B are non-degenerate the intersection must be a polygon
   // (triangle). Either
   //   - the vertex of A (B) opposite the shared edge of lies on B (A), or
@@ -777,8 +794,9 @@ inline bool igl::copyleft::cgal::SelfIntersectMesh<
       } else
       {
         // Triangle object
-        offending[fa].second.push_back(result);
-        offending[fb].second.push_back(result);
+        std::lock_guard<std::mutex> guard(m_offending_lock);
+        offending[fa].push_back({fb, result});
+        offending[fb].push_back({fa, result});
         //cerr<<REDRUM("Coplanar at: "<<fa<<" & "<<fb<<" (double shared).")<<endl;
         return true;
       }
@@ -825,125 +843,129 @@ inline void igl::copyleft::cgal::SelfIntersectMesh<
   const Box& a, 
   const Box& b)
 {
-  using namespace std;
-  // Could we write this as a static function of:
-  //
-  // F.row(fa)
-  // F.row(fb)
-  // A
-  // B
-
-  // index in F and T
-  Index fa = a.handle()-T.begin();
-  Index fb = b.handle()-T.begin();
-  const Triangle_3 & A = *a.handle();
-  const Triangle_3 & B = *b.handle();
-  //// I'm not going to deal with degenerate triangles, though at some point we
-  //// should
-  //assert(!a.handle()->is_degenerate());
-  //assert(!b.handle()->is_degenerate());
-  // Number of combinatorially shared vertices
-  Index comb_shared_vertices = 0;
-  // Number of geometrically shared vertices (*not* including combinatorially
-  // shared)
-  Index geo_shared_vertices = 0;
-  // Keep track of shared vertex indices
-  std::vector<std::pair<Index,Index> > shared;
-  Index ea,eb;
-  for(ea=0;ea<3;ea++)
-  {
-    for(eb=0;eb<3;eb++)
-    {
-      if(F(fa,ea) == F(fb,eb))
+  candidate_box_pairs.push_back({a, b});
+}
+
+template <
+  typename Kernel,
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedVV,
+  typename DerivedFF,
+  typename DerivedIF,
+  typename DerivedJ,
+  typename DerivedIM>
+inline void igl::copyleft::cgal::SelfIntersectMesh<
+  Kernel,
+  DerivedV,
+  DerivedF,
+  DerivedVV,
+  DerivedFF,
+  DerivedIF,
+  DerivedJ,
+  DerivedIM>::process_intersecting_boxes()
+{
+  CGAL::Identity_transformation I;
+  std::vector<std::mutex> triangle_locks(T.size());
+  auto process_chunk = [&](size_t first, size_t last) -> void{
+    assert(last >= first);
+
+    for (size_t i=first; i<last; i++) {
+      const auto& box_pair = candidate_box_pairs[i];
+      const auto& a = box_pair.first;
+      const auto& b = box_pair.second;
+      Index fa = a.handle()-T.begin();
+      Index fb = b.handle()-T.begin();
+
+      std::lock_guard<std::mutex> guard_A(triangle_locks[fa]);
+      std::lock_guard<std::mutex> guard_B(triangle_locks[fb]);
+      const Triangle_3& A = *a.handle();
+      const Triangle_3& B = *b.handle();
+
+      // Number of combinatorially shared vertices
+      Index comb_shared_vertices = 0;
+      // Number of geometrically shared vertices (*not* including combinatorially
+      // shared)
+      Index geo_shared_vertices = 0;
+      // Keep track of shared vertex indices
+      std::vector<std::pair<Index,Index> > shared;
+      Index ea,eb;
+      for(ea=0;ea<3;ea++)
+      {
+        for(eb=0;eb<3;eb++)
+        {
+          if(F(fa,ea) == F(fb,eb))
+          {
+            comb_shared_vertices++;
+            shared.emplace_back(ea,eb);
+          }else if(A.vertex(ea) == B.vertex(eb))
+          {
+            geo_shared_vertices++;
+            shared.emplace_back(ea,eb);
+          }
+        }
+      }
+      const Index total_shared_vertices = comb_shared_vertices + geo_shared_vertices;
+
+      if(comb_shared_vertices== 3)
+      {
+        assert(shared.size() == 3);
+        //// Combinatorially duplicate face, these should be removed by preprocessing
+        //cerr<<REDRUM("Facets "<<fa<<" and "<<fb<<" are combinatorial duplicates")<<endl;
+        continue;
+      }
+      if(total_shared_vertices== 3)
+      {
+        assert(shared.size() == 3);
+        //// Geometrically duplicate face, these should be removed by preprocessing
+        //cerr<<REDRUM("Facets "<<fa<<" and "<<fb<<" are geometrical duplicates")<<endl;
+        continue;
+      }
+      if(total_shared_vertices == 2)
+      {
+        assert(shared.size() == 2);
+        // Q: What about coplanar?
+        //
+        // o    o
+        // |\  /|
+        // | \/ |
+        // | /\ |
+        // |/  \|
+        // o----o
+        double_shared_vertex(A,B,fa,fb,shared);
+        continue;
+      }
+      assert(total_shared_vertices<=1);
+      if(total_shared_vertices==1)
       {
-        comb_shared_vertices++;
-        shared.emplace_back(ea,eb);
-      }else if(A.vertex(ea) == B.vertex(eb))
+        single_shared_vertex(A,B,fa,fb,shared[0].first,shared[0].second);
+      }else
       {
-        geo_shared_vertices++;
-        shared.emplace_back(ea,eb);
+        intersect(*a.handle(),*b.handle(),fa,fb);
       }
     }
+  };
+  size_t num_threads=0;
+  const size_t hardware_limit = std::thread::hardware_concurrency();
+  if (const char* igl_num_threads = std::getenv("LIBIGL_NUM_THREADS")) {
+    num_threads = atoi(igl_num_threads);
   }
-  const Index total_shared_vertices = comb_shared_vertices + geo_shared_vertices;
-  if(comb_shared_vertices== 3)
-  {
-    assert(shared.size() == 3);
-    //// Combinatorially duplicate face, these should be removed by preprocessing
-    //cerr<<REDRUM("Facets "<<fa<<" and "<<fb<<" are combinatorial duplicates")<<endl;
-    goto done;
-  }
-  if(total_shared_vertices== 3)
-  {
-    assert(shared.size() == 3);
-    //// Geometrically duplicate face, these should be removed by preprocessing
-    //cerr<<REDRUM("Facets "<<fa<<" and "<<fb<<" are geometrical duplicates")<<endl;
-    goto done;
+  if (num_threads == 0 || num_threads > hardware_limit) {
+    num_threads = hardware_limit;
   }
-  //// SPECIAL CASES ARE BROKEN FOR COPLANAR TRIANGLES
-  //if(total_shared_vertices > 0)
-  //{
-  //  bool coplanar = 
-  //    CGAL::coplanar(A.vertex(0),A.vertex(1),A.vertex(2),B.vertex(0)) &&
-  //    CGAL::coplanar(A.vertex(0),A.vertex(1),A.vertex(2),B.vertex(1)) &&
-  //    CGAL::coplanar(A.vertex(0),A.vertex(1),A.vertex(2),B.vertex(2));
-  //  if(coplanar)
-  //  {
-  //    cerr<<MAGENTAGIN("Facets "<<fa<<" and "<<fb<<
-  //      " are coplanar and share vertices")<<endl;
-  //    goto full;
-  //  }
-  //}
-
-  if(total_shared_vertices == 2)
-  {
-    assert(shared.size() == 2);
-    // Q: What about coplanar?
-    //
-    // o    o
-    // |\  /|
-    // | \/ |
-    // | /\ |
-    // |/  \|
-    // o----o
-    double_shared_vertex(A,B,fa,fb,shared);
-
-    goto done;
+  assert(num_threads > 0);
+  const size_t num_pairs = candidate_box_pairs.size();
+  const size_t chunk_size = num_pairs / num_threads;
+  std::vector<std::thread> threads;
+  for (size_t i=0; i<num_threads-1; i++) {
+    threads.emplace_back(process_chunk, i*chunk_size, (i+1)*chunk_size);
   }
-  assert(total_shared_vertices<=1);
-  if(total_shared_vertices==1)
-  {
-//#ifndef NDEBUG
-//    CGAL::Object result =
-//#endif
-    single_shared_vertex(A,B,fa,fb,shared[0].first,shared[0].second);
-//#ifndef NDEBUG
-//    if(!CGAL::object_cast<Segment_3 >(&result))
-//    {
-//      const Point_3 * p = CGAL::object_cast<Point_3 >(&result);
-//      assert(p);
-//      for(int ea=0;ea<3;ea++)
-//      {
-//        for(int eb=0;eb<3;eb++)
-//        {
-//          if(F(fa,ea) == F(fb,eb))
-//          {
-//            assert(*p==A.vertex(ea));
-//            assert(*p==B.vertex(eb));
-//          }
-//        }
-//      }
-//    }
-//#endif
-  }else
-  {
-//full:
-    // No geometrically shared vertices, do general intersect
-    intersect(*a.handle(),*b.handle(),fa,fb);
+  // Do some work in the master thread.
+  process_chunk((num_threads-1)*chunk_size, num_pairs);
+  for (auto& t : threads) {
+    if (t.joinable()) t.join();
   }
-done:
-  return;
+  //process_chunk(0, candidate_box_pairs.size());
 }
 
 #endif
-

+ 7 - 1
include/igl/copyleft/cgal/assign_scalar.cpp

@@ -18,7 +18,13 @@ IGL_INLINE void igl::copyleft::cgal::assign_scalar(
   const typename CGAL::Epeck::FT & cgal,
   double & d)
 {
-  d = CGAL::to_double(cgal);
+  const auto interval = CGAL::to_interval(cgal);
+  d = interval.first;
+  do {
+      const double next = nextafter(d, interval.second);
+      if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break;
+      d = next;
+  } while (d < interval.second);
 }
 
 IGL_INLINE void igl::copyleft::cgal::assign_scalar(

+ 6 - 6
include/igl/copyleft/cgal/closest_facet.cpp

@@ -77,7 +77,7 @@ IGL_INLINE void igl::copyleft::cgal::closest_facet(
   Tree tree(triangles.begin(), triangles.end());
   tree.accelerate_distance_queries();
 
-  auto on_the_positive_side = [&](size_t fid, const Point_3& p) {
+  auto on_the_positive_side = [&](size_t fid, const Point_3& p) -> bool{
     const auto& f = F.row(fid).eval();
     Point_3 v0(V(f[0], 0), V(f[0], 1), V(f[0], 2));
     Point_3 v1(V(f[1], 0), V(f[1], 1), V(f[1], 2));
@@ -122,7 +122,7 @@ IGL_INLINE void igl::copyleft::cgal::closest_facet(
 
   enum ElementType { VERTEX, EDGE, FACE };
   auto determine_element_type = [&](const Point_3& p, const size_t fid,
-      size_t& element_index) {
+      size_t& element_index) -> ElementType {
     const auto& tri = triangles[fid];
     const Point_3 p0 = tri[0];
     const Point_3 p1 = tri[1];
@@ -143,7 +143,7 @@ IGL_INLINE void igl::copyleft::cgal::closest_facet(
       size_t query_idx,
       const size_t s, const size_t d,
       size_t preferred_facet,
-      bool& orientation) {
+      bool& orientation) -> size_t {
     Point_3 query_point(
         P(query_idx, 0),
         P(query_idx, 1),
@@ -221,7 +221,7 @@ IGL_INLINE void igl::copyleft::cgal::closest_facet(
 
   auto process_face_case = [&](
       const size_t query_idx, const Point_3& closest_point,
-      const size_t fid, bool& orientation) {
+      const size_t fid, bool& orientation) -> size_t {
     const auto& f = F.row(I(fid, 0));
     return process_edge_case(query_idx, f[0], f[1], I(fid, 0), orientation);
   };
@@ -244,7 +244,7 @@ IGL_INLINE void igl::copyleft::cgal::closest_facet(
     const size_t query_idx, 
     size_t s,
     size_t preferred_facet, 
-    bool& orientation) 
+    bool& orientation) -> size_t
   {
     const Point_3 query_point(
         P(query_idx, 0), P(query_idx, 1), P(query_idx, 2));
@@ -296,7 +296,7 @@ IGL_INLINE void igl::copyleft::cgal::closest_facet(
 
     // A plane is on the exterior if all adj_points lies on or to
     // one side of the plane.
-    auto is_on_exterior = [&](const Plane_3& separator) {
+    auto is_on_exterior = [&](const Plane_3& separator) -> bool{
       size_t positive=0;
       size_t negative=0;
       size_t coplanar=0;

+ 18 - 9
include/igl/copyleft/cgal/extract_cells.cpp

@@ -42,7 +42,8 @@ IGL_INLINE size_t igl::copyleft::cgal::extract_cells_single_component(
     auto edge_index_to_face_index = [&](size_t index) {
         return index % num_faces;
     };
-    auto is_consistent = [&](const size_t fid, const size_t s, const size_t d) {
+    auto is_consistent = [&](const size_t fid, const size_t s, const size_t d)
+    -> bool{
         if ((size_t)F(fid, 0) == s && (size_t)F(fid, 1) == d) return false;
         if ((size_t)F(fid, 1) == s && (size_t)F(fid, 2) == d) return false;
         if ((size_t)F(fid, 2) == s && (size_t)F(fid, 0) == d) return false;
@@ -96,7 +97,7 @@ IGL_INLINE size_t igl::copyleft::cgal::extract_cells_single_component(
     auto peel_cell_bd = [&](
             size_t seed_patch_id,
             short seed_patch_side,
-            size_t cell_idx) {
+            size_t cell_idx) -> void {
         typedef std::pair<size_t, short> PatchSide;
         std::queue<PatchSide> Q;
         Q.emplace(seed_patch_id, seed_patch_side);
@@ -177,13 +178,17 @@ IGL_INLINE size_t igl::copyleft::cgal::extract_cells(
         const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
         Eigen::PlainObjectBase<DerivedC>& cells) {
 #ifdef EXTRACT_CELLS_DEBUG
-  const auto & tictoc = []()
+  const auto & tictoc = []() -> double
   {
     static double t_start = igl::get_seconds();
     double diff = igl::get_seconds()-t_start;
     t_start += diff;
     return diff;
   };
+  const auto log_time = [&](const std::string& label) -> void {
+    std::cout << "extract_cells." << label << ": "
+      << tictoc() << std::endl;
+  };
   tictoc();
 #endif
     const size_t num_faces = F.rows();
@@ -195,19 +200,19 @@ IGL_INLINE size_t igl::copyleft::cgal::extract_cells(
         igl::copyleft::cgal::extract_cells_single_component(
                 V, F, P, uE, uE2E, EMAP, raw_cells);
 #ifdef EXTRACT_CELLS_DEBUG
-    std::cout << "Extract single component cells: " << tictoc() << std::endl;
+    log_time("extract_single_component_cells");
 #endif
 
     std::vector<std::vector<std::vector<Index > > > TT,_1;
     igl::triangle_triangle_adjacency(E, EMAP, uE2E, false, TT, _1);
 #ifdef EXTRACT_CELLS_DEBUG
-    std::cout << "face adj: " << tictoc() << std::endl;
+    log_time("compute_face_adjacency");
 #endif
 
     Eigen::VectorXi C, counts;
     igl::facet_components(TT, C, counts);
 #ifdef EXTRACT_CELLS_DEBUG
-    std::cout << "face comp: " << tictoc() << std::endl;
+    log_time("form_components");
 #endif
 
     const size_t num_components = counts.size();
@@ -232,7 +237,7 @@ IGL_INLINE size_t igl::copyleft::cgal::extract_cells(
         outer_cells[i] = raw_cells(P[outer_facets[i]], outer_facet_orientation[i]);
     }
 #ifdef EXTRACT_CELLS_DEBUG
-    std::cout << "Per comp outer facet: " << tictoc() << std::endl;
+    log_time("outer_facet_per_component");
 #endif
 
     auto get_triangle_center = [&](const size_t fid) {
@@ -307,7 +312,7 @@ IGL_INLINE size_t igl::copyleft::cgal::extract_cells(
         }
     }
 #ifdef EXTRACT_CELLS_DEBUG
-    std::cout << "Determine nested relaitonship: " << tictoc() << std::endl;
+    log_time("nested_relationship");
 #endif
 
     const size_t INVALID = std::numeric_limits<size_t>::max();
@@ -348,6 +353,10 @@ IGL_INLINE size_t igl::copyleft::cgal::extract_cells(
 
     size_t count = 0;
     std::vector<size_t> mapped_indices(num_raw_cells+1, INVALID);
+    // Always map infinite cell to index 0.
+    mapped_indices[INFINITE_CELL] = count;
+    count++;
+
     for (size_t i=0; i<num_patches; i++) {
         const size_t old_positive_cell_id = raw_cells(i, 0);
         const size_t old_negative_cell_id = raw_cells(i, 1);
@@ -371,7 +380,7 @@ IGL_INLINE size_t igl::copyleft::cgal::extract_cells(
     }
     cells = raw_cells;
 #ifdef EXTRACT_CELLS_DEBUG
-    std::cout << "Finalize and output: " << tictoc() << std::endl;
+    log_time("finalize");
 #endif
     return count;
 }

+ 90 - 86
include/igl/copyleft/cgal/extract_cells.h

@@ -13,95 +13,99 @@
 #include <Eigen/Core>
 #include <vector>
 
-namespace igl
-{
+namespace igl {
   namespace copyleft
   {
-    namespace cgal
-    {
-      // Extract connected 3D space partitioned by mesh (V, F) could be many
-      // connected components.
-      //
-      // Inputs:
-      //   V  #V by 3 array of vertices.
-      //   F  #F by 3 array of face indices into V.
-      // Output:
-      //   cells  #F by 2 array of cell indices.  cells(i,0) represents the
-      //     cell index on the positive side of face i, and cells(i,1)
-      //     represents cell index of the negqtive side.
-      template<
-          typename DerivedV,
-          typename DerivedF,
-          typename DerivedC >
-      IGL_INLINE size_t extract_cells(
-              const Eigen::PlainObjectBase<DerivedV>& V,
-              const Eigen::PlainObjectBase<DerivedF>& F,
-              Eigen::PlainObjectBase<DerivedC>& cells);
+    namespace cgal {
+        // Extract connected 3D space partitioned by mesh (V, F).
+        //
+        // Inputs:
+        //   V  #V by 3 array of vertices.
+        //   F  #F by 3 array of faces.
+        //
+        // Output:
+        //   cells  #F by 2 array of cell indices.  cells(i,0) represents the
+        //          cell index on the positive side of face i, and cells(i,1)
+        //          represents cell index of the negqtive side.
+        //          By convension cell with index 0 is the infinite cell.
+        template<
+            typename DerivedV,
+            typename DerivedF,
+            typename DerivedC >
+        IGL_INLINE size_t extract_cells(
+                const Eigen::PlainObjectBase<DerivedV>& V,
+                const Eigen::PlainObjectBase<DerivedF>& F,
+                Eigen::PlainObjectBase<DerivedC>& cells);
+
+        // Extract connected 3D space partitioned by mesh (V, F).
+        //
+        // Inputs:
+        //   V  #V by 3 array of vertices.
+        //   F  #F by 3 array of faces.
+        //   P  #F list of patch indices.
+        //   E  #E by 2 array of vertex indices, one edge per row.
+        //  uE    #uE by 2 list of vertex_indices, represents undirected edges.
+        //  uE2E  #uE list of lists that maps uE to E. (a one-to-many map)
+        //  EMAP  #F*3 list of indices into uE.
+        //
+        // Output:
+        //   cells  #P by 2 array of cell indices.  cells(i,0) represents the
+        //          cell index on the positive side of patch i, and cells(i,1)
+        //          represents cell index of the negqtive side.
+        //          By convension cell with index 0 is the infinite cell.
+        template<
+            typename DerivedV,
+            typename DerivedF,
+            typename DerivedP,
+            typename DerivedE,
+            typename DeriveduE,
+            typename uE2EType,
+            typename DerivedEMAP,
+            typename DerivedC >
+        IGL_INLINE size_t extract_cells(
+                const Eigen::PlainObjectBase<DerivedV>& V,
+                const Eigen::PlainObjectBase<DerivedF>& F,
+                const Eigen::PlainObjectBase<DerivedP>& P,
+                const Eigen::PlainObjectBase<DerivedE>& E,
+                const Eigen::PlainObjectBase<DeriveduE>& uE,
+                const std::vector<std::vector<uE2EType> >& uE2E,
+                const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
+                Eigen::PlainObjectBase<DerivedC>& cells);
+
+        // Extract connected 3D space partitioned by mesh (V, F).  Each
+        // connected component of the mesh partitions the ambient space
+        // separately.
+        //
+        // Inputs:
+        //   V  #V by 3 array of vertices.
+        //   F  #F by 3 array of faces.
+        //   P  #F list of patch indices.
+        //   E  #E by 2 array of vertex indices, one edge per row.
+        //  uE    #uE by 2 list of vertex_indices, represents undirected edges.
+        //  uE2E  #uE list of lists that maps uE to E. (a one-to-many map)
+        //  EMAP  #F*3 list of indices into uE.
+        //
+        // Output:
+        //   cells  #P by 2 array of cell indices.  cells(i,0) represents the
+        //          cell index on the positive side of patch i, and cells(i,1)
+        //          represents cell index of the negqtive side.
+        template<
+            typename DerivedV,
+            typename DerivedF,
+            typename DerivedP,
+            typename DeriveduE,
+            typename uE2EType,
+            typename DerivedEMAP,
+            typename DerivedC >
+        IGL_INLINE size_t extract_cells_single_component(
+                const Eigen::PlainObjectBase<DerivedV>& V,
+                const Eigen::PlainObjectBase<DerivedF>& F,
+                const Eigen::PlainObjectBase<DerivedP>& P,
+                const Eigen::PlainObjectBase<DeriveduE>& uE,
+                const std::vector<std::vector<uE2EType> >& uE2E,
+                const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
+                Eigen::PlainObjectBase<DerivedC>& cells);
 
-      // Extract connected 3D space partitioned by mesh (V, F).
-      //
-      // Inputs:
-      //   V  #V by 3 array of vertices.
-      //   F  #F by 3 array of faces.
-      //   P  #F list of patch indices.
-      //   E  #E by 2 array of vertex indices, one edge per row.
-      //  uE  #uE by 2 list of vertex_indices, represents undirected edges.
-      //  uE2E  #uE list of lists that maps uE to E. (a one-to-many map)
-      //  EMAP  #F*3 list of indices into uE.
-      // Output:
-      //  cells  #P by 2 array of cell indices.  cells(i,0) represents the
-      //    cell index on the positive side of patch i, and cells(i,1)
-      //    represents cell index of the negqtive side.
-      template<
-        typename DerivedV,
-        typename DerivedF,
-        typename DerivedP,
-        typename DerivedE,
-        typename DeriveduE,
-        typename uE2EType,
-        typename DerivedEMAP,
-        typename DerivedC >
-      IGL_INLINE size_t extract_cells(
-        const Eigen::PlainObjectBase<DerivedV>& V,
-        const Eigen::PlainObjectBase<DerivedF>& F,
-        const Eigen::PlainObjectBase<DerivedP>& P,
-        const Eigen::PlainObjectBase<DerivedE>& E,
-        const Eigen::PlainObjectBase<DeriveduE>& uE,
-        const std::vector<std::vector<uE2EType> >& uE2E,
-        const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
-        Eigen::PlainObjectBase<DerivedC>& cells);
-      // Extract connected 3D space partitioned by mesh (V, F).  Each
-      // connected component of the mesh partitions the ambient space
-      // separately.
-      //
-      // Inputs:
-      //  V  #V by 3 array of vertices.
-      //  F  #F by 3 array of faces.
-      //  P  #F list of patch indices.
-      //  E  #E by 2 array of vertex indices, one edge per row.
-      //  uE  #uE by 2 list of vertex_indices, represents undirected edges.
-      //  uE2E  #uE list of lists that maps uE to E. (a one-to-many map)
-      //  EMAP  #F*3 list of indices into uE.
-      // Output:
-      //   cells  #P by 2 array of cell indices.  cells(i,0) represents the
-      //          cell index on the positive side of patch i, and cells(i,1)
-      //          represents cell index of the negqtive side.
-      template<
-        typename DerivedV,
-        typename DerivedF,
-        typename DerivedP,
-        typename DeriveduE,
-        typename uE2EType,
-        typename DerivedEMAP,
-        typename DerivedC >
-      IGL_INLINE size_t extract_cells_single_component(
-        const Eigen::PlainObjectBase<DerivedV>& V,
-        const Eigen::PlainObjectBase<DerivedF>& F,
-        const Eigen::PlainObjectBase<DerivedP>& P,
-        const Eigen::PlainObjectBase<DeriveduE>& uE,
-        const std::vector<std::vector<uE2EType> >& uE2E,
-        const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
-        Eigen::PlainObjectBase<DerivedC>& cells);
     }
   }
 }

+ 10 - 10
include/igl/copyleft/cgal/intersect_other.cpp

@@ -25,11 +25,12 @@ namespace igl
       static IGL_INLINE void push_result(
         const Eigen::PlainObjectBase<DerivedF> & F,
         const int f,
+        const int f_other,
         const CGAL::Object & result,
         std::map<
           typename DerivedF::Index,
-          std::pair<typename DerivedF::Index,
-            std::vector<CGAL::Object> > > & offending,
+          std::vector<std::pair<typename DerivedF::Index, CGAL::Object> > > &
+          offending,
         std::map<
           std::pair<typename DerivedF::Index,typename DerivedF::Index>,
           std::vector<typename DerivedF::Index> > & edge2faces)
@@ -39,8 +40,7 @@ namespace igl
         if(offending.count(f) == 0)
         {
           // first time marking, initialize with new id and empty list
-          Index id = offending.size();
-          offending[f] = {id,{}};
+          offending[f] = {};
           for(Index e = 0; e<3;e++)
           {
             // append face to edge's list
@@ -49,7 +49,7 @@ namespace igl
             edge2faces[EMK(i,j)].push_back(f);
           }
         }
-        offending[f].second.push_back(result);
+        offending[f].push_back({f_other,result});
       }
       template <
         typename Kernel,
@@ -113,7 +113,7 @@ namespace igl
           CGAL::Box_intersection_d::Box_with_handle_d<double,3,TrianglesIterator> 
           Box;
         typedef 
-          std::map<Index,std::pair<Index,std::vector<CGAL::Object> > > 
+          std::map<Index,std::vector<std::pair<Index,CGAL::Object> > > 
           OffendingMap;
         typedef std::map<std::pair<Index,Index>,std::vector<Index> >  EdgeMap;
         typedef std::pair<Index,Index> EMK;
@@ -125,7 +125,7 @@ namespace igl
         // http://www.cgal.org/Manual/latest/doc_html/cgal_manual/Box_intersection_d/Chapter_main.html#Section_63.5 
         // Create the corresponding vector of bounding boxes
         std::vector<Box> A_boxes,B_boxes;
-        const auto box_up = [](Triangles & T, std::vector<Box> & boxes)
+        const auto box_up = [](Triangles & T, std::vector<Box> & boxes) -> void
         {
           boxes.reserve(T.size());
           for ( 
@@ -142,7 +142,7 @@ namespace igl
         EdgeMap edge2facesA,edge2facesB;
 
         std::list<int> lIF;
-        const auto cb = [&](const Box &a, const Box &b)
+        const auto cb = [&](const Box &a, const Box &b) -> void
         {
           using namespace std;
           // index in F and T
@@ -163,8 +163,8 @@ namespace igl
             {
               CGAL::Object result = CGAL::intersection(A,B);
 
-              push_result(FA,fa,result,offendingA,edge2facesA);
-              push_result(FB,fb,result,offendingB,edge2facesB);
+              push_result(FA,fa,fb,result,offendingA,edge2facesA);
+              push_result(FB,fb,fa,result,offendingB,edge2facesB);
             }
           }
         };

+ 1 - 1
include/igl/copyleft/cgal/order_facets_around_edge.cpp

@@ -295,7 +295,7 @@ void igl::copyleft::cgal::order_facets_around_edge(
     {
         return abs(signed_idx) -1;
     };
-    auto get_opposite_vertex_index = [&](size_t fid)
+    auto get_opposite_vertex_index = [&](size_t fid) -> typename DerivedF::Scalar
     {
         typedef typename DerivedF::Scalar Index;
         if (F(fid, 0) != (Index)s && F(fid, 0) != (Index)d) return F(fid, 0);

+ 1 - 1
include/igl/copyleft/cgal/outer_element.cpp

@@ -131,7 +131,7 @@ IGL_INLINE void igl::copyleft::cgal::outer_edge(
     Index outer_opp_vid = INVALID;
     bool infinite_slope_detected = false;
     std::vector<Index> incident_faces;
-    auto check_and_update_outer_edge = [&](Index opp_vid, Index fid) {
+    auto check_and_update_outer_edge = [&](Index opp_vid, Index fid) -> void {
         if (opp_vid == outer_opp_vid)
         {
             incident_faces.push_back(fid);

+ 1 - 1
include/igl/copyleft/cgal/points_inside_component.cpp

@@ -169,7 +169,7 @@ namespace igl {
 
                 // A plane is on the exterior if all adj_points lies on or to
                 // one side of the plane.
-                auto is_on_exterior = [&](const Plane_3& separator) {
+                auto is_on_exterior = [&](const Plane_3& separator) -> bool{
                     size_t positive=0;
                     size_t negative=0;
                     size_t coplanar=0;

+ 13 - 12
include/igl/copyleft/cgal/propagate_winding_numbers.cpp

@@ -40,13 +40,17 @@ IGL_INLINE void igl::copyleft::cgal::propagate_winding_numbers(
     const Eigen::PlainObjectBase<DerivedL>& labels,
     Eigen::PlainObjectBase<DerivedW>& W) {
 #ifdef PROPAGATE_WINDING_NUMBER_TIMING
-  const auto & tictoc = []()
+  const auto & tictoc = []() -> double
   {
     static double t_start = igl::get_seconds();
     double diff = igl::get_seconds()-t_start;
     t_start += diff;
     return diff;
   };
+  const auto log_time = [&](const std::string& label) -> void {
+    std::cout << "propagate_winding_num." << label << ": "
+      << tictoc() << std::endl;
+  };
   tictoc();
 #endif
   const size_t num_faces = F.rows();
@@ -63,16 +67,13 @@ IGL_INLINE void igl::copyleft::cgal::propagate_winding_numbers(
 
   Eigen::VectorXi P;
   const size_t num_patches = igl::extract_manifold_patches(F, EMAP, uE2E, P);
-#ifdef PROPAGATE_WINDING_NUMBER_TIMING
-  std::cout << "extract manifold patches: " << tictoc() << std::endl;
-#endif
 
   DerivedW per_patch_cells;
   const size_t num_cells =
     igl::copyleft::cgal::extract_cells(
         V, F, P, E, uE, uE2E, EMAP, per_patch_cells);
 #ifdef PROPAGATE_WINDING_NUMBER_TIMING
-  std::cout << "extract cells: " << tictoc() << std::endl;;
+  log_time("cell_extraction");
 #endif
 
   typedef std::tuple<size_t, bool, size_t> CellConnection;
@@ -84,10 +85,10 @@ IGL_INLINE void igl::copyleft::cgal::propagate_winding_numbers(
     cell_adjacency[negative_cell].emplace(positive_cell, true, i);
   }
 #ifdef PROPAGATE_WINDING_NUMBER_TIMING
-  std::cout << "cell connection: " << tictoc() << std::endl;
+  log_time("cell_connectivity");
 #endif
 
-  auto save_cell = [&](const std::string& filename, size_t cell_id) {
+  auto save_cell = [&](const std::string& filename, size_t cell_id) -> void{
     std::vector<size_t> faces;
     for (size_t i=0; i<num_patches; i++) {
       if ((per_patch_cells.row(i).array() == cell_id).any()) {
@@ -118,7 +119,7 @@ IGL_INLINE void igl::copyleft::cgal::propagate_winding_numbers(
     cell_labels.setZero();
     Eigen::VectorXi parents(num_cells);
     parents.setConstant(-1);
-    auto trace_parents = [&](size_t idx) {
+    auto trace_parents = [&](size_t idx) -> std::list<size_t> {
       std::list<size_t> path;
       path.push_back(idx);
       while ((size_t)parents[path.back()] != path.back()) {
@@ -169,7 +170,7 @@ IGL_INLINE void igl::copyleft::cgal::propagate_winding_numbers(
       }
     }
 #ifdef PROPAGATE_WINDING_NUMBER_TIMING
-    std::cout << "check for odd cycle: " << tictoc() << std::endl;
+    log_time("odd_cycle_check");
 #endif
   }
 #endif
@@ -180,7 +181,7 @@ IGL_INLINE void igl::copyleft::cgal::propagate_winding_numbers(
   I.setLinSpaced(num_faces, 0, num_faces-1);
   igl::copyleft::cgal::outer_facet(V, F, I, outer_facet, flipped);
 #ifdef PROPAGATE_WINDING_NUMBER_TIMING
-  std::cout << "outer facet: " << tictoc() << std::endl;
+  log_time("outer_facet");
 #endif
 
   const size_t outer_patch = P[outer_facet];
@@ -244,7 +245,7 @@ IGL_INLINE void igl::copyleft::cgal::propagate_winding_numbers(
     }
   }
 #ifdef PROPAGATE_WINDING_NUMBER_TIMING
-  std::cout << "propagate winding number: " << tictoc() << std::endl;
+  log_time("propagate_winding_number");
 #endif
 
   W.resize(num_faces, num_labels*2);
@@ -258,7 +259,7 @@ IGL_INLINE void igl::copyleft::cgal::propagate_winding_numbers(
     }
   }
 #ifdef PROPAGATE_WINDING_NUMBER_TIMING
-  std::cout << "save result: " << tictoc() << std::endl;
+  log_time("store_result");
 #endif
 }
 

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 135 - 90
include/igl/copyleft/cgal/remesh_intersections.cpp


+ 2 - 2
include/igl/copyleft/cgal/remesh_intersections.h

@@ -53,8 +53,8 @@ namespace igl
         const std::vector<CGAL::Triangle_3<Kernel> > & T,
         const std::map<
           typename DerivedF::Index,
-          std::pair<typename DerivedF::Index,
-            std::vector<CGAL::Object> > > & offending,
+            std::vector<
+            std::pair<typename DerivedF::Index, CGAL::Object> > > & offending,
         const std::map<
           std::pair<typename DerivedF::Index,typename DerivedF::Index>,
           std::vector<typename DerivedF::Index> > & edge2faces,

+ 2 - 2
include/igl/copyleft/cgal/remesh_self_intersections.cpp

@@ -56,7 +56,7 @@ IGL_INLINE void igl::copyleft::cgal::remesh_self_intersections(
         DerivedJ,
         DerivedIM>
       SelfIntersectMeshK;
-    SelfIntersectMeshK SIM = SelfIntersectMeshK(V,F,params,VV,FF,IF,J,IM);
+    SelfIntersectMeshK SIM(V,F,params,VV,FF,IF,J,IM);
 
 //#ifdef __APPLE__
 //    signal(SIGFPE,SIG_DFL);
@@ -76,7 +76,7 @@ IGL_INLINE void igl::copyleft::cgal::remesh_self_intersections(
         DerivedJ,
         DerivedIM>
       SelfIntersectMeshK;
-    SelfIntersectMeshK SIM = SelfIntersectMeshK(V,F,params,VV,FF,IF,J,IM);
+    SelfIntersectMeshK SIM(V,F,params,VV,FF,IF,J,IM);
   }
 }
 

+ 1 - 1
include/igl/extract_manifold_patches.cpp

@@ -20,7 +20,7 @@ IGL_INLINE size_t igl::extract_manifold_patches(
     auto face_and_corner_index_to_edge_index = [&](size_t fi, size_t ci) {
         return ci*num_faces + fi;
     };
-    auto is_manifold_edge = [&](size_t fi, size_t ci) {
+    auto is_manifold_edge = [&](size_t fi, size_t ci) -> bool {
         const size_t ei = face_and_corner_index_to_edge_index(fi, ci);
         return uE2E[EMAP(ei, 0)].size() == 2;
     };

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels