Explorar o código

3 new trimming methods and tutorial (#2268) [ci skip]

* 3 new trimming methods and tutorial

* missing template

* rm warning

* add tests

* Windows templates
Alec Jacobson %!s(int64=2) %!d(string=hai) anos
pai
achega
d6448a86fb

+ 1 - 0
include/igl/barycenter.cpp

@@ -34,6 +34,7 @@ IGL_INLINE void igl::barycenter(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
 // generated by autoexplicit.sh
+// generated by autoexplicit.sh
 template void igl::barycenter<Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<double, -1, 2, 0, -1, 2> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&);
 // generated by autoexplicit.sh
 template void igl::barycenter<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);

+ 50 - 7
include/igl/copyleft/cgal/assign.cpp

@@ -8,6 +8,40 @@
 #include "assign.h"
 #include "../../parallel_for.h"
 #include "assign_scalar.h"
+#include <type_traits>
+
+namespace igl { namespace copyleft { namespace cgal {
+  // Would be simpler with C++17 `if constexpr`
+  template <bool Simple> struct assign_Helper { };
+  template <> struct assign_Helper<false>
+  {
+    template <typename DerivedC, typename DerivedD>
+    static void run(
+      const Eigen::MatrixBase<DerivedC> & C,
+      const bool slow_and_more_precise,
+      Eigen::PlainObjectBase<DerivedD> & D)
+    {
+      D.resizeLike(C);
+      igl::parallel_for(C.size(),[&](Eigen::Index k)
+      {
+        const Eigen::Index i = k%C.rows();
+        const Eigen::Index j = k/C.rows();
+        assign_scalar(C(i,j),slow_and_more_precise,D(i,j));
+      },1000);
+    }
+  };
+  template <> struct assign_Helper<true>
+  {
+    template <typename DerivedC, typename DerivedD>
+    static void run(
+      const Eigen::MatrixBase<DerivedC> & C,
+      const bool /*slow_and_more_precise*/,
+      Eigen::PlainObjectBase<DerivedD> & D)
+    {
+      D = C.template cast<typename DerivedD::Scalar>();
+    }
+  };
+} } }
 
 template <typename DerivedC, typename DerivedD>
 IGL_INLINE void igl::copyleft::cgal::assign(
@@ -15,13 +49,10 @@ IGL_INLINE void igl::copyleft::cgal::assign(
   const bool slow_and_more_precise,
   Eigen::PlainObjectBase<DerivedD> & D)
 {
-  D.resizeLike(C);
-  igl::parallel_for(C.size(),[&](Eigen::Index k)
-  {
-    const Eigen::Index i = k%C.rows();
-    const Eigen::Index j = k/C.rows();
-    assign_scalar(C(i,j),slow_and_more_precise,D(i,j));
-  },1000);
+  using CScalar = typename DerivedC::Scalar;
+  using DScalar = typename DerivedD::Scalar;
+  constexpr bool simple = std::is_assignable<DScalar,CScalar>::value;
+  assign_Helper<simple>::run(C,slow_and_more_precise,D);
 }
 template <typename DerivedC, typename DerivedD>
 IGL_INLINE void igl::copyleft::cgal::assign(
@@ -57,6 +88,18 @@ igl::copyleft::cgal::assign(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
+// generated by autoexplicit.sh
+template void igl::copyleft::cgal::assign<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+// generated by autoexplicit.sh
+template void igl::copyleft::cgal::assign<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 1, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 1, -1, -1> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+// generated by autoexplicit.sh
+template void igl::copyleft::cgal::assign<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+// generated by autoexplicit.sh
+template void igl::copyleft::cgal::assign<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+// generated by autoexplicit.sh
+template void igl::copyleft::cgal::assign<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 1, -1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 1, -1, 3> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+// generated by autoexplicit.sh
+template void igl::copyleft::cgal::assign<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 template void igl::copyleft::cgal::assign<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1>, Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3> >&);
 template void igl::copyleft::cgal::assign<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 template void igl::copyleft::cgal::assign<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);

+ 1 - 0
include/igl/copyleft/cgal/barycenter.cpp

@@ -13,4 +13,5 @@
 #include "../../barycenter.cpp"
 // Explicit template instantiation
 template void igl::barycenter<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1> >&);
+template void igl::barycenter<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3> >&);
 #endif

+ 3 - 13
include/igl/copyleft/cgal/mesh_boolean.cpp

@@ -213,22 +213,12 @@ IGL_INLINE bool igl::copyleft::cgal::mesh_boolean(
   DerivedFC F;
   VectorXJ  CJ;
   {
-    Eigen::VectorXi I;
     igl::copyleft::cgal::RemeshSelfIntersectionsParam params;
     params.stitch_all = true;
-    MatrixXES Vr;
-    DerivedFC Fr;
     Eigen::MatrixXi IF;
-    igl::copyleft::cgal::remesh_self_intersections(
-        VV, FF, params, Vr, Fr, IF, CJ, I);
-    assert(I.size() == Vr.rows());
-    // Merge coinciding vertices into non-manifold vertices.
-    std::for_each(Fr.data(), Fr.data()+Fr.size(),
-          [&I](typename DerivedFC::Scalar& a) { a=I[a]; });
-      // Remove unreferenced vertices.
-      Eigen::VectorXi UIM;
-      igl::remove_unreferenced(Vr, Fr, V, F, UIM);
-   }
+    remesh_self_intersections(VV,FF,params,V,F,IF,CJ);
+  }
+  
 #ifdef MESH_BOOLEAN_TIMING
   log_time("resolve_self_intersection");
 #endif

+ 4 - 2
include/igl/copyleft/cgal/point_mesh_squared_distance.cpp

@@ -8,6 +8,7 @@
 #include "point_mesh_squared_distance.h"
 #include "mesh_to_cgal_triangle_list.h"
 #include "assign_scalar.h"
+#include "../../parallel_for.h"
 
 template <
   typename Kernel,
@@ -112,7 +113,8 @@ IGL_INLINE void igl::copyleft::cgal::point_mesh_squared_distance(
   sqrD.resize(n,1);
   I.resize(n,1);
   C.resize(n,P.cols());
-  for(int p = 0;p < n;p++)
+  //for(int p = 0;p < n;p++)
+  igl::parallel_for(n,[&](const int p)
   {
     Point_3 query(P(p,0),P(p,1),P(p,2));
     // Find closest point and primitive id
@@ -123,7 +125,7 @@ IGL_INLINE void igl::copyleft::cgal::point_mesh_squared_distance(
     assign_scalar(closest_point[2],C(p,2));
     assign_scalar((closest_point-query).squared_length(),sqrD(p));
     I(p) = pp.second - T.begin();
-  }
+  },1000);
 }
 
 #ifdef IGL_STATIC_LIBRARY

+ 2 - 0
include/igl/copyleft/cgal/point_solid_signed_squared_distance.cpp

@@ -8,8 +8,10 @@
 #include "point_solid_signed_squared_distance.h"
 #include "points_inside_component.h"
 #include "point_mesh_squared_distance.h"
+#include "../../get_seconds.h"
 #include "../../list_to_matrix.h"
 #include "../../find.h"
+#include "../../parallel_for.h"
 #include <vector>
 #include <Eigen/Core>
 

+ 4 - 2
include/igl/copyleft/cgal/points_inside_component.cpp

@@ -7,6 +7,7 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "points_inside_component.h"
 #include "../../LinSpaced.h"
