Forráskód Böngészése

Merge current master

Former-commit-id: ed811b52613a5e7e488300e5805782591f03150c
jmespadero 8 éve
szülő
commit
892496b73c
41 módosított fájl, 1663 hozzáadás és 235 törlés
  1. 0 15
      include/igl/copyleft/cgal/SelfIntersectMesh.h
  2. 0 3
      include/igl/copyleft/cgal/intersect_other.cpp
  3. 41 0
      include/igl/copyleft/cgal/point_segment_squared_distance.cpp
  4. 44 0
      include/igl/copyleft/cgal/point_segment_squared_distance.h
  5. 47 0
      include/igl/copyleft/cgal/point_triangle_squared_distance.cpp
  6. 45 0
      include/igl/copyleft/cgal/point_triangle_squared_distance.h
  7. 0 30
      include/igl/copyleft/cgal/remesh_intersections.cpp
  8. 91 0
      include/igl/copyleft/cgal/resolve_intersections.cpp
  9. 51 0
      include/igl/copyleft/cgal/resolve_intersections.h
  10. 18 0
      include/igl/copyleft/cgal/row_to_point.cpp
  11. 38 0
      include/igl/copyleft/cgal/row_to_point.h
  12. 129 0
      include/igl/copyleft/cgal/segment_segment_squared_distance.cpp
  13. 46 0
      include/igl/copyleft/cgal/segment_segment_squared_distance.h
  14. 206 0
      include/igl/copyleft/cgal/snap_rounding.cpp
  15. 51 0
      include/igl/copyleft/cgal/snap_rounding.h
  16. 134 0
      include/igl/copyleft/cgal/subdivide_segments.cpp
  17. 56 0
      include/igl/copyleft/cgal/subdivide_segments.h
  18. 114 0
      include/igl/copyleft/cgal/triangle_triangle_squared_distance.cpp
  19. 45 0
      include/igl/copyleft/cgal/triangle_triangle_squared_distance.h
  20. 96 0
      include/igl/ismember.cpp
  21. 41 0
      include/igl/ismember.h
  22. 1 0
      include/igl/list_to_matrix.cpp
  23. 146 125
      include/igl/loop.cpp
  24. 40 29
      include/igl/loop.h
  25. 4 1
      include/igl/serialize.h
  26. 1 0
      include/igl/sort.cpp
  27. 1 0
      include/igl/unique.cpp
  28. 58 24
      include/igl/upsample.cpp
  29. 25 2
      include/igl/upsample.h
  30. 6 0
      matlab-to-eigen.html
  31. 1 1
      shared/cmake/CMakeLists.txt
  32. 1 1
      tutorial/710_SLIM/CMakeLists.txt
  33. 0 0
      tutorial/710_SLIM/main.cpp
  34. 8 0
      tutorial/711_Subdivision/CMakeLists.txt
  35. 68 0
      tutorial/711_Subdivision/main.cpp
  36. 2 2
      tutorial/CMakeLists.txt
  37. 1 0
      tutorial/images/decimated-knight-subdivision.gif.REMOVED.git-id
  38. 0 0
      tutorial/images/slim.png.REMOVED.git-id
  39. 5 0
      tutorial/style.css
  40. 1 1
      tutorial/tutorial.html.REMOVED.git-id
  41. 1 1
      tutorial/tutorial.md.REMOVED.git-id

+ 0 - 15
include/igl/copyleft/cgal/SelfIntersectMesh.h

@@ -76,9 +76,6 @@ namespace igl
           typedef CGAL::Constrained_triangulation_face_base_2<Kernel> CTFB_2;
           typedef CGAL::Triangulation_data_structure_2<TVB_2,CTFB_2> TDS_2;
           typedef CGAL::Exact_intersections_tag Itag;
-          typedef CGAL::Constrained_Delaunay_triangulation_2<Kernel,TDS_2,Itag> 
-            CDT_2;
-          typedef CGAL::Constrained_triangulation_plus_2<CDT_2> CDT_plus_2;
           // Axis-align boxes for all-pairs self-intersection detection
           typedef std::vector<Triangle_3> Triangles;
           typedef typename Triangles::iterator TrianglesIterator;
@@ -206,18 +203,6 @@ namespace igl
           //   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
-          // projection rather than an isometric projection, so we're not
-          // guaranteed that the 2D delaunay triangulation here will be a delaunay
-          // triangulation in 3D.
-          //
-          // Inputs:
-          //   A  triangle in 3D
-          //   A_objects_3  updated list of intersection objects for A
-          // Outputs:
-          //   cdt  Contrained delaunay triangulation in projected 2D plane
         public:
           // Getters:
           //const IndexList& get_lIF() const{ return lIF;}

+ 0 - 3
include/igl/copyleft/cgal/intersect_other.cpp

@@ -96,9 +96,6 @@ namespace igl
         typedef CGAL::Constrained_triangulation_face_base_2<Kernel> CTAB_2;
         typedef CGAL::Triangulation_data_structure_2<TVB_2,CTAB_2> TDS_2;
         typedef CGAL::Exact_intersections_tag Itag;
-        typedef CGAL::Constrained_Delaunay_triangulation_2<Kernel,TDS_2,Itag> 
-          CDT_2;
-        typedef CGAL::Constrained_triangulation_plus_2<CDT_2> CDT_plus_2;
         // Axis-align boxes for all-pairs self-intersection detection
         typedef std::vector<Triangle_3> Triangles;
         typedef typename Triangles::iterator TrianglesIterator;

+ 41 - 0
include/igl/copyleft/cgal/point_segment_squared_distance.cpp

@@ -0,0 +1,41 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "point_segment_squared_distance.h"
+
+template < typename Kernel>
+IGL_INLINE void igl::copyleft::cgal::point_segment_squared_distance(
+  const CGAL::Point_3<Kernel> & P1,
+  const CGAL::Segment_3<Kernel> & S2,
+  CGAL::Point_3<Kernel> & P2,
+  typename Kernel::FT & d)
+{
+  if(S2.is_degenerate())
+  {
+    P2 = S2.source();
+    d = (P1-P2).squared_length();
+    return;
+  }
+  // http://stackoverflow.com/a/1501725/148668
+  const auto sqr_len = S2.squared_length();
+  assert(sqr_len != 0);
+  const auto & V = S2.source();
+  const auto & W = S2.target();
+  const auto t = (P1-V).dot(W-V)/sqr_len;
+  if(t<0)
+  {
+    P2 = V;
+  }else if(t>1)
+  {
+    P2 = W;
+  }else
+  {
+    P2 = V  + t*(W-V);
+  }
+  d = (P1-P2).squared_length();
+}
+

+ 44 - 0
include/igl/copyleft/cgal/point_segment_squared_distance.h

@@ -0,0 +1,44 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_COPYLEFT_CGAL_POINT_SEGMENT_SQUARED_DISTANCE_H
+#define IGL_COPYLEFT_CGAL_POINT_SEGMENT_SQUARED_DISTANCE_H
+#include "../../igl_inline.h"
+#include <CGAL/Segment_3.h>
+#include <CGAL/Point_3.h>
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // Given a point P1 and segment S2 find the points on each of closest
+      // approach and the squared distance thereof.
+      // 
+      // Inputs:
+      //   P1  point
+      //   S2  segment
+      // Outputs:
+      //   P2  point on S2 closest to P1
+      //   d  distance betwee P1 and S2
+      template < typename Kernel>
+      IGL_INLINE void point_segment_squared_distance(
+          const CGAL::Point_3<Kernel> & P1,
+          const CGAL::Segment_3<Kernel> & S2,
+          CGAL::Point_3<Kernel> & P2,
+          typename Kernel::FT & d
+          );
+
+    }
+  }
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "point_segment_squared_distance.cpp"
+#endif
+
+#endif
+

+ 47 - 0
include/igl/copyleft/cgal/point_triangle_squared_distance.cpp

@@ -0,0 +1,47 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "point_triangle_squared_distance.h"
+#include <CGAL/Segment_3.h>
+template < typename Kernel>
+IGL_INLINE void point_triangle_squared_distance(
+  const CGAL::Point_3<Kernel> & P1,
+  const CGAL::Triangle_3<Kernel> & T2,
+  CGAL::Point_3<Kernel> & P2,
+  typename Kernel::FT & d)
+{
+  assert(!T2.is_degenerate());
+  if(T2.has_on(P1))
+  {
+    P2 = P1;
+    d = 0;
+    return;
+  }
+  const auto proj_1 = T2.supporting_plane().projection(P2);
+  if(T2.has_on(proj_1))
+  {
+    P2 = proj_1;
+    d = (proj_1-P1).squared_length();
+    return;
+  }
+  // closest point must be on the boundary
+  bool first = true;
+  // loop over edges
+  for(int i=0;i<3;i++)
+  {
+    CGAL::Point_3<Kernel> P2i;
+    typename Kernel::FT di;
+    const CGAL::Segment_3<Kernel> si( T2.vertex(i+1), T2.vertex(i+2));
+    point_segment_squared_distance(P1,si,P2i,di);
+    if(first || di < d)
+    {
+      first = false;
+      d = di;
+      P2 = P2i;
+    }
+  }
+}

+ 45 - 0
include/igl/copyleft/cgal/point_triangle_squared_distance.h

@@ -0,0 +1,45 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_COPYLEFT_CGAL_POINT_TRIANGLE_SQUARED_DISTANCE_H
+#define IGL_COPYLEFT_CGAL_POINT_TRIANGLE_SQUARED_DISTANCE_H
+#include "../../igl_inline.h"
+#include <CGAL/Triangle_3.h>
+#include <CGAL/Point_3.h>
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // Given a point P1 and triangle T2 find the points on each of closest
+      // approach and the squared distance thereof.
+      // 
+      // Inputs:
+      //   P1  point
+      //   T2  triangle
+      // Outputs:
+      //   P2  point on T2 closest to P1
+      //   d  distance betwee P1 and T2
+      template < typename Kernel>
+      IGL_INLINE void point_triangle_squared_distance(
+        const CGAL::Point_3<Kernel> & P1,
+        const CGAL::Triangle_3<Kernel> & T2,
+        CGAL::Point_3<Kernel> & P2,
+        typename Kernel::FT & d
+        );
+
+    }
+  }
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "point_triangle_squared_distance.cpp"
+#endif
+
+#endif
+
+

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