+#include "../../parallel_for.h"
 #include "order_facets_around_edge.h"
 #include "assign_scalar.h"
 
@@ -292,7 +293,8 @@ IGL_INLINE void igl::copyleft::cgal::points_inside_component(
 
     const size_t num_queries = P.rows();
     inside.resize(num_queries, 1);
-    for (size_t i=0; i<num_queries; i++) {
+    //for (size_t i=0; i<num_queries; i++) {
+    igl::parallel_for(num_queries, [&](const int i) {
         const Point_3 query(P(i,0), P(i,1), P(i,2));
         auto projection = tree.closest_point_and_primitive(query);
         auto closest_point = projection.first;
@@ -321,7 +323,7 @@ IGL_INLINE void igl::copyleft::cgal::points_inside_component(
             default:
                 throw "Unknown closest element type!";
         }
-    }
+    }, 1000);
 }
 
 template<typename DerivedV, typename DerivedF, typename DerivedP,

+ 14 - 0
include/igl/copyleft/cgal/remesh_intersections.cpp

@@ -508,6 +508,17 @@ IGL_INLINE void igl::copyleft::cgal::remesh_intersections(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
+// generated by autoexplicit.sh
+template void igl::copyleft::cgal::remesh_intersections<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epick, Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > > const&, std::map<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, CGAL::Object>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, CGAL::Object> > >, std::less<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index const, std::vector<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, CGAL::Object>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, CGAL::Object> > > > > > const&, bool, bool, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+// generated by autoexplicit.sh
+template void igl::copyleft::cgal::remesh_intersections<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epeck, Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epeck>, std::allocator<CGAL::Triangle_3<CGAL::Epeck> > > const&, std::map<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, CGAL::Object>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, CGAL::Object> > >, std::less<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index const, std::vector<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, CGAL::Object>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, CGAL::Object> > > > > > const&, bool, bool, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+// generated by autoexplicit.sh
+template void igl::copyleft::cgal::remesh_intersections<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epeck, Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epeck>, std::allocator<CGAL::Triangle_3<CGAL::Epeck> > > const&, std::map<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, CGAL::Object>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, CGAL::Object> > >, std::less<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index const, std::vector<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, CGAL::Object>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, CGAL::Object> > > > > > const&, bool, bool, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+// generated by autoexplicit.sh
+template void igl::copyleft::cgal::remesh_intersections<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epeck, Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epeck>, std::allocator<CGAL::Triangle_3<CGAL::Epeck> > > const&, std::map<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, CGAL::Object>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, CGAL::Object> > >, std::less<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index const, std::vector<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, CGAL::Object>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, CGAL::Object> > > > > > const&, bool, bool, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+// generated by autoexplicit.sh
+template void igl::copyleft::cgal::remesh_intersections<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epeck, Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 1, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<CGAL::Triangle_3<CGAL::Epeck>, std::allocator<CGAL::Triangle_3<CGAL::Epeck> > > const&, std::map<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, std::vector<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, CGAL::Object>, std::allocator<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, CGAL::Object> > >, std::less<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index>, std::allocator<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index const, std::vector<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, CGAL::Object>, std::allocator<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, CGAL::Object> > > > > > const&, bool, bool, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 1, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+// Alec
 template void igl::copyleft::cgal::remesh_intersections<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epick, Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > > const&, std::map<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, std::vector<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, CGAL::Object>, std::allocator<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, CGAL::Object> > >, std::less<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index>, std::allocator<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index const, std::vector<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, CGAL::Object>, std::allocator<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, CGAL::Object> > > > > > const&, bool, bool, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::copyleft::cgal::remesh_intersections<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epick, Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > > const&, std::map<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, CGAL::Object>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, CGAL::Object> > >, std::less<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index const, std::vector<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, CGAL::Object>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, CGAL::Object> > > > > > const&, bool, bool, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 1, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 // generated by autoexplicit.sh
@@ -546,6 +557,9 @@ template void igl::copyleft::cgal::remesh_intersections<Eigen::Matrix<double, -1
 template void igl::copyleft::cgal::remesh_intersections<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epick, Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > > const&, std::map<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, std::vector<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, CGAL::Object>, std::allocator<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, CGAL::Object> > >, std::less<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index>, std::allocator<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index const, std::vector<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, CGAL::Object>, std::allocator<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, CGAL::Object> > > > > > const&, bool, bool, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::copyleft::cgal::remesh_intersections<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epick, Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<std::ptrdiff_t, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > > const&, std::map<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, std::vector<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, CGAL::Object>, std::allocator<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, CGAL::Object> > >, std::less<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index>, std::allocator<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index const, std::vector<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, CGAL::Object>, std::allocator<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, CGAL::Object> > > > > > const&, bool, bool, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<std::ptrdiff_t, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 #ifdef WIN32
+template void igl::copyleft::cgal::remesh_intersections<Eigen::Matrix<CGAL::Epeck::FT,-1,3,0,-1,3>,Eigen::Matrix<int,-1,3,0,-1,3>,CGAL::Epick,Eigen::Matrix<CGAL::Epeck::FT,-1,3,0,-1,3>,Eigen::Matrix<int,-1,-1,0,-1,-1>,Eigen::Matrix<int,-1,1,0,-1,1>,Eigen::Matrix<int,-1,1,0,-1,1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT,-1,3,0,-1,3> >const &,Eigen::MatrixBase<Eigen::Matrix<int,-1,3,0,-1,3> > const &,std::vector<CGAL::Triangle_3<CGAL::Epick>,std::allocator<CGAL::Triangle_3<CGAL::Epick>> > const &,std::map<__int64,std::vector<struct std::pair<__int64,CGAL::Object>,std::allocator<struct std::pair<__int64,CGAL::Object> > >,struct std::less<__int64>,std::allocator<struct std::pair<__int64 const ,std::vector<struct std::pair<__int64,CGAL::Object>,std::allocator<struct std::pair<__int64,CGAL::Object> > > > > > const &,bool,bool,Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT,-1,3,0,-1,3> > &,Eigen::PlainObjectBase<Eigen::Matrix<int,-1,-1,0,-1,-1> > &,Eigen::PlainObjectBase<Eigen::Matrix<int,-1,1,0,-1,1> > &,Eigen::PlainObjectBase<Eigen::Matrix<int,-1,1,0,-1,1> > &);
+template void igl::copyleft::cgal::remesh_intersections<Eigen::Matrix<CGAL::Epeck::FT,-1,3,0,-1,3>,Eigen::Matrix<int,-1,3,0,-1,3>,CGAL::Epick,Eigen::Matrix<CGAL::Epeck::FT,-1,3,1,-1,3>,Eigen::Matrix<int,-1,-1,0,-1,-1>,Eigen::Matrix<int,-1,1,0,-1,1>,Eigen::Matrix<int,-1,1,0,-1,1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT,-1,3,0,-1,3> >const &,Eigen::MatrixBase<Eigen::Matrix<int,-1,3,0,-1,3> > const &,std::vector<CGAL::Triangle_3<CGAL::Epick>,std::allocator<CGAL::Triangle_3<CGAL::Epick>> > const &,std::map<__int64,std::vector<struct std::pair<__int64,CGAL::Object>,std::allocator<struct std::pair<__int64,CGAL::Object> > >,struct std::less<__int64>,std::allocator<struct std::pair<__int64 const ,std::vector<struct std::pair<__int64,CGAL::Object>,std::allocator<struct std::pair<__int64,CGAL::Object> > > > > > const &,bool,bool,Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT,-1,3,1,-1,3> > &,Eigen::PlainObjectBase<Eigen::Matrix<int,-1,-1,0,-1,-1> > &,Eigen::PlainObjectBase<Eigen::Matrix<int,-1,1,0,-1,1> > &,Eigen::PlainObjectBase<Eigen::Matrix<int,-1,1,0,-1,1> > &);
+template void igl::copyleft::cgal::remesh_intersections<Eigen::Matrix<CGAL::Epeck::FT,-1,-1,1,-1,-1>,Eigen::Matrix<int,-1,-1,0,-1,-1>,CGAL::Epick,Eigen::Matrix<CGAL::Epeck::FT,-1,-1,1,-1,-1>,Eigen::Matrix<int,-1,-1,0,-1,-1>,Eigen::Matrix<int,-1,1,0,-1,1>,Eigen::Matrix<int,-1,1,0,-1,1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT,-1,-1,1,-1,-1> > const &,Eigen::MatrixBase<Eigen::Matrix<int,-1,-1,0,-1,-1> > const &,std::vector<CGAL::Triangle_3<CGAL::Epick>,std::allocator<CGAL::Triangle_3<CGAL::Epick>> > const &,std::map<__int64,std::vector<struct std::pair<__int64,CGAL::Object>,std::allocator<struct std::pair<__int64,CGAL::Object> > >,struct std::less<__int64>,std::allocator<struct std::pair<__int64 const ,std::vector<struct std::pair<__int64,CGAL::Object>,std::allocator<struct std::pair<__int64,CGAL::Object> > > > > > const &,bool,bool,Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT,-1,-1,1,-1,-1> > &,Eigen::PlainObjectBase<Eigen::Matrix<int,-1,-1,0,-1,-1> > &,Eigen::PlainObjectBase<Eigen::Matrix<int,-1,1,0,-1,1> > &,Eigen::PlainObjectBase<Eigen::Matrix<int,-1,1,0,-1,1> > &);
 template void igl::copyleft::cgal::remesh_intersections<Eigen::Matrix<CGAL::Epeck::FT,-1,3,0,-1,3>,Eigen::Matrix<int,-1,-1,0,-1,-1>,CGAL::Epick,Eigen::Matrix<CGAL::Epeck::FT,-1,3,0,-1,3>,Eigen::Matrix<int,-1,-1,0,-1,-1>,Eigen::Matrix<int,-1,1,0,-1,1>,Eigen::Matrix<int,-1,1,0,-1,1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT,-1,3,0,-1,3> > const &,Eigen::MatrixBase<Eigen::Matrix<int,-1,-1,0,-1,-1> > const &,std::vector<CGAL::Triangle_3<CGAL::Epick>,std::allocator<CGAL::Triangle_3<CGAL::Epick> > > const &,std::map<__int64,std::vector<struct std::pair<__int64,CGAL::Object>,std::allocator<struct std::pair<__int64,CGAL::Object> > >,struct std::less<__int64>,std::allocator<struct std::pair<__int64 const ,std::vector<struct std::pair<__int64,CGAL::Object>,std::allocator<struct std::pair<__int64,CGAL::Object> > > > > > const &,bool,bool,Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT,-1,3,0,-1,3> > &,Eigen::PlainObjectBase<Eigen::Matrix<int,-1,-1,0,-1,-1> > &,Eigen::PlainObjectBase<Eigen::Matrix<int,-1,1,0,-1,1> > &,Eigen::PlainObjectBase<Eigen::Matrix<int,-1,1,0,-1,1> > &);
 template void igl::copyleft::cgal::remesh_intersections<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epick, Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3> > const &, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const &, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > > const &, std::map<__int64, std::vector<struct std::pair<__int64, CGAL::Object>, std::allocator<struct std::pair<__int64, CGAL::Object> > >, struct std::less<__int64>, std::allocator<struct std::pair<__int64 const , std::vector<struct std::pair<__int64, CGAL::Object>, std::allocator<struct std::pair<__int64, CGAL::Object> > > > > > const &, bool, bool, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 1, -1, -1> > &, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > &, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > &, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > &);
 #endif

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

@@ -7,7 +7,9 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "remesh_self_intersections.h"
 #include "SelfIntersectMesh.h"
+#include "assign_scalar.h"
 #include "../../C_STR.h"
+#include "../../remove_unreferenced.h"
 #include <list>
 #include <iostream>
 
@@ -81,9 +83,65 @@ IGL_INLINE void igl::copyleft::cgal::remesh_self_intersections(
   }
 }
 
+template <
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedVV,
+  typename DerivedFF,
+  typename DerivedIF,
+  typename DerivedJ>
+IGL_INLINE void igl::copyleft::cgal::remesh_self_intersections(
+  const Eigen::MatrixBase<DerivedV> & V,
+  const Eigen::MatrixBase<DerivedF> & F,
+  const RemeshSelfIntersectionsParam & params,
+  Eigen::PlainObjectBase<DerivedVV> & VV,
+  Eigen::PlainObjectBase<DerivedFF> & FF,
+  Eigen::PlainObjectBase<DerivedIF> & IF,
+  Eigen::PlainObjectBase<DerivedJ> & J)
+{
+  assert(!params.detect_only && "detect_only must be false");
+  assert(params.stitch_all   && "stitch_all must be true (I think)");
+  {
+    using FFScalar = typename DerivedFF::Scalar;
+    // enforced by assertion: params.stitch_all = true; 
+    Eigen::Matrix<CGAL::Epeck::FT,Eigen::Dynamic,3,DerivedVV::IsRowMajor> Vr;
+    {
+      Eigen::VectorXi I;
+      igl::copyleft::cgal::remesh_self_intersections(
+          V, F, params, Vr, FF, IF, J, I);
+      assert(I.size() == Vr.rows());
+      // Merge coinciding vertices into non-manifold vertices.
+      std::for_each(FF.data(),FF.data()+FF.size(),[&I](FFScalar& a){a=I[a];});
+    }
+    // Remove unreferenced vertices and assign to output
+    {
+      Eigen::VectorXi ruI,ruJ;
+      igl::remove_unreferenced(Vr.rows(), FF, ruI, ruJ);
+      std::for_each(
+        FF.data(),FF.data()+FF.size(),[&ruI](FFScalar& a){a=ruI(a);});
+      VV.resize(ruJ.size(),3);
+      for(int i = 0;i<ruJ.size();i++)
+      {
+        for(int j = 0;j<3;j++)
+        {
+          assign_scalar(Vr(ruJ(i),j),params.slow_and_more_precise_rounding,VV(i,j));
+        }
+      }
+    }
+  }
+}
+
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
 // generated by autoexplicit.sh
+template void igl::copyleft::cgal::remesh_self_intersections<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, igl::copyleft::cgal::RemeshSelfIntersectionsParam const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+// generated by autoexplicit.sh
+template void igl::copyleft::cgal::remesh_self_intersections<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, igl::copyleft::cgal::RemeshSelfIntersectionsParam const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+// generated by autoexplicit.sh
+template void igl::copyleft::cgal::remesh_self_intersections<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, igl::copyleft::cgal::RemeshSelfIntersectionsParam const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 1, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+// generated by autoexplicit.sh
+template void igl::copyleft::cgal::remesh_self_intersections<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, igl::copyleft::cgal::RemeshSelfIntersectionsParam const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+// generated by autoexplicit.sh
 template void igl::copyleft::cgal::remesh_self_intersections<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, igl::copyleft::cgal::RemeshSelfIntersectionsParam const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 1, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 // generated by autoexplicit.sh
 template void igl::copyleft::cgal::remesh_self_intersections<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, igl::copyleft::cgal::RemeshSelfIntersectionsParam const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