@@ -512,65 +512,35 @@ IGL_INLINE void igl::copyleft::cgal::remesh_intersections(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
-// generated by autoexplicit.sh
 template void igl::copyleft::cgal::remesh_intersections<Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epick, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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, 1, -1, -1> > const&, Eigen::PlainObjectBase<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, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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_intersections<Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epeck, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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, 1, -1, -1> > const&, Eigen::PlainObjectBase<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, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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_intersections<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epick, 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&, 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, 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> >&);
-// generated by autoexplicit.sh
 template void igl::copyleft::cgal::remesh_intersections<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epick, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<long, -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&, 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, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -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, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epick, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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&, 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, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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_intersections<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epeck, 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&, 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, 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> >&);
-// generated by autoexplicit.sh
 template void igl::copyleft::cgal::remesh_intersections<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epeck, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<long, -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&, 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, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -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, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epeck, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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&, 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, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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_intersections<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epick, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<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, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -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, -1, 0, -1, -1>, CGAL::Epick, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<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, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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_intersections<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epeck, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<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, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -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, -1, 0, -1, -1>, CGAL::Epeck, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<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, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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_intersections<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epick, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<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, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -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::Epick, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<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, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -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> >&);
-// 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::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<long, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<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, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -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::Epick, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<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, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -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::Epick, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<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, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -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> >&);
-// 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<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<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, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -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<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<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, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -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> >&);
-// 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::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<long, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<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, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -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::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<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, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -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::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<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, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -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> >&);
-// generated by autoexplicit.sh
 template void igl::copyleft::cgal::remesh_intersections<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epick, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<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, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -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::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epick, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<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, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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_intersections<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epeck, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<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, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -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::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epeck, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<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, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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_intersections<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epick, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<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, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -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::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epeck, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<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, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -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::Lazy_exact_nt<CGAL::Gmpq>, 8, 3, 0, 8, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epick, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 8, 3, 0, 8, 3> > const&, Eigen::PlainObjectBase<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, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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_intersections<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 8, 3, 0, 8, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epeck, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 8, 3, 0, 8, 3> > const&, Eigen::PlainObjectBase<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, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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> >&);
 #undef IGL_STATIC_LIBRARY
 #include "../../unique.cpp"

+ 91 - 0
include/igl/copyleft/cgal/resolve_intersections.cpp

@@ -0,0 +1,91 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "resolve_intersections.h"
+#include "subdivide_segments.h"
+#include "row_to_point.h"
+#include "../../unique.h"
+#include "../../list_to_matrix.h"
+#include "../../copyleft/cgal/assign_scalar.h"
+#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+#include <CGAL/Segment_2.h>
+#include <CGAL/Point_2.h>
+#include <algorithm>
+#include <vector>
+
+template <
+  typename DerivedV, 
+  typename DerivedE, 
+  typename DerivedVI, 
+  typename DerivedEI,
+  typename DerivedJ,
+  typename DerivedIM>
+IGL_INLINE void igl::copyleft::cgal::resolve_intersections(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::PlainObjectBase<DerivedE> & E,
+  Eigen::PlainObjectBase<DerivedVI> & VI,
+  Eigen::PlainObjectBase<DerivedEI> & EI,
+  Eigen::PlainObjectBase<DerivedJ> & J,
+  Eigen::PlainObjectBase<DerivedIM> & IM)
+{
+  using namespace Eigen;
+  using namespace igl;
+  using namespace std;
+  // Exact scalar type
+  typedef CGAL::Epeck K;
+  typedef K::FT EScalar;
+  typedef CGAL::Segment_2<K> Segment_2;
+  typedef CGAL::Point_2<K> Point_2;
+  typedef Matrix<EScalar,Dynamic,Dynamic>  MatrixXE;
+
+  // Convert vertex positions to exact kernel
+  MatrixXE VE(V.rows(),V.cols());
+  for(int i = 0;i<V.rows();i++)
+  {
+    for(int j = 0;j<V.cols();j++)
+    {
+      VE(i,j) = V(i,j);
+    }
+  }
+
+  const int m = E.rows();
+  // resolve all intersections: silly O(n²) implementation
+  std::vector<std::vector<Point_2> > steiner(m);
+  for(int i = 0;i<m;i++)
+  {
+    Segment_2 si(row_to_point<K>(VE,E(i,0)),row_to_point<K>(VE,E(i,1)));
+    steiner[i].push_back(si.vertex(0));
+    steiner[i].push_back(si.vertex(1));
+    for(int j = i+1;j<m;j++)
+    {
+      Segment_2 sj(row_to_point<K>(VE,E(j,0)),row_to_point<K>(VE,E(j,1)));
+      // do they intersect?
+      if(CGAL::do_intersect(si,sj))
+      {
+        CGAL::Object result = CGAL::intersection(si,sj);
+        if(const Point_2 * p = CGAL::object_cast<Point_2 >(&result))
+        {
+          steiner[i].push_back(*p);
+          steiner[j].push_back(*p);
+          // add intersection point
+        }else if(const Segment_2 * s = CGAL::object_cast<Segment_2 >(&result))
+        {
+          // add both endpoints
+          steiner[i].push_back(s->vertex(0));
+          steiner[j].push_back(s->vertex(0));
+          steiner[i].push_back(s->vertex(1));
+          steiner[j].push_back(s->vertex(1));
+        }else
+        {
+          assert(false && "Unknown intersection type");
+        }
+      }
+    }
+  }
+
+  subdivide_segments(V,E,steiner,VI,EI,J,IM);
+}

+ 51 - 0
include/igl/copyleft/cgal/resolve_intersections.h

@@ -0,0 +1,51 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_COPYLEFT_CGAL_RESOLVE_INTERSECTIONS_H
+#define IGL_COPYLEFT_CGAL_RESOLVE_INTERSECTIONS_H
+#include "../../igl_inline.h"
+#include <Eigen/Core>
+
+namespace igl
+{
+  namespace copyleft
+  {
+    // RESOLVE_INTERSECTIONS Given a list of possible intersecting segments with
+    // endpoints, split segments to overlap only at endpoints
+    //
+    // Inputs:
+    //   V  #V by 2 list of vertex positions
+    //   E  #E by 2 list of segment indices into V
+    // Outputs:
+    //   VI  #VI by 2 list of output vertex positions, copies of V are always
+    //     the first #V vertices
+    //   EI  #EI by 2 list of segment indices into V, #EI ≥ #E
+    //   J  #EI list of indices into E revealing "parent segments"
+    //   IM  #VI list of indices into VV of unique vertices.
+    namespace cgal
+    {
+      template <
+        typename DerivedV, 
+        typename DerivedE, 
+        typename DerivedVI, 
+        typename DerivedEI,
+        typename DerivedJ,
+        typename DerivedIM>
+      IGL_INLINE void resolve_intersections(
+        const Eigen::PlainObjectBase<DerivedV> & V,
+        const Eigen::PlainObjectBase<DerivedE> & E,
+        Eigen::PlainObjectBase<DerivedVI> & VI,
+        Eigen::PlainObjectBase<DerivedEI> & EI,
+        Eigen::PlainObjectBase<DerivedJ> & J,
+        Eigen::PlainObjectBase<DerivedIM> & IM);
+    }
+  }
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "resolve_intersections.cpp"
+#endif
+#endif

+ 18 - 0
include/igl/copyleft/cgal/row_to_point.cpp

@@ -0,0 +1,18 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "row_to_point.h"
+
+template <
+  typename Kernel,
+  typename DerivedV>
+IGL_INLINE CGAL::Point_2<Kernel> igl::copyleft::cgal::row_to_point(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const typename DerivedV::Index & i)
+{
+  return CGAL::Point_2<Kernel>(V(i,0),V(i,1));
+}

+ 38 - 0
include/igl/copyleft/cgal/row_to_point.h

@@ -0,0 +1,38 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_COPYLEFT_CGAL_ROW_TO_POINT_H
+#define IGL_COPYLEFT_CGAL_ROW_TO_POINT_H
+#include "../../igl_inline.h"
+#include <Eigen/Core>
+#include <CGAL/Point_2.h>
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // Extract a row from V and treat as a 2D cgal point (only first two
+      // columns of V are used).
+      // 
+      // Inputs:
+      //   V  #V by 2 list of vertex positions
+      //   i  row index
+      // Returns 2D cgal point
+      template <
+        typename Kernel,
+        typename DerivedV>
+      IGL_INLINE CGAL::Point_2<Kernel> row_to_point(
+        const Eigen::PlainObjectBase<DerivedV> & V,
+        const typename DerivedV::Index & i);
+    }
+  }
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "row_to_point.cpp"
+#endif
+#endif

+ 129 - 0
include/igl/copyleft/cgal/segment_segment_squared_distance.cpp