@@ -99,6 +157,4 @@ template void igl::copyleft::cgal::remesh_self_intersections<Eigen::Matrix<doubl
 template void igl::copyleft::cgal::remesh_self_intersections<Eigen::Matrix<double,-1,3,0,-1,3>,Eigen::Matrix<int,-1,-1,0,-1,-1>,Eigen::Matrix<CGAL::Epeck::FT,-1,-1,0,-1,-1>,Eigen::Matrix<int,-1,-1,0,-1,-1>,Eigen::Matrix<int,-1,-1,0,-1,-1>,Eigen::Matrix<std::ptrdiff_t,-1,1,0,-1,1>,Eigen::Matrix<int,-1,1,0,-1,1> >(Eigen::MatrixBase<Eigen::Matrix<double,-1,3,0,-1,3> > const&,Eigen::MatrixBase<Eigen::Matrix<int,-1,-1,0,-1,-1> > const&,igl::copyleft::cgal::RemeshSelfIntersectionsParam const&,Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT,-1,-1,0,-1,-1> >&,Eigen::PlainObjectBase<Eigen::Matrix<int,-1,-1,0,-1,-1> >&,Eigen::PlainObjectBase<Eigen::Matrix<int,-1,-1,0,-1,-1> >&,Eigen::PlainObjectBase<Eigen::Matrix<std::ptrdiff_t,-1,1,0,-1,1> >&,Eigen::PlainObjectBase<Eigen::Matrix<int,-1,1,0,-1,1> >&);
 template void igl::copyleft::cgal::remesh_self_intersections<Eigen::Matrix<double,-1,-1,1,-1,-1>,Eigen::Matrix<int,-1,-1,0,-1,-1>,Eigen::Matrix<CGAL::Epeck::FT,-1,-1,0,-1,-1>,Eigen::Matrix<int,-1,-1,0,-1,-1>,Eigen::Matrix<int,-1,-1,0,-1,-1>,Eigen::Matrix<int,-1,1,0,-1,1>,Eigen::Matrix<int,-1,1,0,-1,1> >(Eigen::MatrixBase<Eigen::Matrix<double,-1,-1,1,-1,-1> > const&,Eigen::MatrixBase<Eigen::Matrix<int,-1,-1,0,-1,-1> > const&,igl::copyleft::cgal::RemeshSelfIntersectionsParam const&,Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT,-1,-1,0,-1,-1> >&,Eigen::PlainObjectBase<Eigen::Matrix<int,-1,-1,0,-1,-1> >&,Eigen::PlainObjectBase<Eigen::Matrix<int,-1,-1,0,-1,-1> >&,Eigen::PlainObjectBase<Eigen::Matrix<int,-1,1,0,-1,1> >&,Eigen::PlainObjectBase<Eigen::Matrix<int,-1,1,0,-1,1> >&);
 template void igl::copyleft::cgal::remesh_self_intersections<Eigen::Matrix<double,-1,-1,0,-1,-1>,Eigen::Matrix<int,-1,-1,0,-1,-1>,Eigen::Matrix<CGAL::Epeck::FT,-1,-1,0,-1,-1>,Eigen::Matrix<int,-1,-1,0,-1,-1>,Eigen::Matrix<int,-1,-1,0,-1,-1>,Eigen::Matrix<int,-1,1,0,-1,1>,Eigen::Matrix<int,-1,1,0,-1,1> >(Eigen::MatrixBase<Eigen::Matrix<double,-1,-1,0,-1,-1> > const&,Eigen::MatrixBase<Eigen::Matrix<int,-1,-1,0,-1,-1> > const&,igl::copyleft::cgal::RemeshSelfIntersectionsParam const&,Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT,-1,-1,0,-1,-1> >&,Eigen::PlainObjectBase<Eigen::Matrix<int,-1,-1,0,-1,-1> >&,Eigen::PlainObjectBase<Eigen::Matrix<int,-1,-1,0,-1,-1> >&,Eigen::PlainObjectBase<Eigen::Matrix<int,-1,1,0,-1,1> >&,Eigen::PlainObjectBase<Eigen::Matrix<int,-1,1,0,-1,1> >&);
-#ifdef WIN32
-#endif
 #endif

+ 18 - 0
include/igl/copyleft/cgal/remesh_self_intersections.h

@@ -68,6 +68,24 @@ namespace igl
         Eigen::PlainObjectBase<DerivedIF> & IF,
         Eigen::PlainObjectBase<DerivedJ> & J,
         Eigen::PlainObjectBase<DerivedIM> & IM);
+      /// \overload
+      ///
+      /// IM above is _applied_ to merge duplicated vertices in VV.
+      template <
+        typename DerivedV,
+        typename DerivedF,
+        typename DerivedVV,
+        typename DerivedFF,
+        typename DerivedIF,
+        typename DerivedJ>
+      IGL_INLINE void remesh_self_intersections(
+        const Eigen::MatrixBase<DerivedV> & V,
+        const Eigen::MatrixBase<DerivedF> & F,
+        const RemeshSelfIntersectionsParam & params,
+        Eigen::PlainObjectBase<DerivedVV> & VV,
+        Eigen::PlainObjectBase<DerivedFF> & FF,
+        Eigen::PlainObjectBase<DerivedIF> & IF,
+        Eigen::PlainObjectBase<DerivedJ> & J);
     }
   }
 }

+ 246 - 41
include/igl/copyleft/cgal/trim_with_solid.cpp

@@ -8,11 +8,16 @@
 #include "trim_with_solid.h"
 #include "assign.h"
 #include "intersect_other.h"
+#include "remesh_self_intersections.h"
 #include "point_solid_signed_squared_distance.h"
 
 #include "../../extract_manifold_patches.h"
+#include "../../connected_components.h"
+#include "../../facet_adjacency_matrix.h"
 #include "../../list_to_matrix.h"
 #include "../../find.h"
+#include "../../get_seconds.h"
+#include "../../barycenter.h"
 #include "../../remove_unreferenced.h"
 
 #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
@@ -37,62 +42,262 @@ IGL_INLINE void igl::copyleft::cgal::trim_with_solid(
   Eigen::PlainObjectBase<DerivedF> & F,
   Eigen::PlainObjectBase<DerivedD> & D,
   Eigen::PlainObjectBase<DerivedJ> & J)
+{
+  return trim_with_solid(
+    VA,FA,VB,FB,TrimWithSolidMethod::CHECK_EACH_PATCH,
+    Vd,F,D,J);
+}
+template <
+  typename DerivedVA,
+  typename DerivedFA,
+  typename DerivedVB,
+  typename DerivedFB,
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedD,
+  typename DerivedJ>
+IGL_INLINE void igl::copyleft::cgal::trim_with_solid(
+  const Eigen::PlainObjectBase<DerivedVA> & VA,
+  const Eigen::PlainObjectBase<DerivedFA> & FA,
+  const Eigen::PlainObjectBase<DerivedVB> & VB,
+  const Eigen::PlainObjectBase<DerivedFB> & FB,
+  const TrimWithSolidMethod method,
+  Eigen::PlainObjectBase<DerivedV> & Vd,
+  Eigen::PlainObjectBase<DerivedF> & F,
+  Eigen::PlainObjectBase<DerivedD> & D,
+  Eigen::PlainObjectBase<DerivedJ> & J)
 {
   // resolve intersections using exact representation
   typedef Eigen::Matrix<CGAL::Epeck::FT,Eigen::Dynamic,3> MatrixX3E;
   typedef Eigen::Matrix<CGAL::Epeck::FT,Eigen::Dynamic,1> VectorXE;
+
+  // Previously this used intersect_other to resolve intersections between A and
+  // B hoping that it'd merge the two into a mesh where patches are separated by
+  // non-manifold edges. This happens most of the time but sometimes the
+  // new triangulations on faces of A don't match those on faces of B.
+  // Specifically it seems you can get T junctions:
+  //
+  //             /|\
+  //            / | \
+  //           / B|  \
+  //           ---| A ⋅
+  //           \ B|  /
+  //            \ | /
+  //             \|/
+  // Probably intersect_other should not be attempting to output a single mesh
+  // (i.e., when detect_only=false).
+  //
+  // # Alternative 1)
+  //
+  // Just call point_solid_signed_squared_distance for each output face.
+  // Obviously O(#output-faces) calls to point_solid_signed_squared_distance.
+  // But we get to use intersect_other to avoid finding and remeshing
+  // self-intersections in A
+  //
+  // # Alternative 2)
+  //
+  // Use SelfIntersectMesh to really get a
+  // single mesh with non-manifold edges. _But_ this would resolve any existing
+  // self-intersections in (VA,FA) which is not requested. An idea to "undo"
+  // this resolution is to undo any intersections _involving_ faces between A,B.
+  //
+  // This results in O(#patches) calls to point_solid_signed_squared_distance
+  // but calls remeshes on the order of O(#self-intersections-in-A)
+  //
+  // # Alterative 3)
+  //
+  // Use intersect_other but then create an adjacency matrix based on facets
+  // that share an edge but have a dissimilar J value. This will likely result
+  // in lots of tiny patches along the intersection belt. So let's say it has
+  // O(#A-B-intersection) calls to point_solid_signed_squared_distance
+  //
+  // If point_solid_signed_squared_distance turns out to me costly then 1) is
+  // out and we should do 2) or 3).
+  //
+  // Indeed. point_solid_signed_squared_distance is a major bottleneck for some
+  // examples.
+  //
+
   MatrixX3E V;
-  Eigen::MatrixXi _1;
-  Eigen::VectorXi _2;
-  // Intersect A and B meshes and stitch together new faces
-  igl::copyleft::cgal::intersect_other(
-    VA,FA,VB,FB,{false,false,true},_1,V,F,J,_2);
-  // Partition result into manifold patches
-  Eigen::VectorXi P;
-  const size_t num_patches = igl::extract_manifold_patches(F,P);
-  // only keep faces from A
-  Eigen::Array<bool,Eigen::Dynamic,1> A = J.array()< FA.rows();
-  const auto AI = igl::find(A);
-  F = F(AI,Eigen::all).eval();
-  P = P(AI).eval();
-  J = J(AI).eval();
-  // Aggregate representative query points for each patch
-  std::vector<bool> flag(num_patches);
-  std::vector<std::vector<CGAL::Epeck::FT> > vQ;
-  Eigen::VectorXi P2Q(num_patches);
-  for(int f = 0;f<P.rows();f++)
+  const auto set_D_via_patches = 
+    [&V,&F,&D,&VB,&FB](const int num_patches, const Eigen::VectorXi & P)
+  {
+    // Aggregate representative query points for each patch
+    std::vector<bool> flag(num_patches);
+    std::vector<std::vector<CGAL::Epeck::FT> > vQ;
+    Eigen::VectorXi P2Q(num_patches);
+    for(int f = 0;f<P.rows();f++)
+    {
+      const auto p = P(f);
+      // if not yet processed this patch
+      if(!flag[p])
+      {
+        P2Q(p) = vQ.size();
+        std::vector<CGAL::Epeck::FT> q = {
+          (V(F(f,0),0)+ V(F(f,1),0)+ V(F(f,2),0))/3.,
+          (V(F(f,0),1)+ V(F(f,1),1)+ V(F(f,2),1))/3.,
+          (V(F(f,0),2)+ V(F(f,1),2)+ V(F(f,2),2))/3.};
+        vQ.emplace_back(q);
+        flag[p] = true;
+      }
+    }
+    MatrixX3E Q;
+    igl::list_to_matrix(vQ,Q);
+    VectorXE SP;
+    point_solid_signed_squared_distance(Q,VB,FB,SP);
+    Eigen::Matrix<bool,Eigen::Dynamic,1> DP = SP.array()>0;
+    // distribute flag to all faces
+    D.resize(F.rows());
+    for(int f = 0;f<F.rows();f++)
+    {
+      D(f) = DP(P2Q(P(f)));
+    }
+  };
+
+  switch(method)
   {
-    const auto p = P(f);
-    // if not yet processed this patch
-    if(!flag[p])
+    case CHECK_EACH_PATCH:
+    case CHECK_EACH_FACE:
+    {
+      Eigen::MatrixXi _1;
+      Eigen::VectorXi _2;
+      // Intersect A and B meshes and stitch together new faces
+      igl::copyleft::cgal::intersect_other(
+        VA,FA,VB,FB,{false,false,true},_1,V,F,J,_2);
+      const auto keep = igl::find( (J.array()<FA.rows()).eval() );
+      F = F(keep,Eigen::all).eval();
+      J = J(keep).eval();
+      {
+        Eigen::VectorXi _;
+        igl::remove_unreferenced(decltype(V)(V),decltype(F)(F),V,F,_);
+      }
+      switch(method)
+      {
+        default: /*unreachable*/ break;
+        case CHECK_EACH_PATCH:
+        {
+          Eigen::SparseMatrix<bool> A;
+          igl::facet_adjacency_matrix(F,A);
+          for(int i = 0; i < A.outerSize(); i++)
+          {
+            for(decltype(A)::InnerIterator it(A,i); it; ++it)
+            {
+              const int a = it.row();
+              const int b = it.col();
+              if(J(a) == J(b))
+              {
+                A.coeffRef(a,b) = false;
+              }
+            }
+          }
+          A.prune(false);
+          Eigen::VectorXi P,K;
+          const int num_patches = igl::connected_components(A,P,K);
+          set_D_via_patches(num_patches,P);
+          break;
+        }
+        case CHECK_EACH_FACE:
+        {
+          MatrixX3E Q;
+          igl::barycenter(V,F,Q);
+          VectorXE SP;
+          point_solid_signed_squared_distance(Q,VB,FB,SP);
+          D = (SP.array()>0).template cast<typename DerivedD::Scalar>();
+          break;
+        }
+      }
+      break;
+    }
+    case RESOLVE_BOTH_AND_RESTORE_THEN_CHECK_EACH_PATCH:
     {
-      P2Q(p) = vQ.size();
-      std::vector<CGAL::Epeck::FT> q = {
-        (V(F(f,0),0)+ V(F(f,1),0)+ V(F(f,2),0))/3.,
-        (V(F(f,0),1)+ V(F(f,1),1)+ V(F(f,2),1))/3.,
-        (V(F(f,0),2)+ V(F(f,1),2)+ V(F(f,2),2))/3.};
-      vQ.emplace_back(q);
-      flag[p] = true;
+      RemeshSelfIntersectionsParam params;
+      // This is somewhat dubious but appears to work. The stitch_all flag is
+      // poorly documented.
+      params.stitch_all = false;
+      {
+        Eigen::MatrixXi IF;
+        Eigen::Matrix<typename DerivedVA::Scalar,Eigen::Dynamic,3> VAB(VA.rows() + VB.rows(),3);
+        VAB << VA,VB;
+        Eigen::Matrix<typename DerivedFA::Scalar,Eigen::Dynamic,3> FAB(FA.rows() + FB.rows(),3);
+        FAB << FA,FB.array()+VA.rows();
+        /// Sigh. Can't use this because of how it calls remove_unreferenced 
+        // remesh_self_intersections(VAB,FAB,params,V,F,IF,J);
+        {
+          Eigen::VectorXi I;
+          igl::copyleft::cgal::remesh_self_intersections(
+            VAB, FAB, params, V, F, IF, J, I);
+          // Undo self-intersection remeshing in FA
+          {
+            Eigen::Array<bool,Eigen::Dynamic,1> avoids_B = 
+              Eigen::Array<bool,Eigen::Dynamic,1>::Constant(FA.rows(),1,true);
+            for(int p = 0;p<IF.rows();p++)
+            {
+              if(IF(p,0) >= FA.rows() || IF(p,1) >= FA.rows())
+              {
+                if(IF(p,0) < FA.rows()){ avoids_B[IF(p,0)] = false; }
+                if(IF(p,1) < FA.rows()){ avoids_B[IF(p,1)] = false; }
+              }
+            }
+            // Find first entry for each in J
+            Eigen::VectorXi first = Eigen::VectorXi::Constant(FA.rows(),1,-1);
+            for(int j = 0;j<J.rows();j++)
+            {
+              if(J(j) < FA.rows() && first[J(j)] == -1)
+              {
+                first[J(j)] = j;
+                // restore original face at this first entry
+                if(avoids_B[J(j)])
+                {
+                  F.row(j) = FA.row(J(j));
+                }
+              }
+            }
+            // Maybe this cannot happen for co-planar?
+            assert(first.minCoeff() >= 0 && "Every face should be found");
+            std::vector<int> keep;
+            for(int f = 0;f<F.rows();f++)
+            {
+              if(J(f)>=FA.rows() || !avoids_B[J(f)] || first[J(f)] == f)
+              {
+                keep.push_back(f);
+              }
+            }
+            F = F(keep,Eigen::all).eval();
+            J = J(keep).eval();
+          }
+
+          // Don't do this until the very end:
+          assert(I.size() == Vr.rows());
+          // Merge coinciding vertices into non-manifold vertices.
+          std::for_each(F.data(),F.data()+F.size(),[&I](typename DerivedF::Scalar & a){a=I[a];});
+        }
+      }
+      // Partition result into manifold patches
+      Eigen::VectorXi P;
+      const int num_patches = igl::extract_manifold_patches(F,P);
+      // only keep faces from A
+      Eigen::Array<bool,Eigen::Dynamic,1> A = J.array()< FA.rows();
+      const auto AI = igl::find(A);
+      F = F(AI,Eigen::all).eval();
+      J = J(AI).eval();
+      P = P(AI).eval();
+      set_D_via_patches(num_patches,P);
+      break;
     }
   }
-  MatrixX3E Q;
-  igl::list_to_matrix(vQ,Q);
-  VectorXE SP;
-  point_solid_signed_squared_distance(Q,VB,FB,SP);
-  Eigen::Matrix<bool,Eigen::Dynamic,1> DP = SP.array()>0;
-  // distribute flag to all faces
-  D.resize(F.rows());
-  for(int f = 0;f<F.rows();f++)
   {
-    D(f) = DP(P2Q(P(f)));
+    Eigen::VectorXi _;
+    igl::remove_unreferenced(MatrixX3E(V),DerivedF(F),V,F,_);
   }
-  Eigen::VectorXi _;
-  igl::remove_unreferenced(MatrixX3E(V),DerivedF(F),V,F,_);
   assign(V,Vd);
+
 }
 
 