@@ -0,0 +1,129 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "segment_segment_squared_distance.h"
+#include <CGAL/Vector_3.h>
+
+// http://geomalgorithms.com/a07-_distance.html
+template < typename Kernel>
+IGL_INLINE bool igl::copyleft::cgal::segment_segment_squared_distance(
+    const CGAL::Segment_3<Kernel> & S1,
+    const CGAL::Segment_3<Kernel> & S2,
+    CGAL::Point_3<Kernel> & P1,
+    CGAL::Point_3<Kernel> & P2,
+    typename Kernel::FT & dst)
+{
+  typedef CGAL::Point_3<Kernel> Point_3;
+  typedef CGAL::Vector_3<Kernel> Vector_3;
+  typedef typename Kernel::FT EScalar;
+  if(S1.is_degenerate())
+  {
+    // All points on S1 are the same
+    P1 = S1.source();
+    point_segment_squared_distance(P1,S2,P2,dst);
+    return true;
+  }else if(S2.is_degenerate())
+  {
+    assert(!S1.is_degenerate());
+    // All points on S2 are the same
+    P2 = S2.source();
+    point_segment_squared_distance(P2,S1,P1,dst);
+    return true;
+  }
+
+  assert(!S1.is_degenerate());
+  assert(!S2.is_degenerate());
+
+  Vector_3 u = S1.target() - S1.source();
+  Vector_3 v = S2.target() - S2.source();
+  Vector_3 w = S1.source() - S2.source();
+
+  const auto a = u.dot(u);         // always >= 0
+  const auto b = u.dot(v);
+  const auto c = v.dot(v);         // always >= 0
+  const auto d = u.dot(w);
+  const auto e = v.dot(w);
+  const auto D = a*c - b*b;        // always >= 0
+  assert(D>=0);
+  const auto sc=D, sN=D, sD = D;       // sc = sN / sD, default sD = D >= 0
+  const auto tc=D, tN=D, tD = D;       // tc = tN / tD, default tD = D >= 0
+
+  bool parallel = false;
+  // compute the line parameters of the two closest points
+  if (D==0) 
+  { 
+    // the lines are almost parallel
+    parallel = true;
+    sN = 0.0;         // force using source point on segment S1
+    sD = 1.0;         // to prevent possible division by 0.0 later
+    tN = e;
+    tD = c;
+  } else
+  {
+    // get the closest points on the infinite lines
+    sN = (b*e - c*d);
+    tN = (a*e - b*d);
+    if (sN < 0.0) 
+    { 
+      // sc < 0 => the s=0 edge is visible
+      sN = 0.0;
+      tN = e;
+      tD = c;
+    } else if (sN > sD) 
+    {  // sc > 1  => the s=1 edge is visible
+      sN = sD;
+      tN = e + b;
+      tD = c;
+    }
+  }
+
+  if (tN < 0.0) 
+  {
+    // tc < 0 => the t=0 edge is visible
+    tN = 0.0;
+    // recompute sc for this edge
+    if (-d < 0.0)
+    {
+      sN = 0.0;
+    }else if (-d > a)
+    {
+      sN = sD;
+    }else 
+    {
+      sN = -d;
+      sD = a;
+    }
+  }else if (tN > tD) 
+  {
+    // tc > 1  => the t=1 edge is visible
+    tN = tD;
+    // recompute sc for this edge
+    if ((-d + b) < 0.0)
+    {
+      sN = 0;
+    }else if ((-d + b) > a)
+    {
+      sN = sD;
+    }else
+    {
+      sN = (-d +  b);
+      sD = a;
+    }
+  }
+  // finally do the division to get sc and tc
+  sc = (abs(sN) == 0 ? 0.0 : sN / sD);
+  tc = (abs(tN) == 0 ? 0.0 : tN / tD);
+
+  // get the difference of the two closest points
+  P1 = S1.source() + sc*(S1.target()-S1.source());
+  P2 = S2.source() + sc*(S2.target()-S2.source());
+  Vector_3   dP = w + (sc * u) - (tc * v);  // =  S1(sc) - S2(tc)
+  assert(dP == (P1-P2));
+
+  dst = dP.squared_length();   // return the closest distance
+  return parallel;
+}

+ 46 - 0
include/igl/copyleft/cgal/segment_segment_squared_distance.h

@@ -0,0 +1,46 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_COPYLEFT_CGAL_SEGMENT_SEGMENT_SQUARED_DISTANCE_H
+#define IGL_COPYLEFT_CGAL_SEGMENT_SEGMENT_SQUARED_DISTANCE_H
+#include "../../igl_inline.h"
+#include <CGAL/Segment_3.h>
+#include <CGAL/Point_3.h>
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // Given two segments S1 and S2 find the points on each of closest
+      // approach and the squared distance thereof.
+      // 
+      // Inputs:
+      //   S1  first segment
+      //   S2  second segment
+      // Outputs:
+      //   P1  point on S1 closest to S2
+      //   P2  point on S2 closest to S1
+      //   d  distance betwee P1 and S2
+      // Returns true if the closest approach is unique.
+      template < typename Kernel>
+      IGL_INLINE bool segment_segment_squared_distance(
+          const CGAL::Segment_3<Kernel> & S1,
+          const CGAL::Segment_3<Kernel> & S2,
+          CGAL::Point_3<Kernel> & P1,
+          CGAL::Point_3<Kernel> & P2,
+          typename Kernel::FT & d
+          );
+
+    }
+  }
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "segment_segment_squared_distance.cpp"
+#endif
+
+#endif

+ 206 - 0
include/igl/copyleft/cgal/snap_rounding.cpp

@@ -0,0 +1,206 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "snap_rounding.h"
+#include "resolve_intersections.h"
+#include "subdivide_segments.h"
+#include "../../remove_unreferenced.h"
+#include "../../unique.h"
+#include <CGAL/Segment_2.h>
+#include <CGAL/Point_2.h>
+#include <CGAL/Vector_2.h>
+#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+#include <algorithm>
+
+template <
+  typename DerivedV, 
+  typename DerivedE, 
+  typename DerivedVI, 
+  typename DerivedEI,
+  typename DerivedJ>
+IGL_INLINE void igl::copyleft::cgal::snap_rounding(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::PlainObjectBase<DerivedE> & E,
+  Eigen::PlainObjectBase<DerivedVI> & VI,
+  Eigen::PlainObjectBase<DerivedEI> & EI,
+  Eigen::PlainObjectBase<DerivedJ> & J)
+{
+  using namespace Eigen;
+  using namespace igl;
+  using namespace igl::copyleft::cgal;
+  using namespace std;
+  // Exact scalar type
+  typedef CGAL::Epeck Kernel;
+  typedef Kernel::FT EScalar;
+  typedef CGAL::Segment_2<Kernel> Segment_2;
+  typedef CGAL::Point_2<Kernel> Point_2;
+  typedef CGAL::Vector_2<Kernel> Vector_2;
+  typedef Matrix<EScalar,Dynamic,Dynamic>  MatrixXE;
+  // Convert vertex positions to exact kernel
+
+  MatrixXE VE;
+  {
+    VectorXi IM;
+    resolve_intersections(V,E,VE,EI,J,IM);
+    for_each(
+      EI.data(),
+      EI.data()+EI.size(),
+      [&IM](typename DerivedEI::Scalar& i){i=IM(i);});
+    VectorXi _;
+    remove_unreferenced( MatrixXE(VE), DerivedEI(EI), VE,EI,_);
+  }
+
+  // find all hot pixels
+  //// southwest and north east corners
+  //const RowVector2i SW(
+  //  round(VE.col(0).minCoeff()),
+  //  round(VE.col(1).minCoeff()));
+  //const RowVector2i NE(
+  //  round(VE.col(0).maxCoeff()),
+  //  round(VE.col(1).maxCoeff()));
+
+  // https://github.com/CGAL/cgal/issues/548
+  // Round an exact scalar to the nearest integer. A priori can't just round
+  // double. Suppose e=0.5+ε but double(e)<0.5
+  //
+  // Inputs:
+  //   e  exact number
+  // Outputs:
+  //   i  closest integer
+  const auto & round = [](const EScalar & e)->int
+  {
+    const double d = CGAL::to_double(e);
+    // get an integer that's near the closest int
+    int i = std::round(d);
+    EScalar di_sqr = CGAL::square((e-EScalar(i)));
+    const auto & search = [&i,&di_sqr,&e](const int dir)
+    {
+      while(true)
+      {
+        const int j = i+dir;
+        const EScalar dj_sqr = CGAL::square((e-EScalar(j)));
+        if(dj_sqr < di_sqr)
+        {
+          i = j;
+          di_sqr = dj_sqr;
+        }else
+        {
+          break;
+        }
+      }
+    };
+    // Try to increase/decrease int
+    search(1);
+    search(-1);
+    return i;
+  };
+  vector<Point_2> hot;
+  for(int i = 0;i<VE.rows();i++)
+  {
+    hot.emplace_back(round(VE(i,0)),round(VE(i,1)));
+  }
+  {
+    std::vector<size_t> _1,_2;
+    igl::unique(vector<Point_2>(hot),hot,_1,_2);
+  }
+
+  // find all segments intersecting hot pixels
+  //   split edge at closest point to hot pixel center
+  vector<vector<Point_2>>  steiner(EI.rows());
+  // initialize each segment with endpoints
+  for(int i = 0;i<EI.rows();i++)
+  {
+    steiner[i].emplace_back(VE(EI(i,0),0),VE(EI(i,0),1));
+    steiner[i].emplace_back(VE(EI(i,1),0),VE(EI(i,1),1));
+  }
+  // silly O(n²) implementation
+  for(const Point_2 & h : hot)
+  {
+    // North, East, South, West
+    Segment_2 wall[4] = 
+    {
+      {h+Vector_2(-0.5, 0.5),h+Vector_2( 0.5, 0.5)},
+      {h+Vector_2( 0.5, 0.5),h+Vector_2( 0.5,-0.5)},
+      {h+Vector_2( 0.5,-0.5),h+Vector_2(-0.5,-0.5)},
+      {h+Vector_2(-0.5,-0.5),h+Vector_2(-0.5, 0.5)}
+    };
+    // consider all segments
+    for(int i = 0;i<EI.rows();i++)
+    {
+      // endpoints
+      const Point_2 s(VE(EI(i,0),0),VE(EI(i,0),1));
+      const Point_2 d(VE(EI(i,1),0),VE(EI(i,1),1));
+      // if either end-point is in h's pixel then ignore
+      const Point_2 rs(round(s.x()),round(s.y()));
+      const Point_2 rd(round(d.x()),round(d.y()));
+      if(h == rs || h == rd)
+      {
+        continue;
+      }
+      // otherwise check for intersections with walls consider all walls
+      const Segment_2 si(s,d);
+      vector<Point_2> hits;
+      for(int j = 0;j<4;j++)
+      {
+        const Segment_2 & sj = wall[j];
+        if(CGAL::do_intersect(si,sj))
+        {
+          CGAL::Object result = CGAL::intersection(si,sj);
+          if(const Point_2 * p = CGAL::object_cast<Point_2 >(&result))
+          {
+            hits.push_back(*p);
+          }else if(const Segment_2 * s = CGAL::object_cast<Segment_2 >(&result))
+          {
+            // add both endpoints
+            hits.push_back(s->vertex(0));
+            hits.push_back(s->vertex(1));
+          }
+        }
+      }
+      if(hits.size() == 0)
+      {
+        continue;
+      }
+      // centroid of hits
+      Vector_2 cen(0,0);
+      for(const Point_2 & hit : hits)
+      {
+        cen = Vector_2(cen.x()+hit.x(), cen.y()+hit.y());
+      }
+      cen = Vector_2(cen.x()/EScalar(hits.size()),cen.y()/EScalar(hits.size()));
+      const Point_2 rcen(round(cen.x()),round(cen.y()));
+      // after all of that, don't add as a steiner unless it's going to round
+      // to h
+      if(rcen == h)
+      {
+        steiner[i].emplace_back(cen.x(),cen.y());
+      }
+    }
+  }
+  {
+    DerivedJ prevJ = J;
+    VectorXi IM;
+    subdivide_segments(MatrixXE(VE),MatrixXi(EI),steiner,VE,EI,J,IM);
+    for_each(J.data(),J.data()+J.size(),[&prevJ](typename DerivedJ::Scalar & j){j=prevJ(j);});
+    for_each(
+      EI.data(),
+      EI.data()+EI.size(),
+      [&IM](typename DerivedEI::Scalar& i){i=IM(i);});
+    VectorXi _;
+    remove_unreferenced( MatrixXE(VE), DerivedEI(EI), VE,EI,_);
+  }
+
+
+  VI.resize(VE.rows(),VE.cols());
+  for(int i = 0;i<VE.rows();i++)
+  {
+    for(int j = 0;j<VE.cols();j++)
+    {
+      VI(i,j) = round(CGAL::to_double(VE(i,j)));
+    }
+  }
+}