+
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
-template void igl::copyleft::cgal::trim_with_solid<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1,  -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0,  -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>  >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int,  -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&,  Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1,  -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&,  Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1,  1> >&);
+template void igl::copyleft::cgal::trim_with_solid<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int,  -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&,  Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1,  -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&,  Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1,  1> >&);
+template void igl::copyleft::cgal::trim_with_solid<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Array<bool, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Array<bool, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+template void igl::copyleft::cgal::trim_with_solid<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Array<bool, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, igl::copyleft::cgal::TrimWithSolidMethod, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Array<bool, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 #endif

+ 48 - 0
include/igl/copyleft/cgal/trim_with_solid.h

@@ -17,6 +17,31 @@ namespace igl
   {
     namespace cgal
     {
+      enum TrimWithSolidMethod
+      {
+        /// Resolve intersections only between A and B and then check whether
+        /// every face in A is inside/outside of B. (Included for debugging).
+        CHECK_EACH_FACE = 1,
+        /// Resolve intersections only between A and B, then separate into
+        /// patches of connected faces --- where connected means sharing an edge
+        /// and _not_ the same original face in A --- then label each patch as
+        /// inside or outside. This should always be strictly equivalent in
+        /// output and strictly fewer FLOPS than CHECK_EACH_FACE. There will be
+        /// many tiny patches along the intersection of A and B. 
+        CHECK_EACH_PATCH = 2,
+        /// Merge A and B into the same mesh and resolve all self-itnersections.
+        /// Then "undo" remeshing on faces of A not involved in intersections
+        /// with B (i.e., self-intersections in A). Then seperate into patches
+        /// based on connected faces --- where connected means sharing a
+        /// _manifold edge_ --- then label each aptch as inside or outside.
+        /// Results in fewer patches than CHECK_EACH_PATCH but finding, meshing and
+        /// mesh-undoing self-intersections in A can be costly. This
+        /// could result in different output from CHECK_EACH_PATCH because of
+        /// shared remeshing with (i.e., faces in A that both intersect B and
+        /// other faces in A). If A has no self-intersections then I claim the
+        /// outputs should be the same.
+        RESOLVE_BOTH_AND_RESTORE_THEN_CHECK_EACH_PATCH = 3,
+      };
       /// Given an arbitrary mesh (VA,FA) and the boundary mesh
       /// (VB,FB) of a solid (as defined in [Zhou et al. 2016]), Resolve intersections
       /// between A and B subdividing faces of A so that intersections with B exists
@@ -51,6 +76,29 @@ namespace igl
         Eigen::PlainObjectBase<DerivedF> & F,
         Eigen::PlainObjectBase<DerivedD> & D,
         Eigen::PlainObjectBase<DerivedJ> & J);
+      /// \overload
+      ///
+      /// @param[in] method  which method for extracting and determining the
+      /// trim contents.
+      template <
+        typename DerivedVA,
+        typename DerivedFA,
+        typename DerivedVB,
+        typename DerivedFB,
+        typename DerivedV,
+        typename DerivedF,
+        typename DerivedD,
+        typename DerivedJ>
+      IGL_INLINE void trim_with_solid(
+        const Eigen::PlainObjectBase<DerivedVA> & VA,
+        const Eigen::PlainObjectBase<DerivedFA> & FA,
+        const Eigen::PlainObjectBase<DerivedVB> & VB,
+        const Eigen::PlainObjectBase<DerivedFB> & FB,
+        const TrimWithSolidMethod method,
+        Eigen::PlainObjectBase<DerivedV> & Vd,
+        Eigen::PlainObjectBase<DerivedF> & F,
+        Eigen::PlainObjectBase<DerivedD> & D,
+        Eigen::PlainObjectBase<DerivedJ> & J);
     }
   }
 }

+ 2 - 0
include/igl/facet_adjacency_matrix.cpp

@@ -54,5 +54,7 @@ IGL_INLINE void igl::facet_adjacency_matrix(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
 // generated by autoexplicit.sh
+template void igl::facet_adjacency_matrix<Eigen::Matrix<int, -1, -1, 0, -1, -1>, bool>(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<bool, 0, int>&);
+// generated by autoexplicit.sh
 template void igl::facet_adjacency_matrix<Eigen::Matrix<int, -1, -1, 0, -1, -1>, int>(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<int, 0, int>&);
 #endif

+ 19 - 0
include/igl/find.cpp

@@ -41,6 +41,25 @@ IGL_INLINE void igl::find(
   }
 }
 
+template < typename T>
+IGL_INLINE std::vector<Eigen::Triplet<T> > igl::find(
+  const Eigen::SparseMatrix<T>& X)
+{
+  std::vector<Eigen::Triplet<T>> ijv;
+  for(int i = 0; i < X.outerSize(); i++)
+  {
+    for(typename Eigen::SparseMatrix<T>::InnerIterator it(X,i); it; it++)
+    {
+      // Match find above
+      //if(it.value())
+      {
+        ijv.emplace_back(it.row(),it.col(),it.value());
+      }
+    }
+  }
+  return ijv;
+}
+
 template <
   typename DerivedX,
   typename DerivedI, 

+ 4 - 0
include/igl/find.h

@@ -34,6 +34,10 @@ namespace igl
     Eigen::DenseBase<DerivedJ> & J,
     Eigen::DenseBase<DerivedV> & V);
   /// \overload
+  template < typename T>
+  IGL_INLINE std::vector<Eigen::Triplet<T> > find(
+    const Eigen::SparseMatrix<T>& X);
+  /// \overload
   template <
     typename DerivedX,
     typename DerivedI, 

+ 2 - 0
include/igl/orient_outward.h

@@ -20,6 +20,8 @@ namespace igl
   /// @param[out] FF  #F by 3 list of new triangle indices such that FF(~I,:) = F(~I,:) and
   ///     FF(I,:) = fliplr(F(I,:)) (OK if &FF = &F)
   /// @param[out] I  max(C)+1 list of whether face has been flipped
+  ///
+  /// \see orientable_patches, reorient_facets_raycast
   template <
     typename DerivedV,
     typename DerivedF,

+ 2 - 1
include/igl/sort_triangles.cpp

@@ -52,6 +52,7 @@ IGL_INLINE void igl::sort_triangles(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
-template void igl::sort_triangles<Eigen::Matrix<double, -1, 4, 0, -1, 4>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 4, 4, 0, 4, 4>, Eigen::Matrix<double, 4, 4, 0, 4, 4>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 4, 0, -1, 4> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 4, 4, 0, 4, 4> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 4, 4, 0, 4, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+// generated by autoexplicit.sh
+template void igl::sort_triangles<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<float, 4, 4, 0, 4, 4>, Eigen::Matrix<float, 4, 4, 0, 4, 4>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, 4, 4, 0, 4, 4> > const&, Eigen::MatrixBase<Eigen::Matrix<float, 4, 4, 0, 4, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::sort_triangles<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 4, 4, 0, 4, 4>, Eigen::Matrix<double, 4, 4, 0, 4, 4>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 4, 4, 0, 4, 4> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 4, 4, 0, 4, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 #endif

+ 2 - 0
include/igl/writeDMAT.cpp

@@ -84,6 +84,8 @@ IGL_INLINE bool igl::writeDMAT(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
+// generated by autoexplicit.sh
+template bool igl::writeDMAT<Eigen::Matrix<int, -1, 1, 0, -1, 1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, bool);
 template bool igl::writeDMAT<Eigen::Matrix<double, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, bool);
 template bool igl::writeDMAT<Eigen::Matrix<double, -1, 1, 0, -1, 1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, bool);
 template bool igl::writeDMAT<Eigen::Matrix<double, 1, 3, 1, 1, 3> >(std::string, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, bool);

+ 3 - 0
include/igl/writePLY.cpp

@@ -404,6 +404,9 @@ bool writePLY(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
 // generated by autoexplicit.sh
+// generated by autoexplicit.sh
+template bool igl::writePLY<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&);
+// generated by autoexplicit.sh
 template bool igl::writePLY<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, igl::FileEncoding);
 // generated by autoexplicit.sh
 template bool igl::writePLY<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, igl::FileEncoding);

+ 110 - 0
tests/include/igl/copyleft/cgal/trim_with_solid.cpp

@@ -0,0 +1,110 @@
+#include <test_common.h>
+#include <igl/copyleft/cgal/trim_with_solid.h>
+#include <igl/matlab_format.h>
+#include <iostream>
+
+TEST_CASE("trim_with_solid: triangle-vs-tet", "[igl/copyleft/cgal]")
+{
+  // Single Tet
+  Eigen::MatrixXd VB(4,3);
+  VB<<
+    0,0,0,
+    1,0,0,
+    0,1,0,
+    0,0,1;
+  Eigen::MatrixXi FB(4,3);
+  FB<<
+    0,1,3,
+    0,2,1,
+    0,3,2,
+    1,2,3;
+  Eigen::MatrixXd VA(3,3);
+  VA<< 
+    0.2,0.2,0.2,
+    0.8,0.2,0.2,
+    0.2,0.8,0.2;
+  Eigen::MatrixXi FA(1,3);
+  FA<<0,1,2;
+  using namespace igl::copyleft::cgal;
+  Eigen::MatrixXd V;
+  Eigen::MatrixXi F;
+  Eigen::Array<bool,Eigen::Dynamic,1> D;
+  Eigen::VectorXi J;
+  const auto test = [&]()
+  {
+    REQUIRE(V.rows() == 5);
+    REQUIRE(F.rows() == 3);
+    REQUIRE(D.size() == F.rows());
+    REQUIRE(J.size() == F.rows());
+    REQUIRE(D.count() == 2);
+    REQUIRE((J.array() == 0).count() == 3);
+  };
+  igl::copyleft::cgal::trim_with_solid(VA,FA,VB,FB,CHECK_EACH_FACE,V,F,D,J);
+  test();
+  igl::copyleft::cgal::trim_with_solid(VA,FA,VB,FB,CHECK_EACH_PATCH,V,F,D,J);
+  test();
+  igl::copyleft::cgal::trim_with_solid(VA,FA,VB,FB,RESOLVE_BOTH_AND_RESTORE_THEN_CHECK_EACH_PATCH,V,F,D,J);
+  test();
+}
+
+TEST_CASE("trim_with_solid: two-vs-cube", "[igl/copyleft/cgal]")
+{
+  Eigen::MatrixXd VA(6,3);
+  VA<< 
+    3.5301513671875,77.03765869140625,1.3964500427246094,
+    3.5709075927734375,77.055023193359375,1.396728515625,
+    4.4851531982421875,78.03460693359375,1.6064491271972656,
+    3.6009368896484375,77.064865112304688,1.50128173828125,
+    3.613006591796875,77.075912475585938,1.5090217590332031,
+    4.2685699462890625,77.5335693359375,1.6356697082519531;
+  Eigen::MatrixXi FA(2,3);
+  FA<< 
+    1,2,3,
+    0,4,5;
+  Eigen::MatrixXd VB(8,3);
+  VB<< 
+    -1.8674041748046903,-5.6647888183593835,-0.071252098083496196,
+    -1.8674041748046903,118.96056518554688,-0.071252098083496196,
+    39.21548767089844,-5.6647888183593835,-0.071252098083496196,
+    39.21548767089844,118.96056518554688,-0.071252098083496196,
+    39.21548767089844,-5.6647888183593835,1.496294059753418,
+    39.21548767089844,118.96056518554688,1.496294059753418,
+    -1.8674041748046903,-5.6647888183593835,1.496294059753418,
+    -1.8674041748046903,118.96056518554688,1.496294059753418;
+  Eigen::MatrixXi FB(12,3);
+  FB<< 
+    1,2,0,
+    1,3,2,
+    3,4,2,
+    3,5,4,
+    0,4,6,
+    0,2,4,
+    7,3,1,
+    7,5,3,
+    7,0,6,
+    7,1,0,
+    5,6,4,
+    5,7,6;
+  using namespace igl::copyleft::cgal;
+  Eigen::MatrixXd V;
+  Eigen::MatrixXi F;
+  Eigen::Array<bool,Eigen::Dynamic,1> D;
+  Eigen::VectorXi J;
+  const auto test = [&]()
+  {
+    REQUIRE(V.rows() >= VA.rows());
+    REQUIRE(FA.rows() == FA.rows());
+    REQUIRE(D.size() == F.rows());
+    REQUIRE(J.size() == F.rows());
+    // some in some out
+    REQUIRE( (D.array() == false).count() != 0);
+    REQUIRE( (D.array() == true).count() != 0);
+  };
+  igl::copyleft::cgal::trim_with_solid(VA,FA,VB,FB,CHECK_EACH_FACE,V,F,D,J);
+  test();
+  igl::copyleft::cgal::trim_with_solid(VA,FA,VB,FB,CHECK_EACH_PATCH,V,F,D,J);
+  test();
+  igl::copyleft::cgal::trim_with_solid(VA,FA,VB,FB,RESOLVE_BOTH_AND_RESTORE_THEN_CHECK_EACH_PATCH,V,F,D,J);
+  test();
+
+}