+ 51 - 0
include/igl/copyleft/cgal/snap_rounding.h

@@ -0,0 +1,51 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_COPYLEFT_CGAL_SNAP_ROUNDING_H
+#define IGL_COPYLEFT_CGAL_SNAP_ROUNDING_H
+
+#include "../../igl_inline.h"
+#include <Eigen/Core>
+
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // SNAP_ROUNDING Snap a list of possible intersecting segments with
+      // endpoints in any precision to _the_ integer grid.
+      //
+      // Inputs:
+      //   V  #V by 2 list of vertex positions
+      //   E  #E by 2 list of segment indices into V
+      // Outputs:
+      //   VI  #VI by 2 list of output integer vertex positions, rounded copies
+      //     of V are always the first #V vertices
+      //   EI  #EI by 2 list of segment indices into V, #EI ≥ #E
+      //   J  #EI list of indices into E revealing "parent segments"
+      template <
+        typename DerivedV, 
+        typename DerivedE, 
+        typename DerivedVI, 
+        typename DerivedEI,
+        typename DerivedJ>
+      IGL_INLINE void snap_rounding(
+        const Eigen::PlainObjectBase<DerivedV> & V,
+        const Eigen::PlainObjectBase<DerivedE> & E,
+        Eigen::PlainObjectBase<DerivedVI> & VI,
+        Eigen::PlainObjectBase<DerivedEI> & EI,
+        Eigen::PlainObjectBase<DerivedJ> & J);
+    }
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "snap_rounding.cpp"
+#endif
+
+#endif

+ 134 - 0
include/igl/copyleft/cgal/subdivide_segments.cpp

@@ -0,0 +1,134 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "subdivide_segments.h"
+#include "row_to_point.h"
+#include "../../unique.h"
+#include "../../list_to_matrix.h"
+#include "../../copyleft/cgal/assign_scalar.h"
+#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+#include <CGAL/Segment_2.h>
+#include <CGAL/Point_2.h>
+#include <algorithm>
+#include <vector>
+
+template <
+  typename DerivedV, 
+  typename DerivedE,
+  typename Kernel, 
+  typename DerivedVI, 
+  typename DerivedEI,
+  typename DerivedJ,
+  typename DerivedIM>
+IGL_INLINE void igl::copyleft::cgal::subdivide_segments(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::PlainObjectBase<DerivedE> & E,
+  const std::vector<std::vector<CGAL::Point_2<Kernel> > > & _steiner,
+  Eigen::PlainObjectBase<DerivedVI> & VI,
+  Eigen::PlainObjectBase<DerivedEI> & EI,
+  Eigen::PlainObjectBase<DerivedJ> & J,
+  Eigen::PlainObjectBase<DerivedIM> & IM)
+{
+  using namespace Eigen;
+  using namespace igl;
+  using namespace std;
+
+  // Exact scalar type
+  typedef Kernel K;
+  typedef typename Kernel::FT EScalar;
+  typedef CGAL::Segment_2<Kernel> Segment_2;
+  typedef CGAL::Point_2<Kernel> Point_2;
+  typedef Matrix<EScalar,Dynamic,Dynamic>  MatrixXE;
+
+  // non-const copy
+  std::vector<std::vector<CGAL::Point_2<Kernel> > > steiner = _steiner;
+
+  // Convert vertex positions to exact kernel
+  MatrixXE VE(V.rows(),V.cols());
+  for(int i = 0;i<V.rows();i++)
+  {
+    for(int j = 0;j<V.cols();j++)
+    {
+      VE(i,j) = V(i,j);
+    }
+  }
+
+  // number of original vertices
+  const int n = V.rows();
+  // number of original segments
+  const int m = E.rows();
+  // now steiner contains lists of points (unsorted) for each edge. Sort them
+  // and count total number of vertices and edges
+  int ni = 0;
+  int mi = 0;
+  // new steiner points
+  std::vector<Point_2> S;
+  std::vector<std::vector<typename DerivedE::Scalar> > vEI;
+  std::vector<typename DerivedJ::Scalar> vJ;
+  for(int i = 0;i<m;i++)
+  {
+    {
+      const Point_2 s = row_to_point<K>(VE,E(i,0));
+      std::sort(
+        steiner[i].begin(),
+        steiner[i].end(),
+        [&s](const Point_2 & A, const Point_2 & B)->bool
+        {
+          return (A-s).squared_length() < (B-s).squared_length();
+        });
+    }
+    // remove duplicates
+    steiner[i].erase(
+      std::unique(steiner[i].begin(), steiner[i].end()), 
+      steiner[i].end());
+    {
+      int s = E(i,0);
+      // legs to each steiner in order
+      for(int j = 1;j<steiner[i].size()-1;j++)
+      {
+        int d = n+S.size();
+        S.push_back(steiner[i][j]);
+        vEI.push_back({s,d});
+        vJ.push_back(i);
+        s = d;
+      }
+      // don't forget last (which might only) leg
+      vEI.push_back({s,E(i,1)});
+      vJ.push_back(i);
+    }
+  }
+  // potentially unnecessary copying ...
+  VI.resize(n+S.size(),2);
+  for(int i = 0;i<V.rows();i++)
+  {
+    for(int j = 0;j<V.cols();j++)
+    {
+      assign_scalar(V(i,j),VI(i,j));
+    }
+  }
+  for(int i = 0;i<S.size();i++)
+  {
+    assign_scalar(S[i].x(),VI(n+i,0));
+    assign_scalar(S[i].y(),VI(n+i,1));
+  }
+  list_to_matrix(vEI,EI);
+  list_to_matrix(vJ,J);
+  {
+    // Find unique mapping
+    std::vector<Point_2> vVES,_1;
+    for(int i = 0;i<n;i++)
+    {
+      vVES.push_back(row_to_point<K>(VE,i));
+    }
+    vVES.insert(vVES.end(),S.begin(),S.end());
+    std::vector<size_t> vA,vIM;
+    igl::unique(vVES,_1,vA,vIM);
+    // Push indices back into vVES
+    for_each(vIM.data(),vIM.data()+vIM.size(),[&vA](size_t & i){i=vA[i];});
+    list_to_matrix(vIM,IM);
+  }
+}

+ 56 - 0
include/igl/copyleft/cgal/subdivide_segments.h

@@ -0,0 +1,56 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_COPYLEFT_CGAL_SUBDIVIDE_SEGMENTS_H
+#define IGL_COPYLEFT_CGAL_SUBDIVIDE_SEGMENTS_H
+#include "../../igl_inline.h"
+#include <Eigen/Core>
+#include <CGAL/Segment_2.h>
+#include <CGAL/Point_2.h>
+#include <vector>
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // Insert steiner points to subdivide a given set of line segments
+      // 
+      // Inputs:
+      //   V  #V by 2 list of vertex positions
+      //   E  #E by 2 list of segment indices into V
+      //   steiner  #E list of lists of unsorted steiner points (including
+      //     endpoints) along the #E original segments
+      // Outputs:
+      //   VI  #VI by 2 list of output vertex positions, copies of V are always
+      //     the first #V vertices
+      //   EI  #EI by 2 list of segment indices into V, #EI ≥ #E
+      //   J  #EI list of indices into E revealing "parent segments"
+      //   IM  #VI list of indices into VV of unique vertices.
+      template <
+        typename DerivedV, 
+        typename DerivedE,
+        typename Kernel, 
+        typename DerivedVI, 
+        typename DerivedEI,
+        typename DerivedJ,
+        typename DerivedIM>
+      IGL_INLINE void subdivide_segments(
+        const Eigen::PlainObjectBase<DerivedV> & V,
+        const Eigen::PlainObjectBase<DerivedE> & E,
+        const std::vector<std::vector<CGAL::Point_2<Kernel> > > & steiner,
+        Eigen::PlainObjectBase<DerivedVI> & VI,
+        Eigen::PlainObjectBase<DerivedEI> & EI,
+        Eigen::PlainObjectBase<DerivedJ> & J,
+        Eigen::PlainObjectBase<DerivedIM> & IM);
+    }
+  }
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "subdivide_segments.cpp"
+#endif
+#endif

+ 114 - 0
include/igl/copyleft/cgal/triangle_triangle_squared_distance.cpp