+ 94 - 0
tutorial/906_TrimWithSolid/main.cpp

@@ -0,0 +1,94 @@
+#include <igl/opengl/glfw/Viewer.h>
+#include <igl/read_triangle_mesh.h>
+#include <igl/get_seconds.h>
+#include <igl/sort_triangles.h>
+#include <igl/material_colors.h>
+#include <igl/copyleft/cgal/trim_with_solid.h>
+
+int main(int argc, char *argv[])
+{
+  using namespace igl;
+  IGL_TICTOC_LAMBDA;
+  Eigen::MatrixXd VA, VB;
+  Eigen::MatrixXi FA, FB;
+  // Load a hot mess of a mesh
+  igl::read_triangle_mesh(argc>1?argv[1]:TUTORIAL_SHARED_PATH "/truck.obj", VA, FA);
+  // Load a solid mesh
+  igl::read_triangle_mesh(argc>2?argv[2]:TUTORIAL_SHARED_PATH "/bunny.off", VB, FB);
+  if(argc<2)
+  {
+    // resize bunny
+    VB.rowwise() -= VB.colwise().mean();
+    VB /= (VB.colwise().maxCoeff()-VB.colwise().minCoeff()).maxCoeff();
+    VB *= 1.15;
+    VB.rowwise() += VA.colwise().mean();
+  }
+
+  Eigen::VectorXi J;
+  Eigen::MatrixXd VC;
+  Eigen::MatrixXi FC;
+  Eigen::Array<bool, Eigen::Dynamic, 1> D;
+  using namespace igl::copyleft::cgal;
+  tictoc();
+  // More patches, less intersection handling
+  igl::copyleft::cgal::trim_with_solid(VA, FA, VB, FB, CHECK_EACH_PATCH, VC, FC, D, J);
+  printf("CHECK_EACH_PATCH: %g secs, |FC| = %d, |D| = %d\n", tictoc(),FC.rows(),D.count());
+  // More intersection handling, fewer patches
+  igl::copyleft::cgal::trim_with_solid(VA, FA, VB, FB, RESOLVE_BOTH_AND_RESTORE_THEN_CHECK_EACH_PATCH, VC, FC, D, J);
+  printf("RESOLVE_BOTH_...: %g secs, |FC| = %d, |D| = %d\n", tictoc(),FC.rows(),D.count());
+
+  igl::opengl::glfw::Viewer vr;
+  vr.data().set_mesh(VC, FC);
+  // Turn on double sided lighting
+  vr.data().double_sided = true;
+  vr.data().set_face_based(true);
+  vr.data().set_data(D.cast<double>());
+  Eigen::MatrixXd CM = (Eigen::MatrixXd(2,3)<< 
+      1,1,1,
+      GOLD_DIFFUSE[0],GOLD_DIFFUSE[1],GOLD_DIFFUSE[2]
+      ).finished();
+  vr.data().set_colormap(CM);
+
+  vr.append_mesh();
+  vr.data().set_mesh(VB, FB);
+  vr.data().show_lines = false;
+  // Make a semi-transparent orange matcap
+  {
+    Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> 
+      R(256,256), G(256,256), B(256,256), A(256,256);
+    for(int i = 0;i<R.rows();i++)
+    {
+      for(int j = 0;j<R.cols();j++)
+      {
+        R(i,j) = 255;
+        G(i,j) = 110;
+        B(i,j) = 20;
+        // distance to middle of image
+        const double x = (i+0.5-R.rows()/2.0)/(R.rows()/2.0);
+        const double y = (j+0.5-R.cols()/2.0)/(R.cols()/2.0);
+        const double r = std::min(1.0,sqrt(x*x+y*y));
+        A(i,j) = 255*(1-sqrt(1-r*r));
+      }
+    }
+    vr.data().set_texture(R,G,B,A);
+  }
+  vr.data().use_matcap = true;
+  // On mouse up resort for better transparency
+  vr.callback_mouse_up = 
+    [&](igl::opengl::glfw::Viewer &, int button, int mod)
+  {
+    Eigen::VectorXi _;
+    igl::sort_triangles(
+      VB,Eigen::MatrixXi(FB), vr.core().view, vr.core().proj,FB,_);
+    vr.data_list[1].set_mesh(VB, FB);
+    return false;
+  };
+  // set first mesh as selected
+  vr.selected_data_index = 0;
+
+  vr.launch_init(false);
+  vr.core().draw(vr.data(),true);
+  vr.callback_mouse_up(vr,0,0);
+  vr.launch_rendering(true);
+  vr.launch_shut();
+}

+ 1 - 0
tutorial/CMakeLists.txt

@@ -127,4 +127,5 @@ if(LIBIGL_TUTORIALS_CHAPTER9)
     igl_add_tutorial(903_FastFindSelfIntersections igl::imgui igl::glfw)
     igl_add_tutorial(904_FastFindIntersections igl::imgui igl::glfw)
     igl_add_tutorial(905_Isolines igl::imgui igl::glfw)
+    igl_add_tutorial(906_TrimWithSolid igl::glfw igl_copyleft::cgal)
 endif()