@@ -0,0 +1,114 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "triangle_triangle_squared_distance.h"
+#include "point_triangle_squared_distance.h"
+#include <CGAL/Vector_3.h>
+#include <CGAL/Segment_3.h>
+#include <CGAL/intersections.h>
+
+template < typename Kernel>
+IGL_INLINE bool igl::copyleft::cgal::triangle_triangle_squared_distance(
+  const CGAL::Triangle_3<Kernel> & T1,
+  const CGAL::Triangle_3<Kernel> & T2,
+  CGAL::Point_3<Kernel> & P1,
+  CGAL::Point_3<Kernel> & P2,
+  typename Kernel::FT & d)
+{
+  typedef CGAL::Point_3<Kernel> Point_3;
+  typedef CGAL::Vector_3<Kernel> Vector_3;
+  typedef CGAL::Triangle_3<Kernel> Triangle_3;
+  typedef CGAL::Segment_3<Kernel> Segment_3;
+  typedef typename Kernel::FT EScalar;
+  assert(!T1.is_degenerate());
+  assert(!T2.is_degenerate());
+
+  bool unique = true;
+  if(CGAL::do_intersect(T1,T2))
+  {
+    // intersecting triangles have zero (squared) distance
+    CGAL::Object result = CGAL::intersection(T1,T2);
+    // Some point on the intersection result
+    CGAL::Point_3<Kernel> Q;
+    if(const Point_3 * p = CGAL::object_cast<Point_3 >(&result))
+    {
+      Q = *p;
+    }else if(const Segment_3 * s = CGAL::object_cast<Segment_3 >(&result))
+    {
+      unique = false;
+      Q = s->source();
+    }else if(const Triangle_3 *itri = CGAL::object_cast<Triangle_3 >(&result))
+    {
+      Q = s->vertex(0);
+      unique = false;
+    }else if(const std::vector<Point_3 > *polyp = 
+      CGAL::object_cast< std::vector<Point_3 > >(&result))
+    {
+      assert(polyp->size() > 0 && "intersection poly should not be empty");
+      Q = polyp[0];
+      unique = false;
+    }else
+    {
+      assert(false && "Unknown intersection result");
+    }
+    P1 = Q;
+    P2 = Q;
+    d = 0;
+    return unique;
+  }
+  // triangles do not intersect: the points of closest approach must be on the
+  // boundary of one of the triangles
+  d = std::numeric_limits<double>::infinity();
+  const auto & vertices_face = [&unique](
+    const Triangle_3 & T1,
+    const Triangle_3 & T2,
+    Point_3 & P1,
+    Point_3 & P2,
+    EScalar & d)
+  {
+    for(int i = 0;i<3;i++)
+    {
+      const Point_3 vi = T1.vertex(i);
+      Point_3 P2i;
+      EScalar di;
+      point_triangle_squared_distance(vi,T2,P2i,di);
+      if(di<d)
+      {
+        d = di;
+        P1 = vi;
+        P2 = P2i;
+        unique = true;
+      }else if(d == di)
+      {
+        // edge of T1 floating parallel above T2
+        unique = false;
+      }
+    }
+  };
+  vertices_face(T1,T2,P1,P2,d);
+  vertices_face(T2,T1,P1,P2,d);
+  for(int i = 0;i<3;i++)
+  {
+    const Segment_3 s1( T1.vertex(i+1), T1.vertex(i+2));
+    for(int j = 0;j<3;j++)
+    {
+      const Segment_3 s2( T2.vertex(i+1), T2.vertex(i+2));
+      Point_3 P1ij;
+      Point_3 P2ij;
+      EScalar dij;
+      bool uniqueij = segment_segment_squared_distance(s1,s2,P1ij,P2ij,dij);
+      if(dij < d)
+      {
+        P1 = P1ij;
+        P2 = P2ij;
+        d = dij;
+        unique = uniqueij;
+      }
+    }
+  }
+  return unique;
+}

+ 45 - 0
include/igl/copyleft/cgal/triangle_triangle_squared_distance.h

@@ -0,0 +1,45 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_COPYLEFT_CGAL_TRIANGLE_TRIANGLE_SQUARED_DISTANCE_H
+#define IGL_COPYLEFT_CGAL_TRIANGLE_TRIANGLE_SQUARED_DISTANCE_H
+#include "../../igl_inline.h"
+#include <CGAL/Triangle_3.h>
+#include <CGAL/Point_3.h>
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // Given two triangles T1 and T2 find the points on each of closest
+      // approach and the squared distance thereof.
+      // 
+      // Inputs:
+      //   T1  first triangle
+      //   T2  second triangle
+      // Outputs:
+      //   P1  point on T1 closest to T2
+      //   P2  point on T2 closest to T1
+      //   d  distance betwee P1 and T2
+      // Returns true if the closest approach is unique.
+      template < typename Kernel>
+      IGL_INLINE bool triangle_triangle_squared_distance(
+        const CGAL::Triangle_3<Kernel> & T1,
+        const CGAL::Triangle_3<Kernel> & T2,
+        CGAL::Point_3<Kernel> & P1,
+        CGAL::Point_3<Kernel> & P2,
+        typename Kernel::FT & d);
+    }
+  }
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "triangle_triangle_squared_distance.cpp"
+#endif
+
+#endif
+

+ 96 - 0
include/igl/ismember.cpp

@@ -0,0 +1,96 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "ismember.h"
+#include "colon.h"
+#include "list_to_matrix.h"
+#include "sort.h"
+#include "unique.h"
+
+template <
+  typename DerivedA,
+  typename DerivedB,
+  typename DerivedIA,
+  typename DerivedLOCB>
+IGL_INLINE void igl::ismember(
+  const Eigen::PlainObjectBase<DerivedA> & A,
+  const Eigen::PlainObjectBase<DerivedB> & B,
+  Eigen::PlainObjectBase<DerivedIA> & IA,
+  Eigen::PlainObjectBase<DerivedLOCB> & LOCB)
+{
+  using namespace Eigen;
+  using namespace std;
+  IA.resize(A.rows(),A.cols());
+  IA.setConstant(false);
+  LOCB.resize(A.rows(),A.cols());
+  LOCB.setConstant(-1);
+  // boring base cases
+  if(A.size() == 0)
+  {
+    return;
+  }
+  if(B.size() == 0)
+  {
+    return;
+  }
+
+  // Get rid of any duplicates
+  typedef Matrix<typename DerivedA::Scalar,Dynamic,1> VectorA;
+  typedef Matrix<typename DerivedB::Scalar,Dynamic,1> VectorB;
+  const VectorA vA(Eigen::Map<const VectorA>(A.data(), A.cols()*A.rows(),1));
+  const VectorB vB(Eigen::Map<const VectorB>(B.data(), B.cols()*B.rows(),1));
+  VectorA uA;
+  VectorB uB;
+  Eigen::Matrix<typename DerivedA::Index,Dynamic,1> uIA,uIuA,uIB,uIuB;
+  unique(vA,uA,uIA,uIuA);
+  unique(vB,uB,uIB,uIuB);
+  // Sort both
+  VectorA sA;
+  VectorB sB;
+  Eigen::Matrix<typename DerivedA::Index,Dynamic,1> sIA,sIB;
+  sort(uA,1,true,sA,sIA);
+  sort(uB,1,true,sB,sIB);
+
+  Eigen::Matrix<bool,Eigen::Dynamic,1> uF = 
+    Eigen::Matrix<bool,Eigen::Dynamic,1>::Zero(sA.size(),1);
+  Eigen::Matrix<typename DerivedLOCB::Scalar, Eigen::Dynamic,1> uLOCB =
+    Eigen::Matrix<typename DerivedLOCB::Scalar,Eigen::Dynamic,1>::
+    Constant(sA.size(),1,-1);
+  {
+    int bi = 0;
+    // loop over sA
+    bool past = false;
+    for(int a = 0;a<sA.size();a++)
+    {
+      while(!past && sA(a)>sB(bi))
+      {
+        bi++;
+        past = bi>=sB.size();
+      }
+      if(!past && sA(a)==sB(bi))
+      {
+        uF(sIA(a)) = true;
+        uLOCB(sIA(a)) = uIB(sIB(bi));
+      }
+    }
+  }
+
+  Map< Matrix<typename DerivedIA::Scalar,Dynamic,1> > 
+    vIA(IA.data(),IA.cols()*IA.rows(),1);
+  Map< Matrix<typename DerivedLOCB::Scalar,Dynamic,1> > 
+    vLOCB(LOCB.data(),LOCB.cols()*LOCB.rows(),1);
+  for(int a = 0;a<A.size();a++)
+  {
+    vIA(a) = uF(uIuA(a));
+    vLOCB(a) = uLOCB(uIuA(a));
+  }
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template specialization
+template void igl::ismember<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<bool, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+#endif

+ 41 - 0
include/igl/ismember.h

@@ -0,0 +1,41 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_ISMEMBER_H
+#define IGL_ISMEMBER_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+namespace igl
+{
+  // Determine if elements of A exist in elements of B
+  //
+  // Inputs:
+  //   A  ma by na matrix
+  //   B  mb by nb matrix
+  // Outputs:
+  //   IA  ma by na matrix of flags whether corresponding element of A exists in
+  //     B
+  //   LOCB  ma by na matrix of indices in B locating matching element (-1 if
+  //     not found), indices assume column major ordering
+  //
+  template <
+    typename DerivedA,
+    typename DerivedB,
+    typename DerivedIA,
+    typename DerivedLOCB>
+  IGL_INLINE void ismember(
+    const Eigen::PlainObjectBase<DerivedA> & A,
+    const Eigen::PlainObjectBase<DerivedB> & B,
+    Eigen::PlainObjectBase<DerivedIA> & IA,
+    Eigen::PlainObjectBase<DerivedLOCB> & LOCB);
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "ismember.cpp"
+#endif
+#endif
+

+ 1 - 0
include/igl/list_to_matrix.cpp

@@ -151,6 +151,7 @@ template bool igl::list_to_matrix<double, Eigen::Matrix<double, -1, -1, 0, -1, -
 template bool igl::list_to_matrix<int, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::vector<int, std::allocator<int> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template bool igl::list_to_matrix<unsigned long, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::vector<unsigned long, std::allocator<unsigned long> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template bool igl::list_to_matrix<int, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
+template bool igl::list_to_matrix<unsigned long, Eigen::Matrix<long, -1, 1, 0, -1, 1> >(std::vector<unsigned long, std::allocator<unsigned long> > const&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&);
 
 #ifdef WIN32
 template bool igl::list_to_matrix<unsigned long long,class Eigen::Matrix<int,-1,1,0,-1,1> >(class std::vector<unsigned long long,class std::allocator<unsigned long long> > const &,class Eigen::PlainObjectBase<class Eigen::Matrix<int,-1,1,0,-1,1> > &);

+ 146 - 125
include/igl/loop.cpp

@@ -14,139 +14,160 @@
 
 #include <vector>
 
-namespace igl
+template <
+  typename DerivedF,
+  typename SType,
+  typename DerivedNF>
+IGL_INLINE void igl::loop(
+  const int n_verts,
+  const Eigen::PlainObjectBase<DerivedF> & F,
+  Eigen::SparseMatrix<SType>& S,
+  Eigen::PlainObjectBase<DerivedNF> & NF)
 {
-    
-    IGL_INLINE void loop(const int n_verts,
-                         const Eigen::MatrixXi& F,
-                         Eigen::SparseMatrix<double>& S,
-                         Eigen::MatrixXi& newF)
+  typedef Eigen::SparseMatrix<SType> SparseMat;
+  typedef Eigen::Triplet<SType> Triplet_t;
+  
+  //Ref. https://graphics.stanford.edu/~mdfisher/subdivision.html
+  //Heavily borrowing from igl::upsample
+  
+  DerivedF FF, FFi;
+  triangle_triangle_adjacency(F, FF, FFi);
+  std::vector<std::vector<typename DerivedF::Scalar>> adjacencyList;
+  adjacency_list(F, adjacencyList, true);
+  
+  //Compute the number and positions of the vertices to insert (on edges)
+  Eigen::MatrixXi NI = Eigen::MatrixXi::Constant(FF.rows(), FF.cols(), -1);
+  Eigen::MatrixXi NIdoubles = Eigen::MatrixXi::Zero(FF.rows(), FF.cols());
+  Eigen::VectorXi vertIsOnBdry = Eigen::VectorXi::Zero(n_verts);
+  int counter = 0;
+  for(int i=0; i<FF.rows(); ++i)
+  {
+    for(int j=0; j<3; ++j)
     {
-        
-        typedef Eigen::SparseMatrix<double> SparseMat;
-        typedef Eigen::Triplet<double> Triplet_t;
-        
-        //Ref. https://graphics.stanford.edu/~mdfisher/subdivision.html
-        //Heavily borrowing from igl::upsample
-        
-        Eigen::MatrixXi FF, FFi;
-        triangle_triangle_adjacency(F, FF, FFi);
-        std::vector<std::vector<int>> adjacencyList;
-        adjacency_list(F, adjacencyList, true);
-        
-        //Compute the number and positions of the vertices to insert (on edges)
-        Eigen::MatrixXi NI = Eigen::MatrixXi::Constant(FF.rows(), FF.cols(), -1);
-        Eigen::MatrixXi NIdoubles = Eigen::MatrixXi::Zero(FF.rows(), FF.cols());
-        Eigen::VectorXi vertIsOnBdry = Eigen::VectorXi::Zero(n_verts);
-        int counter = 0;
-        for(int i=0; i<FF.rows(); ++i)
+      if(NI(i,j) == -1)
+      {
+        NI(i,j) = counter;
+        NIdoubles(i,j) = 0;
+        if (FF(i,j) != -1) 
         {
-            for(int j=0; j<3; ++j)
-            {
-                if(NI(i,j) == -1)
-                {
-                    NI(i,j) = counter;
-                    NIdoubles(i,j) = 0;
-                    if (FF(i,j) != -1) {
-                        //If it is not a boundary
-                        NI(FF(i,j), FFi(i,j)) = counter;
-                        NIdoubles(i,j) = 1;
-                    } else {
-                        //Mark boundary vertices for later
-                        vertIsOnBdry(F(i,j)) = 1;
-                        vertIsOnBdry(F(i,(j+1)%3)) = 1;
-                    }
-                    ++counter;
-                }
-            }
-        }
-        
-        const int& n_odd = n_verts;
-        const int& n_even = counter;
-        const int n_newverts = n_odd + n_even;
-        
-        //Construct vertex positions
-        std::vector<Triplet_t> tripletList;
-        for(int i=0; i<n_odd; ++i) {
-            //Old vertices
-            const std::vector<int>& localAdjList = adjacencyList[i];
-            if(vertIsOnBdry(i)==1) {
-                //Boundary vertex
-                tripletList.emplace_back(i, localAdjList.front(), 1./8.);
-                tripletList.emplace_back(i, localAdjList.back(), 1./8.);
-                tripletList.emplace_back(i, i, 3./4.);
-            } else {
-                const int n = localAdjList.size();
-                const double dn = n;
-                double beta;
-                if(n==3)
-                    beta = 3./16.;
-                else
-                    beta = 3./8./dn;
-                for(int j=0; j<n; ++j)
-                    tripletList.emplace_back(i, localAdjList[j], beta);
-                tripletList.emplace_back(i, i, 1.-dn*beta);
-            }
-        }
-        for(int i=0; i<FF.rows(); ++i) {
-            //New vertices
-            for(int j=0; j<3; ++j) {
-                if(NIdoubles(i,j)==0) {
-                    if(FF(i,j)==-1) {
-                        //Boundary vertex
-                        tripletList.emplace_back(NI(i,j) + n_odd, F(i,j), 1./2.);
-                        tripletList.emplace_back(NI(i,j) + n_odd, F(i, (j+1)%3), 1./2.);
-                    } else {
-                        tripletList.emplace_back(NI(i,j) + n_odd, F(i,j), 3./8.);
-                        tripletList.emplace_back(NI(i,j) + n_odd, F(i, (j+1)%3), 3./8.);
-                        tripletList.emplace_back(NI(i,j) + n_odd, F(i, (j+2)%3), 1./8.);
-                        tripletList.emplace_back(NI(i,j) + n_odd, F(FF(i,j), (FFi(i,j)+2)%3), 1./8.);
-                    }
-                }
-            }
-        }
-        S.resize(n_newverts, n_verts);
-        S.setFromTriplets(tripletList.begin(), tripletList.end());
-        
-        // Build the new topology (Every face is replaced by four)
-        newF.resize(F.rows()*4, 3);
-        for(int i=0; i<F.rows();++i)
+          //If it is not a boundary
+          NI(FF(i,j), FFi(i,j)) = counter;
+          NIdoubles(i,j) = 1;
+        } else 
         {
-            Eigen::VectorXi VI(6);
-            VI << F(i,0), F(i,1), F(i,2), NI(i,0) + n_odd, NI(i,1) + n_odd, NI(i,2) + n_odd;
-            
-            Eigen::VectorXi f0(3), f1(3), f2(3), f3(3);
-            f0 << VI(0), VI(3), VI(5);
-            f1 << VI(1), VI(4), VI(3);
-            f2 << VI(3), VI(4), VI(5);
-            f3 << VI(4), VI(2), VI(5);
-            
-            newF.row((i*4)+0) = f0;
-            newF.row((i*4)+1) = f1;
-            newF.row((i*4)+2) = f2;
-            newF.row((i*4)+3) = f3;
+          //Mark boundary vertices for later
+          vertIsOnBdry(F(i,j)) = 1;
+          vertIsOnBdry(F(i,(j+1)%3)) = 1;
         }
-        
+        ++counter;
+      }
     }
-    
-    
-    IGL_INLINE void loop(const Eigen::MatrixXd& V,
-                         const Eigen::MatrixXi& F,
-                         Eigen::MatrixXd& newV,
-                         Eigen::MatrixXi& newF,
-                         const int number_of_subdivs)
+  }
+  
+  const int& n_odd = n_verts;
+  const int& n_even = counter;
+  const int n_newverts = n_odd + n_even;
+  
+  //Construct vertex positions
+  std::vector<Triplet_t> tripletList;
+  for(int i=0; i<n_odd; ++i) 
+  {
+    //Old vertices
+    const std::vector<int>& localAdjList = adjacencyList[i];
+    if(vertIsOnBdry(i)==1) 
+    {
+      //Boundary vertex
+      tripletList.emplace_back(i, localAdjList.front(), 1./8.);
+      tripletList.emplace_back(i, localAdjList.back(), 1./8.);
+      tripletList.emplace_back(i, i, 3./4.);
+    } else 
+    {
+      const int n = localAdjList.size();
+      const SType dn = n;
+      SType beta;
+      if(n==3)
+      {
+        beta = 3./16.;
+      } else
+      {
+        beta = 3./8./dn;
+      }
+      for(int j=0; j<n; ++j)
+      {
+        tripletList.emplace_back(i, localAdjList[j], beta);
+      }
+      tripletList.emplace_back(i, i, 1.-dn*beta);
+    }
+  }
+  for(int i=0; i<FF.rows(); ++i) 
+  {
+    //New vertices
+    for(int j=0; j<3; ++j) 
     {
-        typedef Eigen::SparseMatrix<double> SparseMat;
-        typedef Eigen::Triplet<double> Triplet_t;
-        
-        newV = V;
-        newF = F;
-        for(int i=0; i<number_of_subdivs; ++i) {
-            Eigen::MatrixXi tempF = newF;
-            SparseMat S;
-            loop(newV.rows(), tempF, S, newF);
-            newV = S*newV;
+      if(NIdoubles(i,j)==0) 
+      {
+        if(FF(i,j)==-1) 
+        {
+          //Boundary vertex
+          tripletList.emplace_back(NI(i,j) + n_odd, F(i,j), 1./2.);
+          tripletList.emplace_back(NI(i,j) + n_odd, F(i, (j+1)%3), 1./2.);
+        } else 
+        {
+          tripletList.emplace_back(NI(i,j) + n_odd, F(i,j), 3./8.);
+          tripletList.emplace_back(NI(i,j) + n_odd, F(i, (j+1)%3), 3./8.);
+          tripletList.emplace_back(NI(i,j) + n_odd, F(i, (j+2)%3), 1./8.);
+          tripletList.emplace_back(NI(i,j) + n_odd, F(FF(i,j), (FFi(i,j)+2)%3), 1./8.);
         }
+      }
     }
+  }
+  S.resize(n_newverts, n_verts);
+  S.setFromTriplets(tripletList.begin(), tripletList.end());
+  
+  // Build the new topology (Every face is replaced by four)
+  NF.resize(F.rows()*4, 3);
+  for(int i=0; i<F.rows();++i)
+  {
+    Eigen::VectorXi VI(6);
+    VI << F(i,0), F(i,1), F(i,2), NI(i,0) + n_odd, NI(i,1) + n_odd, NI(i,2) + n_odd;
+    
+    Eigen::VectorXi f0(3), f1(3), f2(3), f3(3);
+    f0 << VI(0), VI(3), VI(5);
+    f1 << VI(1), VI(4), VI(3);
+    f2 << VI(3), VI(4), VI(5);
+    f3 << VI(4), VI(2), VI(5);
     
+    NF.row((i*4)+0) = f0;
+    NF.row((i*4)+1) = f1;
+    NF.row((i*4)+2) = f2;
+    NF.row((i*4)+3) = f3;
+  }
 }
+
+template <
+  typename DerivedV, 
+  typename DerivedF,
+  typename DerivedNV,
+  typename DerivedNF>
+IGL_INLINE void igl::loop(
+  const Eigen::PlainObjectBase<DerivedV>& V,
+  const Eigen::PlainObjectBase<DerivedF>& F,
+  Eigen::PlainObjectBase<DerivedNV>& NV,
+  Eigen::PlainObjectBase<DerivedNF>& NF,
+  const int number_of_subdivs)
+{
+  NV = V;
+  NF = F;
+  for(int i=0; i<number_of_subdivs; ++i) 
+  {
+    DerivedNF tempF = NF;
+    Eigen::SparseMatrix<typename DerivedV::Scalar> S;
+    loop(NV.rows(), tempF, S, NF);
+    // This .eval is super important
+    NV = (S*NV).eval();
+  }
+}
+
+#ifdef IGL_STATIC_LIBRARY
+template void igl::loop<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::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> >&, int);
+#endif

+ 40 - 29
include/igl/loop.h

@@ -15,38 +15,49 @@
 
 namespace igl
 {
-    // LOOP Given the triangle mesh [V, F], where n_verts = V.rows(), computes newV and a sparse matrix S s.t. [newV, newF] is the subdivided mesh where newV = S*V.
-    //
-    // Inputs:
-    //  n_verts an integer (number of mesh vertices)
-    //  F an m by 3 matrix of integers of triangle faces
-    // Outputs:
-    //  S a sparse matrix (will become the subdivision matrix)
-    //  newF a matrix containing the new faces
-    IGL_INLINE void loop(const int n_verts,
-                         const Eigen::MatrixXi& F,
-                         Eigen::SparseMatrix<double>& S,
-                         Eigen::MatrixXi& newF);
-    
-    // LOOP Given the triangle mesh [V, F], computes number_of_subdivs steps of loop subdivision and outputs the new mesh [newV, newF]
-    //
-    // Inputs:
-    //  V an n by 3 matrix of vertices
-    //  F an m by 3 matrix of integers of triangle faces
-    //  number_of_subdivs an integer that specifies how many subdivision steps to do
-    // Outputs:
-    //  newV a matrix containing the new vertices
-    //  newF a matrix containing the new faces
-    IGL_INLINE void loop(const Eigen::MatrixXd& V,
-                         const Eigen::MatrixXi& F,
-                         Eigen::MatrixXd& newV,
-                         Eigen::MatrixXi& newF,
-                         const int number_of_subdivs = 1);
-    
+  // LOOP Given the triangle mesh [V, F], where n_verts = V.rows(), computes
+  // newV and a sparse matrix S s.t. [newV, newF] is the subdivided mesh where
+  // newV = S*V.
+  //
+  // Inputs:
+  //   n_verts  an integer (number of mesh vertices)
+  //   F  an m by 3 matrix of integers of triangle faces
+  // Outputs:
+  //   S  a sparse matrix (will become the subdivision matrix)
+  //   newF  a matrix containing the new faces
+  template <
+    typename DerivedF,
+    typename SType,
+    typename DerivedNF>
+  IGL_INLINE void loop(
+    const int n_verts,
+    const Eigen::PlainObjectBase<DerivedF> & F,
+    Eigen::SparseMatrix<SType>& S,
+    Eigen::PlainObjectBase<DerivedNF> & NF);
+  // LOOP Given the triangle mesh [V, F], computes number_of_subdivs steps of loop subdivision and outputs the new mesh [newV, newF]
+  //
+  // Inputs:
+  //  V an n by 3 matrix of vertices
+  //  F an m by 3 matrix of integers of triangle faces
+  //  number_of_subdivs an integer that specifies how many subdivision steps to do
+  // Outputs:
+  //  NV a matrix containing the new vertices
+  //  NF a matrix containing the new faces
+  template <
+    typename DerivedV, 
+    typename DerivedF,
+    typename DerivedNV,
+    typename DerivedNF>
+  IGL_INLINE void loop(
+    const Eigen::PlainObjectBase<DerivedV>& V,
+    const Eigen::PlainObjectBase<DerivedF>& F,
+    Eigen::PlainObjectBase<DerivedNV>& NV,
+    Eigen::PlainObjectBase<DerivedNF>& NF,
+    const int number_of_subdivs = 1);
 }
 
 #ifndef IGL_STATIC_LIBRARY
-#include "loop.cpp"
+#  include "loop.cpp"
 #endif
 
 #endif

+ 4 - 1
include/igl/serialize.h

@@ -187,7 +187,10 @@ namespace igl
  
   public:
  
-    // Override this function to add your member variables which should be serialized
+    // You **MUST** Override this function to add your member variables which
+    // should be serialized
+    //
+    // http://stackoverflow.com/a/6634382/148668
     virtual void InitSerialization() = 0;
  
     // Following functions can be overridden to handle the specific events.

+ 1 - 0
include/igl/sort.cpp

@@ -338,4 +338,5 @@ template void igl::sort<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<doub
 template void igl::sort<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::sort<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<int, -1, 1, 0, -1, 1> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 
+template void igl::sort<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<long, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&);
 #endif

+ 1 - 0
include/igl/unique.cpp

@@ -279,6 +279,7 @@ template void igl::unique<double>(std::vector<double, std::allocator<double> > c
 template void igl::unique<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::unique<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::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, 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::unique_rows<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<int, -1, -1, 0, -1, -1> > const&, 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::unique<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<long, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&);
 
 #ifdef WIN32
 template void __cdecl igl::unique_rows<class Eigen::Matrix<int, -1, -1, 0, -1, -1>, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1> >(class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1> > const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1> > &, class Eigen::PlainObjectBase<class Eigen::Matrix<__int64, -1, 1, 0, -1, 1> > &, class Eigen::PlainObjectBase<class Eigen::Matrix<__int64, -1, 1, 0, -1, 1> > &);

+ 58 - 24
include/igl/upsample.cpp

@@ -11,24 +11,21 @@
 
 
 template <
-  typename DerivedV,
   typename DerivedF,
-  typename DerivedNV,
+  typename SType,
   typename DerivedNF>
 IGL_INLINE void igl::upsample(
-  const Eigen::PlainObjectBase<DerivedV>& V,
+  const int n_verts,
   const Eigen::PlainObjectBase<DerivedF>& F,
-  Eigen::PlainObjectBase<DerivedNV>& NV,
+  Eigen::SparseMatrix<SType>& S,
   Eigen::PlainObjectBase<DerivedNF>& NF)
 {
-  // Use "in place" wrapper instead
-  assert(&V != &NV);
-  assert(&F != &NF);
   using namespace std;
   using namespace Eigen;
 
-  Eigen::Matrix<
-    typename DerivedF::Scalar,Eigen::Dynamic,Eigen::Dynamic>
+  typedef Eigen::Triplet<SType> Triplet_t;
+
+  Eigen::Matrix< typename DerivedF::Scalar,Eigen::Dynamic,Eigen::Dynamic>
     FF,FFi;
   triangle_triangle_adjacency(F,FF,FFi);
 
@@ -36,6 +33,7 @@ IGL_INLINE void igl::upsample(
 
   // Compute the number and positions of the vertices to insert (on edges)
   Eigen::MatrixXi NI = Eigen::MatrixXi::Constant(FF.rows(),FF.cols(),-1);
+  Eigen::MatrixXi NIdoubles = Eigen::MatrixXi::Zero(FF.rows(), FF.cols());
   int counter = 0;
 
   for(int i=0;i<FF.rows();++i)
@@ -45,33 +43,45 @@ IGL_INLINE void igl::upsample(
       if(NI(i,j) == -1)
       {
         NI(i,j) = counter;
-        if (FF(i,j) != -1) // If it is not a border
-          NI(FF(i,j),FFi(i,j)) = counter;
+        NIdoubles(i,j) = 0;
+        if (FF(i,j) != -1) {
+          //If it is not a boundary
+          NI(FF(i,j), FFi(i,j)) = counter;
+          NIdoubles(i,j) = 1;
+        }
         ++counter;
       }
     }
   }
 
-  int n_odd = V.rows();
-  int n_even = counter;
+  const int& n_odd = n_verts;
+  const int& n_even = counter;
+  const int n_newverts = n_odd + n_even;
 
-  // Preallocate NV and NF
-  NV.resize(V.rows()+n_even,V.cols());
-  NF.resize(F.rows()*4,3);
+  //Construct vertex positions
+  std::vector<Triplet_t> tripletList;
 
   // Fill the odd vertices position
-  NV.block(0,0,V.rows(),V.cols()) = V;
+  for (int i=0; i<n_odd; ++i)
+  {
+    tripletList.emplace_back(i, i, 1.);
+  }
 
-  // Fill the even vertices position
   for(int i=0;i<FF.rows();++i)
   {
     for(int j=0;j<3;++j)
     {
-      NV.row(NI(i,j) + n_odd) = 0.5 * V.row(F(i,j)) + 0.5 * V.row(F(i,(j+1)%3));
+      if(NIdoubles(i,j)==0) {
+        tripletList.emplace_back(NI(i,j) + n_odd, F(i,j), 1./2.);
+        tripletList.emplace_back(NI(i,j) + n_odd, F(i,(j+1)%3), 1./2.);
+      }
     }
   }
+  S.resize(n_newverts, n_verts);
+  S.setFromTriplets(tripletList.begin(), tripletList.end());
 
   // Build the new topology (Every face is replaced by four)
+  NF.resize(F.rows()*4,3);
   for(int i=0; i<F.rows();++i)
   {
     VectorXi VI(6);
@@ -88,7 +98,30 @@ IGL_INLINE void igl::upsample(
     NF.row((i*4)+2) = f2;
     NF.row((i*4)+3) = f3;
   }
+}
 
+template <
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedNV,
+  typename DerivedNF>
+IGL_INLINE void igl::upsample(
+  const Eigen::PlainObjectBase<DerivedV>& V,
+  const Eigen::PlainObjectBase<DerivedF>& F,
+  Eigen::PlainObjectBase<DerivedNV>& NV,
+  Eigen::PlainObjectBase<DerivedNF>& NF,
+  const int number_of_subdivs)
+{
+  NV = V;
+  NF = F;
+  for(int i=0; i<number_of_subdivs; ++i) 
+  {
+    DerivedNF tempF = NF;
+    Eigen::SparseMatrix<typename DerivedV::Scalar >S;
+    upsample(NV.rows(), tempF, S, NF);
+    // This .eval is super important
+    NV = (S*NV).eval();
+  }
 }
 
 template <
@@ -96,16 +129,17 @@ template <
   typename MatF>
 IGL_INLINE void igl::upsample(
   MatV& V,
-  MatF& F)
+  MatF& F,
+  const int number_of_subdivs)
 {
   const MatV V_copy = V;
   const MatF F_copy = F;
-  return upsample(V_copy,F_copy,V,F);
+  return upsample(V_copy,F_copy,V,F,number_of_subdivs);
 }
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
-// generated by autoexplicit.sh
-template void igl::upsample<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
-template void igl::upsample<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>&);
+template void igl::upsample<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::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> >&, int);
+template void igl::upsample<Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<double, 0, int>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template void igl::upsample<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>&, int);
 #endif

+ 25 - 2
include/igl/upsample.h

@@ -10,11 +10,31 @@
 #include "igl_inline.h"
 
 #include <Eigen/Core>
+#include <Eigen/Sparse>
 
 // History:
 //  changed templates from generic matrices to PlainObjectBase Alec May 7, 2011
 namespace igl
 {
+  // Subdivide without moving vertices: Given the triangle mesh [V, F],
+  // where n_verts = V.rows(), computes newV and a sparse matrix S s.t.
+  // [newV, newF] is the subdivided mesh where newV = S*V.
+  //
+  // Inputs:
+  //   n_verts  an integer (number of mesh vertices)
+  //   F  an m by 3 matrix of integers of triangle faces
+  // Outputs:
+  //   S  a sparse matrix (will become the subdivision matrix)
+  //   newF  a matrix containing the new faces
+  template <
+    typename DerivedF,
+    typename SType,
+    typename DerivedNF>
+  IGL_INLINE void upsample(
+    const int n_verts,
+    const Eigen::PlainObjectBase<DerivedF>& F,
+    Eigen::SparseMatrix<SType>& S,
+    Eigen::PlainObjectBase<DerivedNF>& NF);
   // Subdivide a mesh without moving vertices: loop subdivision but odd
   // vertices stay put and even vertices are just edge midpoints
   // 
@@ -42,14 +62,17 @@ namespace igl
     const Eigen::PlainObjectBase<DerivedV>& V,
     const Eigen::PlainObjectBase<DerivedF>& F,
     Eigen::PlainObjectBase<DerivedNV>& NV,
-    Eigen::PlainObjectBase<DerivedNF>& NF);
+    Eigen::PlainObjectBase<DerivedNF>& NF,
+    const int number_of_subdivs = 1);
+
   // Virtually in place wrapper
   template <
     typename MatV, 
     typename MatF>
   IGL_INLINE void upsample(
     MatV& V,
-    MatF& F);
+    MatF& F,
+    const int number_of_subdivs = 1);
 }
 
 #ifndef IGL_STATIC_LIBRARY

+ 6 - 0
matlab-to-eigen.html

@@ -272,6 +272,12 @@ bool a = A.array().any();
         <td></td>
       </tr>
 
+      <tr class=d1>
+        <td><pre><code>[IA,LOCB] = ismember(A,B)</code></pre></td>
+        <td><pre><code>igl::ismember(A,B,IA,LOCB)</code></pre></td>
+        <td></td>
+      </tr>
+
       <!-- Insert rows for each command pair -->
 
       <!-- Leave this here for copy and pasting

+ 1 - 1
shared/cmake/CMakeLists.txt

@@ -401,7 +401,7 @@ if(LIBIGL_WITH_VIEWER)
     add_subdirectory("${NANOGUI_DIR}/ext/glfw" "glfw")
 
     set(VIEWER_INCLUDE_DIRS "${NANOGUI_DIR}/ext/glfw/include")
-    set(LIBIGL_VIEWER_EXTRA_LIBRARIES "glfw" ${OPENGL_gl_LIBRARY})
+    set(LIBIGL_VIEWER_EXTRA_LIBRARIES "glfw" ${OPENGL_gl_LIBRARY} ${GLFW_LIBRARIES})
   endif()
 
   ### GLEW for linux and windows

+ 1 - 1
tutorial/611_SLIM/CMakeLists.txt → tutorial/710_SLIM/CMakeLists.txt

@@ -1,5 +1,5 @@
 cmake_minimum_required(VERSION 2.8.12)
-project(611_SLIM)
+project(710_SLIM)
 
 add_executable(${PROJECT_NAME}_bin
   main.cpp)

+ 0 - 0
tutorial/611_SLIM/main.cpp → tutorial/710_SLIM/main.cpp


+ 8 - 0
tutorial/711_Subdivision/CMakeLists.txt

@@ -0,0 +1,8 @@
+cmake_minimum_required(VERSION 2.8.12)
+project(711_Subdivision)
+
+add_executable(${PROJECT_NAME}_bin
+  main.cpp)
+target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
+target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 68 - 0
tutorial/711_Subdivision/main.cpp

@@ -0,0 +1,68 @@
+#include <igl/read_triangle_mesh.h>
+#include <igl/loop.h>
+#include <igl/upsample.h>
+#include <igl/false_barycentric_subdivision.h>
+#include <igl/viewer/Viewer.h>
+#include <Eigen/Core>
+#include <iostream>
+
+#include "tutorial_shared_path.h"
+
+int main(int argc, char * argv[])
+{
+  using namespace std;
+  using namespace igl;
+  Eigen::MatrixXi OF,F;
+  Eigen::MatrixXd OV,V;
+  bool show_swept_volume = false;
+  read_triangle_mesh(
+      TUTORIAL_SHARED_PATH "/decimated-knight.off",OV,OF);
+  V = OV;
+  F = OF;
+  cout<<R"(Usage:
+1  Restore Original mesh
+2  Apply In-plane upsampled mesh
+3  Apply Loop subdivided mesh
+4  Apply False barycentric subdivision
+)";
+  igl::viewer::Viewer viewer;
+  viewer.data.set_mesh(V,F);
+  viewer.data.set_face_based(true);
+
+  viewer.callback_key_down =
+    [&](igl::viewer::Viewer & viewer, unsigned char key, int mod)->bool
+    {
+      switch(key)
+      {
+        default:
+          return false;
+        case '1':
+        {
+          V = OV;
+          F = OF;
+          break;
+        }
+        case '2':
+        {
+          igl::upsample( Eigen::MatrixXd(V), Eigen::MatrixXi(F), V,F);
+          break;
+        }
+        case '3':
+        {
+          igl::loop( Eigen::MatrixXd(V), Eigen::MatrixXi(F), V,F);
+          break;
+        }
+        case '4':
+        {
+          igl::false_barycentric_subdivision(
+            Eigen::MatrixXd(V),Eigen::MatrixXi(F),V,F);
+          break;
+        }
+      }
+      viewer.data.clear();
+      viewer.data.set_mesh(V,F);
+      viewer.data.set_face_based(true);
+      return true;
+    };
+  viewer.launch();
+}

+ 2 - 2
tutorial/CMakeLists.txt

@@ -164,7 +164,6 @@ if(TUTORIALS_CHAPTER6)
     add_subdirectory("609_Boolean")
     add_subdirectory("610_CSGTree")
   endif()
-  add_subdirectory("611_SLIM")
 endif()
 
 # Chapter 7
@@ -180,5 +179,6 @@ if(TUTORIALS_CHAPTER7)
   add_subdirectory("707_SweptVolume")
   add_subdirectory("708_Picking")
   add_subdirectory("709_VectorFieldVisualizer")
-
+  add_subdirectory("710_SLIM")
+  add_subdirectory("711_Subdivision")
 endif()

+ 1 - 0
tutorial/images/decimated-knight-subdivision.gif.REMOVED.git-id

@@ -0,0 +1 @@
+c334c086e2f3ec1de26911b03329804c4ab90ea7

+ 0 - 0
tutorial/images/611_SLIM.png.REMOVED.git-id → tutorial/images/slim.png.REMOVED.git-id


+ 5 - 0
tutorial/style.css

@@ -55,6 +55,11 @@ figcaption
   font-style: italic;
 }
 
+figcaption code
+{
+  font-style: normal;
+}
+
 pre, code {
   font-size: 0.85em;
   font-family: Consolas, Inconsolata, Courier, monospace;

+ 1 - 1
tutorial/tutorial.html.REMOVED.git-id

@@ -1 +1 @@
-cd11b42bda4357cfaae8f62d5036f840df5b627d
+2d4017ae4cf96f5ddc6c543c54d15c47418217cb

+ 1 - 1
tutorial/tutorial.md.REMOVED.git-id

@@ -1 +1 @@
-d17b6043e03c640488d1b324beebc066cdc3c830
+7e9a0845653ff898c4654b6c35e9d326955283f8