Przeglądaj źródła

Merge remote-tracking branch 'upstream/master'

Former-commit-id: 19b6134ccaf73d633fd4f88b41787bedd1f564b9
Qingnan Zhou 8 lat temu
rodzic
commit
5dd15b5ea1
100 zmienionych plików z 3155 dodań i 779 usunięć
  1. 1 0
      .appveyor.yml
  2. 4 0
      include/igl/AABB.cpp
  3. 1 0
      include/igl/Timer.h
  4. 11 11
      include/igl/active_set.cpp
  5. 1 2
      include/igl/angle_bound_frame_fields.cpp
  6. 2 2
      include/igl/arap.cpp
  7. 1 1
      include/igl/arap_dof.cpp
  8. 0 201
      include/igl/bbw/bbw.cpp
  9. 0 99
      include/igl/bbw/bbw.h
  10. 2 2
      include/igl/boundary_facets.cpp
  11. 1 1
      include/igl/ceil.cpp
  12. 1 1
      include/igl/circulation.h
  13. 128 3
      include/igl/collapse_edge.cpp
  14. 90 0
      include/igl/collapse_edge.h
  15. 0 15
      include/igl/copyleft/cgal/SelfIntersectMesh.h
  16. 5 5
      include/igl/copyleft/cgal/assign_scalar.cpp
  17. 3 3
      include/igl/copyleft/cgal/assign_scalar.h
  18. 0 3
      include/igl/copyleft/cgal/intersect_other.cpp
  19. 1 1
      include/igl/copyleft/cgal/order_facets_around_edge.cpp
  20. 2 0
      include/igl/copyleft/cgal/outer_hull.cpp
  21. 41 0
      include/igl/copyleft/cgal/point_segment_squared_distance.cpp
  22. 44 0
      include/igl/copyleft/cgal/point_segment_squared_distance.h
  23. 47 0
      include/igl/copyleft/cgal/point_triangle_squared_distance.cpp
  24. 45 0
      include/igl/copyleft/cgal/point_triangle_squared_distance.h
  25. 0 30
      include/igl/copyleft/cgal/remesh_intersections.cpp
  26. 91 0
      include/igl/copyleft/cgal/resolve_intersections.cpp
  27. 51 0
      include/igl/copyleft/cgal/resolve_intersections.h
  28. 18 0
      include/igl/copyleft/cgal/row_to_point.cpp
  29. 38 0
      include/igl/copyleft/cgal/row_to_point.h
  30. 129 0
      include/igl/copyleft/cgal/segment_segment_squared_distance.cpp
  31. 46 0
      include/igl/copyleft/cgal/segment_segment_squared_distance.h
  32. 206 0
      include/igl/copyleft/cgal/snap_rounding.cpp
  33. 51 0
      include/igl/copyleft/cgal/snap_rounding.h
  34. 134 0
      include/igl/copyleft/cgal/subdivide_segments.cpp
  35. 56 0
      include/igl/copyleft/cgal/subdivide_segments.h
  36. 114 0
      include/igl/copyleft/cgal/triangle_triangle_squared_distance.cpp
  37. 45 0
      include/igl/copyleft/cgal/triangle_triangle_squared_distance.h
  38. 1 1
      include/igl/copyleft/progressive_hulls.cpp
  39. 4 6
      include/igl/copyleft/tetgen/cdt.cpp
  40. 52 0
      include/igl/cylinder.cpp
  41. 33 0
      include/igl/cylinder.h
  42. 189 44
      include/igl/decimate.cpp
  43. 146 0
      include/igl/decimate.h
  44. 1 0
      include/igl/deform_skeleton.h
  45. 1 0
      include/igl/directed_edge_orientations.h
  46. 2 2
      include/igl/dot_row.cpp
  47. 1 1
      include/igl/dot_row.h
  48. 1 1
      include/igl/doublearea.cpp
  49. 1 1
      include/igl/face_areas.cpp
  50. 1 1
      include/igl/floor.cpp
  51. 4 0
      include/igl/hausdorff.cpp
  52. 11 2
      include/igl/hausdorff.h
  53. 96 0
      include/igl/ismember.cpp
  54. 41 0
      include/igl/ismember.h
  55. 7 1
      include/igl/jet.cpp
  56. 1 1
      include/igl/jet.h
  57. 5 6
      include/igl/line_field_missmatch.cpp
  58. 5 3
      include/igl/list_to_matrix.cpp
  59. 146 125
      include/igl/loop.cpp
  60. 40 29
      include/igl/loop.h
  61. 1 0
      include/igl/matrix_to_list.cpp
  62. 10 3
      include/igl/matrix_to_list.h
  63. 16 5
      include/igl/max_faces_stopping_condition.cpp
  64. 5 0
      include/igl/max_faces_stopping_condition.h
  65. 10 10
      include/igl/min_quad_with_fixed.cpp
  66. 1 1
      include/igl/on_boundary.cpp
  67. 1 1
      include/igl/orient_outward.cpp
  68. 5 1
      include/igl/parula.cpp
  69. 1 1
      include/igl/per_vertex_attribute_smoothing.cpp
  70. 157 0
      include/igl/per_vertex_point_to_plane_quadrics.cpp
  71. 53 0
      include/igl/per_vertex_point_to_plane_quadrics.h
  72. 1 0
      include/igl/point_mesh_squared_distance.cpp
  73. 26 14
      include/igl/point_simplex_squared_distance.cpp
  74. 3 3
      include/igl/point_simplex_squared_distance.h
  75. 2 2
      include/igl/project_isometrically_to_plane.cpp
  76. 112 0
      include/igl/qslim.cpp
  77. 41 0
      include/igl/qslim.h
  78. 130 0
      include/igl/qslim_optimal_collapse_edge_callbacks.cpp
  79. 81 0
      include/igl/qslim_optimal_collapse_edge_callbacks.h
  80. 2 1
      include/igl/quad_planarity.cpp
  81. 24 0
      include/igl/quadric_binary_plus_operator.cpp
  82. 35 0
      include/igl/quadric_binary_plus_operator.h
  83. 0 9
      include/igl/randperm.cpp
  84. 0 2
      include/igl/randperm.h
  85. 5 2
      include/igl/serialize.h
  86. 1 1
      include/igl/setdiff.cpp
  87. 23 0
      include/igl/shortest_edge_and_midpoint.cpp
  88. 48 0
      include/igl/shortest_edge_and_midpoint.h
  89. 2 2
      include/igl/signed_distance.cpp
  90. 4 1
      include/igl/simplify_polyhedron.cpp
  91. 19 20
      include/igl/slice_into.cpp
  92. 7 7
      include/igl/slice_into.h
  93. 15 14
      include/igl/sort.cpp
  94. 1 0
      include/igl/unique.cpp
  95. 58 24
      include/igl/upsample.cpp
  96. 25 2
      include/igl/upsample.h
  97. 2 2
      include/igl/viewer/TextRenderer.cpp
  98. 9 7
      include/igl/viewer/Viewer.cpp
  99. 19 39
      include/igl/viewer/ViewerCore.cpp
  100. 1 1
      include/igl/winding_number.cpp

+ 1 - 0
.appveyor.yml

@@ -5,6 +5,7 @@ clone_folder: C:\projects\libigl
 branches:
   only:
     - master
+    - alecjacobson
 install:
   - git submodule update --init --recursive
   - cinstall: python

+ 4 - 0
include/igl/AABB.cpp

@@ -949,6 +949,10 @@ igl::AABB<DerivedV,DIM>::intersect_ray(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // generated by autoexplicit.sh
+template void igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 3>::squared_distance<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&) const;
+// generated by autoexplicit.sh
+template void igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 2>::squared_distance<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&) const;
+// generated by autoexplicit.sh
 template void igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 3>::init(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&);
 template void igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 2>::init(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&);
 template void igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 3>::squared_distance<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&) const;

+ 1 - 0
include/igl/Timer.h

@@ -21,6 +21,7 @@
 #else
 #include <sys/time.h>
 #endif
+#include <cstddef>
 
 namespace igl
 {

+ 11 - 11
include/igl/active_set.cpp

@@ -56,7 +56,7 @@ IGL_INLINE igl::SolverStatus igl::active_set(
   // Discard const qualifiers
   //if(B.size() == 0)
   //{
-  //  B = Eigen::PlainObjectBase<DerivedB>::Zero(n,1);
+  //  B = DerivedB::Zero(n,1);
   //}
   assert(n == B.rows() && "B.rows() must match A.rows()");
   assert(B.cols() == 1 && "B must be a column vector");
@@ -71,7 +71,7 @@ IGL_INLINE igl::SolverStatus igl::active_set(
   Eigen::Matrix<typename Derivedux::Scalar,Eigen::Dynamic,1> ux;
   if(p_lx.size() == 0)
   {
-    lx = Eigen::PlainObjectBase<Derivedlx>::Constant(
+    lx = Derivedlx::Constant(
       n,1,-numeric_limits<typename Derivedlx::Scalar>::max());
   }else
   {
@@ -79,7 +79,7 @@ IGL_INLINE igl::SolverStatus igl::active_set(
   }
   if(p_ux.size() == 0)
   {
-    ux = Eigen::PlainObjectBase<Derivedux>::Constant(
+    ux = Derivedux::Constant(
       n,1,numeric_limits<typename Derivedux::Scalar>::max());
   }else
   {
@@ -109,8 +109,8 @@ IGL_INLINE igl::SolverStatus igl::active_set(
   Matrix<BOOL,Dynamic,1> as_ieq = Matrix<BOOL,Dynamic,1>::Constant(Aieq.rows(),1,FALSE);
 
   // Keep track of previous Z for comparison
-  PlainObjectBase<DerivedZ> old_Z;
-  old_Z = PlainObjectBase<DerivedZ>::Constant(
+  DerivedZ old_Z;
+  old_Z = DerivedZ::Constant(
       n,1,numeric_limits<typename DerivedZ::Scalar>::max());
 
   int iter = 0;
@@ -143,7 +143,7 @@ IGL_INLINE igl::SolverStatus igl::active_set(
       }
       if(Aieq.rows() > 0)
       {
-        PlainObjectBase<DerivedZ> AieqZ;
+        DerivedZ AieqZ;
         AieqZ = Aieq*Z;
         for(int a = 0;a<Aieq.rows();a++)
         {
@@ -190,9 +190,9 @@ IGL_INLINE igl::SolverStatus igl::active_set(
 #endif
 
     // PREPARE FIXED VALUES
-    PlainObjectBase<Derivedknown> known_i;
+    Derivedknown known_i;
     known_i.resize(nk + as_lx_count + as_ux_count,1);
-    PlainObjectBase<DerivedY> Y_i;
+    DerivedY Y_i;
     Y_i.resize(nk + as_lx_count + as_ux_count,1);
     {
       known_i.block(0,0,known.rows(),known.cols()) = known;
@@ -225,7 +225,7 @@ IGL_INLINE igl::SolverStatus igl::active_set(
     // PREPARE EQUALITY CONSTRAINTS
     VectorXi as_ieq_list(as_ieq_count,1);
     // Gather active constraints and resp. rhss
-    PlainObjectBase<DerivedBeq> Beq_i;
+    DerivedBeq Beq_i;
     Beq_i.resize(Beq.rows()+as_ieq_count,1);
     Beq_i.head(Beq.rows()) = Beq;
     {
@@ -262,7 +262,7 @@ IGL_INLINE igl::SolverStatus igl::active_set(
     }
 #endif
 
-    Eigen::PlainObjectBase<DerivedZ> sol;
+    DerivedZ sol;
     if(known_i.size() == A.rows())
     {
       // Everything's fixed?
@@ -311,7 +311,7 @@ IGL_INLINE igl::SolverStatus igl::active_set(
     SparseMatrix<AT> Ak;
     // Slow
     slice(A,known_i,1,Ak);
-    Eigen::PlainObjectBase<DerivedB> Bk;
+    DerivedB Bk;
     slice(B,known_i,Bk);
     MatrixXd Lambda_known_i = -(0.5*Ak*Z + 0.5*Bk);
     // reverse the lambda values for lx

+ 1 - 2
include/igl/angle_bound_frame_fields.cpp

@@ -38,8 +38,7 @@ namespace igl {
       Eigen::VectorXi indInteriorToFull;
       Eigen::VectorXi indFullToInterior;
 
-//#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
-      Eigen::PlainObjectBase<DerivedV> B1, B2, FN;
+      DerivedV B1, B2, FN;
 
       //laplacians
       Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar>> DDA, DDB;

+ 2 - 2
include/igl/arap.cpp

@@ -55,8 +55,8 @@ IGL_INLINE bool igl::arap_precomputation(
   assert(data.dim <= V.cols() && "solve dim should be <= embedding");
   bool flat = (V.cols() - data.dim)==1;
 
-  PlainObjectBase<DerivedV> plane_V;
-  PlainObjectBase<DerivedF> plane_F;
+  DerivedV plane_V;
+  DerivedF plane_F;
   typedef SparseMatrix<Scalar> SparseMatrixS;
   SparseMatrixS ref_map,ref_map_dim;
   if(flat)

+ 1 - 1
include/igl/arap_dof.cpp

@@ -149,7 +149,7 @@ IGL_INLINE bool igl::arap_dof_precomputation(
   // Apply group sum to each dimension's block of covariance scatter matrix
   SparseMatrix<double> G_sum_dim;
   repdiag(G_sum,data.dim,G_sum_dim);
-  CSM = G_sum_dim * CSM;
+  CSM = (G_sum_dim * CSM).eval();
 #ifdef EXTREME_VERBOSE
   cout<<"CSMIJV=["<<endl;print_ijv(CSM,1);cout<<endl<<"];"<<
     endl<<"CSM=sparse(CSMIJV(:,1),CSMIJV(:,2),CSMIJV(:,3),"<<

+ 0 - 201
include/igl/bbw/bbw.cpp

@@ -1,201 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2013 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 "bbw.h"
-
-#include <igl/cotmatrix.h>
-#include <igl/massmatrix.h>
-#include <igl/invert_diag.h>
-#include <igl/speye.h>
-#include <igl/slice_into.h>
-#include <igl/min_quad_with_fixed.h>
-
-#include <Eigen/Sparse>
-
-#include <iostream>
-#include <cstdio>
-
-igl::bbw::BBWData::BBWData():
-  partition_unity(false),
-  W0(),
-#ifndef IGL_NO_MOSEK
-  mosek_data(),
-#endif
-  active_set_params(),
-  qp_solver(QP_SOLVER_IGL_ACTIVE_SET),
-  verbosity(0)
-{
-  // We know that the Bilaplacian is positive semi-definite
-  active_set_params.Auu_pd = true;
-}
-
-void igl::bbw::BBWData::print()
-{
-  using namespace std;
-  cout<<"partition_unity: "<<partition_unity<<endl;
-  cout<<"W0=["<<endl<<W0<<endl<<"];"<<endl;
-  cout<<"qp_solver: "<<QPSolverNames[qp_solver]<<endl;
-}
-
-
-template <
-  typename DerivedV,
-  typename DerivedEle,
-  typename Derivedb,
-  typename Derivedbc,
-  typename DerivedW>
-IGL_INLINE bool igl::bbw::bbw(
-  const Eigen::PlainObjectBase<DerivedV> & V,
-  const Eigen::PlainObjectBase<DerivedEle> & Ele,
-  const Eigen::PlainObjectBase<Derivedb> & b,
-  const Eigen::PlainObjectBase<Derivedbc> & bc,
-  igl::bbw::BBWData & data,
-  Eigen::PlainObjectBase<DerivedW> & W
-  )
-{
-  using namespace std;
-  using namespace Eigen;
-
-  // number of domain vertices
-  int n = V.rows();
-  // number of handles
-  int m = bc.cols();
-  // Build biharmonic operator
-  SparseMatrix<typename DerivedW::Scalar> L;
-  cotmatrix(V,Ele,L);
-  SparseMatrix<typename DerivedW::Scalar> M;
-  SparseMatrix<typename DerivedW::Scalar> Mi;
-  massmatrix(V,Ele,MASSMATRIX_TYPE_DEFAULT,M);
-  invert_diag(M,Mi);
-  SparseMatrix<typename DerivedW::Scalar> Q = L.transpose() * Mi * L;
-  assert(!data.partition_unity && "partition_unity not implemented yet");
-
-  W.derived().resize(n,m);
-  {
-    // No linear terms
-    VectorXd c = VectorXd::Zero(n);
-    // No linear constraints
-    SparseMatrix<typename DerivedW::Scalar> A(0,n),Aeq(0,n),Aieq(0,n);
-    VectorXd uc(0,1),Beq(0,1),Bieq(0,1),lc(0,1);
-    // Upper and lower box constraints (Constant bounds)
-    VectorXd ux = VectorXd::Ones(n);
-    VectorXd lx = VectorXd::Zero(n);
-    active_set_params eff_params = data.active_set_params;
-    switch(data.qp_solver)
-    {
-      case QP_SOLVER_IGL_ACTIVE_SET:
-      {
-        if(data.verbosity >= 1)
-        {
-          cout<<"BBW: max_iter: "<<data.active_set_params.max_iter<<endl;
-          cout<<"BBW: eff_max_iter: "<<eff_params.max_iter<<endl;
-        }
-        if(data.verbosity >= 1)
-        {
-          cout<<"BBW: Computing initial weights for "<<m<<" handle"<<
-            (m!=1?"s":"")<<"."<<endl;
-        }
-        min_quad_with_fixed_data<typename DerivedW::Scalar > mqwf;
-        min_quad_with_fixed_precompute(Q,b,Aeq,true,mqwf);
-        min_quad_with_fixed_solve(mqwf,c,bc,Beq,W);
-        // decrement
-        eff_params.max_iter--;
-        bool error = false;
-        // Loop over handles
-#pragma omp parallel for
-        for(int i = 0;i<m;i++)
-        {
-          // Quicker exit for openmp
-          if(error)
-          {
-            continue;
-          }
-          if(data.verbosity >= 1)
-          {
-#pragma omp critical
-            cout<<"BBW: Computing weight for handle "<<i+1<<" out of "<<m<<
-              "."<<endl;
-          }
-          VectorXd bci = bc.col(i);
-          VectorXd Wi;
-          // use initial guess
-          Wi = W.col(i);
-          SolverStatus ret = active_set(
-              Q,c,b,bci,Aeq,Beq,Aieq,Bieq,lx,ux,eff_params,Wi);
-          switch(ret)
-          {
-            case SOLVER_STATUS_CONVERGED:
-              break;
-            case SOLVER_STATUS_MAX_ITER:
-              cerr<<"active_set: max iter without convergence."<<endl;
-              break;
-            case SOLVER_STATUS_ERROR:
-            default:
-              cerr<<"active_set error."<<endl;
-              error = true;
-          }
-          W.col(i) = Wi;
-        }
-        if(error)
-        {
-          return false;
-        }
-        break;
-      }
-      case QP_SOLVER_MOSEK:
-      {
-#ifdef IGL_NO_MOSEK
-        assert(false && "Use another QPSolver. Recompile without IGL_NO_MOSEK defined.");
-        cerr<<"Use another QPSolver. Recompile without IGL_NO_MOSEK defined."<<endl;
-        return false;
-#else
-        // Loop over handles
-        for(int i = 0;i<m;i++)
-        {
-          if(data.verbosity >= 1)
-          {
-            cout<<"BBW: Computing weight for handle "<<i+1<<" out of "<<m<<
-              "."<<endl;
-          }
-          VectorXd bci = bc.col(i);
-          VectorXd Wi;
-          // impose boundary conditions via bounds
-          slice_into(bci,b,ux);
-          slice_into(bci,b,lx);
-          bool r = mosek_quadprog(Q,c,0,A,lc,uc,lx,ux,data.mosek_data,Wi);
-          if(!r)
-          {
-            return false;
-          }
-          W.col(i) = Wi;
-        }
-#endif
-        break;
-      }
-      default:
-      {
-        assert(false && "Unknown qp_solver");
-        return false;
-      }
-    }
-#ifndef NDEBUG
-    const double min_rowsum = W.rowwise().sum().array().abs().minCoeff();
-    if(min_rowsum < 0.1)
-    {
-      cerr<<"bbw.cpp: Warning, minimum row sum is very low. Consider more "
-        "active set iterations or enforcing partition of unity."<<endl;
-    }
-#endif
-  }
-
-  return true;
-}
-
-#ifdef IGL_STATIC_LIBRARY
-// Explicit template specialization
-template bool igl::bbw::bbw<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<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -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<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, igl::bbw::BBWData&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
-#endif

+ 0 - 99
include/igl/bbw/bbw.h

@@ -1,99 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2013 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_BBW_BBW_H
-#define IGL_BBW_BBW_H
-#include "../igl_inline.h"
-
-#include <Eigen/Dense>
-#ifndef IGL_NO_MOSEK
-#  include <igl/mosek/mosek_quadprog.h>
-#endif
-#include <igl/active_set.h>
-
-namespace igl
-{
-  namespace bbw
-  {
-    enum QPSolver
-    {
-      QP_SOLVER_IGL_ACTIVE_SET = 0,
-      QP_SOLVER_MOSEK = 1,
-      NUM_QP_SOLVERS = 2
-    };
-    const char * const QPSolverNames[NUM_QP_SOLVERS] =
-    {
-      "QP_SOLVER_IGL_ACTIVE_SET",
-      "QP_SOLVER_MOSEK"
-    };
-    // Container for BBW computation related data and flags
-    class BBWData
-    {
-      public:
-        // Enforce partition of unity during optimization (optimize all weight
-        // simultaneously)
-        bool partition_unity;
-        // Initial guess
-        Eigen::MatrixXd W0;
-#ifndef IGL_NO_MOSEK
-        igl::mosek::MosekData mosek_data;
-#endif
-        igl::active_set_params active_set_params;
-        // Which solver
-        QPSolver qp_solver;
-        // Verbosity level
-        // 0: quiet
-        // 1: loud
-        // 2: louder
-        int verbosity;
-      public:
-        IGL_INLINE BBWData();
-
-        // Print current state of object
-        IGL_INLINE void print();
-    };
-
-    // Compute Bounded Biharmonic Weights on a given domain (V,Ele) with a given
-    // set of boundary conditions
-    //
-    // Templates
-    //   DerivedV  derived type of eigen matrix for V (e.g. MatrixXd)
-    //   DerivedF  derived type of eigen matrix for F (e.g. MatrixXi)
-    //   Derivedb  derived type of eigen matrix for b (e.g. VectorXi)
-    //   Derivedbc  derived type of eigen matrix for bc (e.g. MatrixXd)
-    //   DerivedW  derived type of eigen matrix for W (e.g. MatrixXd)
-    // Inputs:
-    //   V  #V by dim vertex positions
-    //   Ele  #Elements by simplex-size list of element indices
-    //   b  #b boundary indices into V
-    //   bc #b by #W list of boundary values
-    //   data  object containing options, intial guess --> solution and results
-    // Outputs:
-    //   W  #V by #W list of *unnormalized* weights to normalize use
-    //    igl::normalize_row_sums(W,W);
-    // Returns true on success, false on failure
-    template <
-      typename DerivedV,
-               typename DerivedEle,
-               typename Derivedb,
-               typename Derivedbc,
-               typename DerivedW>
-                 IGL_INLINE bool bbw(
-                     const Eigen::PlainObjectBase<DerivedV> & V,
-                     const Eigen::PlainObjectBase<DerivedEle> & Ele,
-                     const Eigen::PlainObjectBase<Derivedb> & b,
-                     const Eigen::PlainObjectBase<Derivedbc> & bc,
-                     BBWData & data,
-                     Eigen::PlainObjectBase<DerivedW> & W);
-  }
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "bbw.cpp"
-#endif
-
-#endif

+ 2 - 2
include/igl/boundary_facets.cpp

@@ -110,9 +110,9 @@ IGL_INLINE void igl::boundary_facets(
   using namespace std;
   using namespace Eigen;
   // Cop out: use vector of vectors version
-  vector<vector<typename Eigen::PlainObjectBase<DerivedT>::Scalar> > vT;
+  vector<vector<typename DerivedT::Scalar> > vT;
   matrix_to_list(T,vT);
-  vector<vector<typename Eigen::PlainObjectBase<DerivedF>::Scalar> > vF;
+  vector<vector<typename DerivedF::Scalar> > vF;
   boundary_facets(vT,vF);
   list_to_matrix(vF,F);
 }

+ 1 - 1
include/igl/ceil.cpp

@@ -14,7 +14,7 @@ IGL_INLINE void igl::ceil(
   Eigen::PlainObjectBase<DerivedY>& Y)
 {
   using namespace std;
-  //Y = Eigen::PlainObjectBase<DerivedY>::Zero(m,n);
+  //Y = DerivedY::Zero(m,n);
 //#pragma omp parallel for
   //for(int i = 0;i<m;i++)
   //{

+ 1 - 1
include/igl/circulation.h

@@ -28,7 +28,7 @@ namespace igl
   //     F(f,:) opposite the vth corner, where EI(e,0)=v. Similarly EF(e,1) "
   //     e=(j->i)
   //   EI  #E by 2 list of edge flap corners (see above).
-  // Returns list of faces touched by circulation.
+  // Returns list of faces touched by circulation (in cyclically order).
   //   
   IGL_INLINE std::vector<int> circulation(
     const int e,

+ 128 - 3
include/igl/collapse_edge.cpp

@@ -176,8 +176,96 @@ IGL_INLINE bool igl::collapse_edge(
   Eigen::MatrixXd & C)
 {
   int e,e1,e2,f1,f2;
+  const auto always_try = [](
+    const Eigen::MatrixXd &                                         ,/*V*/
+    const Eigen::MatrixXi &                                         ,/*F*/
+    const Eigen::MatrixXi &                                         ,/*E*/
+    const Eigen::VectorXi &                                         ,/*EMAP*/
+    const Eigen::MatrixXi &                                         ,/*EF*/
+    const Eigen::MatrixXi &                                         ,/*EI*/
+    const std::set<std::pair<double,int> > &                        ,/*Q*/
+    const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
+    const Eigen::MatrixXd &                                         ,/*C*/
+    const int                                                        /*e*/
+    ) -> bool { return true;};
+  const auto never_care = [](
+    const Eigen::MatrixXd &                                         ,   /*V*/
+    const Eigen::MatrixXi &                                         ,   /*F*/
+    const Eigen::MatrixXi &                                         ,   /*E*/
+    const Eigen::VectorXi &                                         ,/*EMAP*/
+    const Eigen::MatrixXi &                                         ,  /*EF*/
+    const Eigen::MatrixXi &                                         ,  /*EI*/
+    const std::set<std::pair<double,int> > &                        ,   /*Q*/
+    const std::vector<std::set<std::pair<double,int> >::iterator > &, /*Qit*/
+    const Eigen::MatrixXd &                                         ,   /*C*/
+    const int                                                       ,   /*e*/
+    const int                                                       ,  /*e1*/
+    const int                                                       ,  /*e2*/
+    const int                                                       ,  /*f1*/
+    const int                                                       ,  /*f2*/
+    const bool                                                  /*collapsed*/
+    )-> void { };
   return 
-    collapse_edge(cost_and_placement,V,F,E,EMAP,EF,EI,Q,Qit,C,e,e1,e2,f1,f2);
+    collapse_edge(
+      cost_and_placement,always_try,never_care,
+      V,F,E,EMAP,EF,EI,Q,Qit,C,e,e1,e2,f1,f2);
+}
+
+IGL_INLINE bool igl::collapse_edge(
+  const std::function<void(
+    const int,
+    const Eigen::MatrixXd &,
+    const Eigen::MatrixXi &,
+    const Eigen::MatrixXi &,
+    const Eigen::VectorXi &,
+    const Eigen::MatrixXi &,
+    const Eigen::MatrixXi &,
+    double &,
+    Eigen::RowVectorXd &)> & cost_and_placement,
+  const std::function<bool(
+    const Eigen::MatrixXd &                                         ,/*V*/
+    const Eigen::MatrixXi &                                         ,/*F*/
+    const Eigen::MatrixXi &                                         ,/*E*/
+    const Eigen::VectorXi &                                         ,/*EMAP*/
+    const Eigen::MatrixXi &                                         ,/*EF*/
+    const Eigen::MatrixXi &                                         ,/*EI*/
+    const std::set<std::pair<double,int> > &                        ,/*Q*/
+    const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
+    const Eigen::MatrixXd &                                         ,/*C*/
+    const int                                                        /*e*/
+    )> & pre_collapse,
+  const std::function<void(
+    const Eigen::MatrixXd &                                         ,   /*V*/
+    const Eigen::MatrixXi &                                         ,   /*F*/
+    const Eigen::MatrixXi &                                         ,   /*E*/
+    const Eigen::VectorXi &                                         ,/*EMAP*/
+    const Eigen::MatrixXi &                                         ,  /*EF*/
+    const Eigen::MatrixXi &                                         ,  /*EI*/
+    const std::set<std::pair<double,int> > &                        ,   /*Q*/
+    const std::vector<std::set<std::pair<double,int> >::iterator > &, /*Qit*/
+    const Eigen::MatrixXd &                                         ,   /*C*/
+    const int                                                       ,   /*e*/
+    const int                                                       ,  /*e1*/
+    const int                                                       ,  /*e2*/
+    const int                                                       ,  /*f1*/
+    const int                                                       ,  /*f2*/
+    const bool                                                  /*collapsed*/
+    )> & post_collapse,
+  Eigen::MatrixXd & V,
+  Eigen::MatrixXi & F,
+  Eigen::MatrixXi & E,
+  Eigen::VectorXi & EMAP,
+  Eigen::MatrixXi & EF,
+  Eigen::MatrixXi & EI,
+  std::set<std::pair<double,int> > & Q,
+  std::vector<std::set<std::pair<double,int> >::iterator > & Qit,
+  Eigen::MatrixXd & C)
+{
+  int e,e1,e2,f1,f2;
+  return 
+    collapse_edge(
+      cost_and_placement,pre_collapse,post_collapse,
+      V,F,E,EMAP,EF,EI,Q,Qit,C,e,e1,e2,f1,f2);
 }
 
 
@@ -192,6 +280,35 @@ IGL_INLINE bool igl::collapse_edge(
     const Eigen::MatrixXi &,
     double &,
     Eigen::RowVectorXd &)> & cost_and_placement,
+  const std::function<bool(
+    const Eigen::MatrixXd &                                         ,/*V*/
+    const Eigen::MatrixXi &                                         ,/*F*/
+    const Eigen::MatrixXi &                                         ,/*E*/
+    const Eigen::VectorXi &                                         ,/*EMAP*/
+    const Eigen::MatrixXi &                                         ,/*EF*/
+    const Eigen::MatrixXi &                                         ,/*EI*/
+    const std::set<std::pair<double,int> > &                        ,/*Q*/
+    const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
+    const Eigen::MatrixXd &                                         ,/*C*/
+    const int                                                        /*e*/
+    )> & pre_collapse,
+  const std::function<void(
+    const Eigen::MatrixXd &                                         ,   /*V*/
+    const Eigen::MatrixXi &                                         ,   /*F*/
+    const Eigen::MatrixXi &                                         ,   /*E*/
+    const Eigen::VectorXi &                                         ,/*EMAP*/
+    const Eigen::MatrixXi &                                         ,  /*EF*/
+    const Eigen::MatrixXi &                                         ,  /*EI*/
+    const std::set<std::pair<double,int> > &                        ,   /*Q*/
+    const std::vector<std::set<std::pair<double,int> >::iterator > &, /*Qit*/
+    const Eigen::MatrixXd &                                         ,   /*C*/
+    const int                                                       ,   /*e*/
+    const int                                                       ,  /*e1*/
+    const int                                                       ,  /*e2*/
+    const int                                                       ,  /*f1*/
+    const int                                                       ,  /*f2*/
+    const bool                                                  /*collapsed*/
+    )> & post_collapse,
   Eigen::MatrixXd & V,
   Eigen::MatrixXi & F,
   Eigen::MatrixXi & E,
@@ -225,8 +342,16 @@ IGL_INLINE bool igl::collapse_edge(
   std::vector<int> N  = circulation(e, true,F,E,EMAP,EF,EI);
   std::vector<int> Nd = circulation(e,false,F,E,EMAP,EF,EI);
   N.insert(N.begin(),Nd.begin(),Nd.end());
-  const bool collapsed =
-    collapse_edge(e,C.row(e),V,F,E,EMAP,EF,EI,e1,e2,f1,f2);
+  bool collapsed = true;
+  if(pre_collapse(V,F,E,EMAP,EF,EI,Q,Qit,C,e))
+  {
+    collapsed = collapse_edge(e,C.row(e),V,F,E,EMAP,EF,EI,e1,e2,f1,f2);
+  }else
+  {
+    // Aborted by pre collapse callback
+    collapsed = false;
+  }
+  post_collapse(V,F,E,EMAP,EF,EI,Q,Qit,C,e,e1,e2,f1,f2,collapsed);
   if(collapsed)
   {
     // Erase the two, other collapsed edges

+ 90 - 0
include/igl/collapse_edge.h

@@ -70,6 +70,9 @@ namespace igl
   //   cost_and_placement  function computing cost of collapsing an edge and 3d
   //     position where it should be placed:
   //     cost_and_placement(V,F,E,EMAP,EF,EI,cost,placement);
+  //     **If the edges is collapsed** then this function will be called on all
+  //     edges of all faces previously incident on the endpoints of the
+  //     collapsed edge.
   //   Q  queue containing pairs of costs and edge indices
   //   Qit  list of iterators so that Qit[e] --> iterator of edge e in Q
   //   C  #E by dim list of stored placements
@@ -93,6 +96,64 @@ namespace igl
     std::set<std::pair<double,int> > & Q,
     std::vector<std::set<std::pair<double,int> >::iterator > & Qit,
     Eigen::MatrixXd & C);
+  // Inputs:
+  //   pre_collapse  callback called with index of edge whose collapse is about
+  //     to be attempted. This function should return whether to **proceed**
+  //     with the collapse: returning true means "yes, try to collapse",
+  //     returning false means "No, consider this edge 'uncollapsable', behave
+  //     as if collapse_edge(e) returned false.
+  //   post_collapse  callback called with index of edge whose collapse was
+  //     just attempted and a flag revealing whether this was successful.
+  IGL_INLINE bool collapse_edge(
+    const std::function<void(
+      const int,
+      const Eigen::MatrixXd &,
+      const Eigen::MatrixXi &,
+      const Eigen::MatrixXi &,
+      const Eigen::VectorXi &,
+      const Eigen::MatrixXi &,
+      const Eigen::MatrixXi &,
+      double &,
+      Eigen::RowVectorXd &)> & cost_and_placement,
+    const std::function<bool(
+      const Eigen::MatrixXd &                                         ,/*V*/
+      const Eigen::MatrixXi &                                         ,/*F*/
+      const Eigen::MatrixXi &                                         ,/*E*/
+      const Eigen::VectorXi &                                         ,/*EMAP*/
+      const Eigen::MatrixXi &                                         ,/*EF*/
+      const Eigen::MatrixXi &                                         ,/*EI*/
+      const std::set<std::pair<double,int> > &                        ,/*Q*/
+      const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
+      const Eigen::MatrixXd &                                         ,/*C*/
+      const int                                                        /*e*/
+      )> & pre_collapse,
+    const std::function<void(
+      const Eigen::MatrixXd &                                         ,   /*V*/
+      const Eigen::MatrixXi &                                         ,   /*F*/
+      const Eigen::MatrixXi &                                         ,   /*E*/
+      const Eigen::VectorXi &                                         ,/*EMAP*/
+      const Eigen::MatrixXi &                                         ,  /*EF*/
+      const Eigen::MatrixXi &                                         ,  /*EI*/
+      const std::set<std::pair<double,int> > &                        ,   /*Q*/
+      const std::vector<std::set<std::pair<double,int> >::iterator > &, /*Qit*/
+      const Eigen::MatrixXd &                                         ,   /*C*/
+      const int                                                       ,   /*e*/
+      const int                                                       ,  /*e1*/
+      const int                                                       ,  /*e2*/
+      const int                                                       ,  /*f1*/
+      const int                                                       ,  /*f2*/
+      const bool                                                  /*collapsed*/
+      )> & post_collapse,
+    Eigen::MatrixXd & V,
+    Eigen::MatrixXi & F,
+    Eigen::MatrixXi & E,
+    Eigen::VectorXi & EMAP,
+    Eigen::MatrixXi & EF,
+    Eigen::MatrixXi & EI,
+    std::set<std::pair<double,int> > & Q,
+    std::vector<std::set<std::pair<double,int> >::iterator > & Qit,
+    Eigen::MatrixXd & C);
+
   IGL_INLINE bool collapse_edge(
     const std::function<void(
       const int,
@@ -104,6 +165,35 @@ namespace igl
       const Eigen::MatrixXi &,
       double &,
       Eigen::RowVectorXd &)> & cost_and_placement,
+    const std::function<bool(
+      const Eigen::MatrixXd &                                         ,/*V*/
+      const Eigen::MatrixXi &                                         ,/*F*/
+      const Eigen::MatrixXi &                                         ,/*E*/
+      const Eigen::VectorXi &                                         ,/*EMAP*/
+      const Eigen::MatrixXi &                                         ,/*EF*/
+      const Eigen::MatrixXi &                                         ,/*EI*/
+      const std::set<std::pair<double,int> > &                        ,/*Q*/
+      const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
+      const Eigen::MatrixXd &                                         ,/*C*/
+      const int                                                        /*e*/
+      )> & pre_collapse,
+    const std::function<void(
+      const Eigen::MatrixXd &                                         ,   /*V*/
+      const Eigen::MatrixXi &                                         ,   /*F*/
+      const Eigen::MatrixXi &                                         ,   /*E*/
+      const Eigen::VectorXi &                                         ,/*EMAP*/
+      const Eigen::MatrixXi &                                         ,  /*EF*/
+      const Eigen::MatrixXi &                                         ,  /*EI*/
+      const std::set<std::pair<double,int> > &                        ,   /*Q*/
+      const std::vector<std::set<std::pair<double,int> >::iterator > &, /*Qit*/
+      const Eigen::MatrixXd &                                         ,   /*C*/
+      const int                                                       ,   /*e*/
+      const int                                                       ,  /*e1*/
+      const int                                                       ,  /*e2*/
+      const int                                                       ,  /*f1*/
+      const int                                                       ,  /*f2*/
+      const bool                                                  /*collapsed*/
+      )> & post_collapse,
     Eigen::MatrixXd & V,
     Eigen::MatrixXi & F,
     Eigen::MatrixXi & E,

+ 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;}

+ 5 - 5
include/igl/copyleft/cgal/assign_scalar.cpp

@@ -8,18 +8,18 @@
 #include "assign_scalar.h"
 
 IGL_INLINE void igl::copyleft::cgal::assign_scalar(
-  const typename CGAL::Epeck::FT & cgal,
+  const CGAL::Epeck::FT & cgal,
   CGAL::Epeck::FT & d)
 {
   d = cgal;
 }
 
 IGL_INLINE void igl::copyleft::cgal::assign_scalar(
-  const typename CGAL::Epeck::FT & _cgal,
+  const CGAL::Epeck::FT & _cgal,
   double & d)
 {
   // FORCE evaluation of the exact type otherwise interval might be huge.
-  const typename CGAL::Epeck::FT cgal = _cgal.exact();
+  const CGAL::Epeck::FT cgal = _cgal.exact();
   const auto interval = CGAL::to_interval(cgal);
   d = interval.first;
   do {
@@ -30,11 +30,11 @@ IGL_INLINE void igl::copyleft::cgal::assign_scalar(
 }
 
 IGL_INLINE void igl::copyleft::cgal::assign_scalar(
-  const typename CGAL::Epeck::FT & _cgal,
+  const CGAL::Epeck::FT & _cgal,
   float& d)
 {
   // FORCE evaluation of the exact type otherwise interval might be huge.
-  const typename CGAL::Epeck::FT cgal = _cgal.exact();
+  const CGAL::Epeck::FT cgal = _cgal.exact();
   const auto interval = CGAL::to_interval(cgal);
   d = interval.first;
   do {

+ 3 - 3
include/igl/copyleft/cgal/assign_scalar.h

@@ -20,13 +20,13 @@ namespace igl
       // Outputs:
       //   d  output scalar
       IGL_INLINE void assign_scalar(
-        const typename CGAL::Epeck::FT & cgal,
+        const CGAL::Epeck::FT & cgal,
         CGAL::Epeck::FT & d);
       IGL_INLINE void assign_scalar(
-        const typename CGAL::Epeck::FT & cgal,
+        const CGAL::Epeck::FT & cgal,
         double & d);
       IGL_INLINE void assign_scalar(
-        const typename CGAL::Epeck::FT & cgal,
+        const CGAL::Epeck::FT & cgal,
         float& d);
       IGL_INLINE void assign_scalar(
         const double & c,

+ 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;

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

@@ -201,7 +201,7 @@ void igl::copyleft::cgal::order_facets_around_edge(
     return order;
   };
 
-  Eigen::PlainObjectBase<DerivedI> positive_order, negative_order;
+  DerivedI positive_order, negative_order;
   order_facets_around_edge(V, F, s, d, positive_side, positive_order, debug);
   order_facets_around_edge(V, F, s, d, negative_side, negative_order, debug);
   std::vector<size_t> tie_positive_order = index_sort(tie_positive_oriented);

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

@@ -542,4 +542,6 @@ template void igl::copyleft::cgal::outer_hull_legacy<Eigen::Matrix<double, -1, 3
 template void igl::barycenter<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1> >&);
 #include "../../remove_unreferenced.cpp"
 template void igl::remove_unreferenced<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, 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::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, 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> >&);
+#include "../../slice.cpp"
+template void igl::slice<Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1> >, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1> > >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1> >&);
 #endif

+ 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
+

+ 1 - 1
include/igl/copyleft/progressive_hulls.cpp

@@ -23,7 +23,7 @@ IGL_INLINE bool igl::copyleft::progressive_hulls(
     V,
     F,
     progressive_hulls_cost_and_placement,
-    max_faces_stopping_condition(m,max_m),
+    max_faces_stopping_condition(m,(const int)m,max_m),
     U,
     G,
     J,

+ 4 - 6
include/igl/copyleft/tetgen/cdt.cpp

@@ -26,16 +26,14 @@ IGL_INLINE bool igl::copyleft::tetgen::cdt(
 {
   using namespace Eigen;
   using namespace std;
-  typedef Eigen::PlainObjectBase<DerivedV> MatrixXS;
-  typedef Eigen::PlainObjectBase<DerivedF> MatrixXI;
   // Effective input mesh
-  MatrixXS U;
-  MatrixXI G;
+  DerivedV U;
+  DerivedF G;
   if(param.use_bounding_box)
   {
     // Construct bounding box mesh
-    MatrixXS BV;
-    MatrixXI BF;
+    DerivedV BV;
+    DerivedF BF;
     bounding_box(V,BV,BF);
     // scale bounding box
     const RowVector3d mid = 

+ 52 - 0
include/igl/cylinder.cpp

@@ -0,0 +1,52 @@
+// 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 "cylinder.h"
+#include "PI.h"
+#include <cassert>
+#include <cmath>
+
+template <typename DerivedV, typename DerivedF>
+IGL_INLINE void igl::cylinder(
+  const int axis_devisions,
+  const int height_devisions,
+  Eigen::PlainObjectBase<DerivedV> & V,
+  Eigen::PlainObjectBase<DerivedF> & F)
+{
+  V.resize(axis_devisions*height_devisions,3);
+  F.resize(2*(axis_devisions*(height_devisions-1)),3);
+  int f = 0;
+  typedef typename DerivedV::Scalar Scalar;
+  for(int th = 0;th<axis_devisions;th++)
+  {
+    Scalar x = cos(2.*igl::PI*Scalar(th)/Scalar(axis_devisions));
+    Scalar y = sin(2.*igl::PI*Scalar(th)/Scalar(axis_devisions));
+    for(int h = 0;h<height_devisions;h++)
+    {
+      Scalar z = Scalar(h)/Scalar(height_devisions-1);
+      V(th+h*axis_devisions,0) = x;
+      V(th+h*axis_devisions,1) = y;
+      V(th+h*axis_devisions,2) = z;
+      if(h > 0)
+      {
+        F(f,0) = ((th+0)%axis_devisions)+(h-1)*axis_devisions;
+        F(f,1) = ((th+1)%axis_devisions)+(h-1)*axis_devisions;
+        F(f,2) = ((th+0)%axis_devisions)+(h+0)*axis_devisions;
+        f++;
+        F(f,0) = ((th+1)%axis_devisions)+(h-1)*axis_devisions;
+        F(f,1) = ((th+1)%axis_devisions)+(h+0)*axis_devisions;
+        F(f,2) = ((th+0)%axis_devisions)+(h+0)*axis_devisions;
+        f++;
+      }
+    }
+  }
+  assert(f == F.rows());
+}
+
+#ifdef IGL_STATIC_LIBRARY
+template void igl::cylinder<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(int, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+#endif

+ 33 - 0
include/igl/cylinder.h

@@ -0,0 +1,33 @@
+// 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_CYLINDER_H
+#define IGL_CYLINDER_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+namespace igl
+{
+  // Construct a triangle mesh of a cylinder (without caps)
+  //
+  // Inputs:
+  //   axis_devisions  number of vertices _around the cylinder_
+  //   height_devisions  number of vertices _up the cylinder_
+  // Outputs:
+  //   V  #V by 3 list of mesh vertex positions
+  //   F  #F by 3 list of triangle indices into V
+  //
+  template <typename DerivedV, typename DerivedF>
+  IGL_INLINE void cylinder(
+    const int axis_devisions,
+    const int height_devisions,
+    Eigen::PlainObjectBase<DerivedV> & V,
+    Eigen::PlainObjectBase<DerivedF> & F);
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "cylinder.cpp"
+#endif
+#endif

+ 189 - 44
include/igl/decimate.cpp

@@ -12,7 +12,8 @@
 #include "slice_mask.h"
 #include "slice.h"
 #include "connect_boundary_to_infinity.h"
-#include <iostream>
+#include "max_faces_stopping_condition.h"
+#include "shortest_edge_and_midpoint.h"
 
 IGL_INLINE bool igl::decimate(
   const Eigen::MatrixXd & V,
@@ -23,57 +24,20 @@ IGL_INLINE bool igl::decimate(
   Eigen::VectorXi & J,
   Eigen::VectorXi & I)
 {
-
   // Original number of faces
   const int orig_m = F.rows();
   // Tracking number of faces
   int m = F.rows();
-  const auto & shortest_edge_and_midpoint = [](
-    const int e,
-    const Eigen::MatrixXd & V,
-    const Eigen::MatrixXi & /*F*/,
-    const Eigen::MatrixXi & E,
-    const Eigen::VectorXi & /*EMAP*/,
-    const Eigen::MatrixXi & /*EF*/,
-    const Eigen::MatrixXi & /*EI*/,
-    double & cost,
-    Eigen::RowVectorXd & p)
-  {
-    cost = (V.row(E(e,0))-V.row(E(e,1))).norm();
-    p = 0.5*(V.row(E(e,0))+V.row(E(e,1)));
-  };
   typedef Eigen::MatrixXd DerivedV;
   typedef Eigen::MatrixXi DerivedF;
   DerivedV VO;
   DerivedF FO;
   igl::connect_boundary_to_infinity(V,F,VO,FO);
-  const auto & max_non_infinite_faces_stopping_condition = 
-    [max_m,orig_m,&m](
-      const Eigen::MatrixXd &,
-      const Eigen::MatrixXi &,
-      const Eigen::MatrixXi &,
-      const Eigen::VectorXi &,
-      const Eigen::MatrixXi &,
-      const Eigen::MatrixXi &,
-      const std::set<std::pair<double,int> > &,
-      const std::vector<std::set<std::pair<double,int> >::iterator > &,
-      const Eigen::MatrixXd &,
-      const int,
-      const int,
-      const int,
-      const int f1,
-      const int f2) -> bool
-    {
-      // Only subtract if we're collapsing a real face
-      if(f1 < orig_m) m-=1;
-      if(f2 < orig_m) m-=1;
-      return m<=(int)max_m;
-    };
   bool ret = decimate(
     VO,
     FO,
     shortest_edge_and_midpoint,
-    max_non_infinite_faces_stopping_condition,
+    max_faces_stopping_condition(m,orig_m,max_m),
     U,
     G,
     J,
@@ -133,17 +97,196 @@ IGL_INLINE bool igl::decimate(
   Eigen::VectorXi & I
   )
 {
+  const auto always_try = [](
+    const Eigen::MatrixXd &                                         ,/*V*/
+    const Eigen::MatrixXi &                                         ,/*F*/
+    const Eigen::MatrixXi &                                         ,/*E*/
+    const Eigen::VectorXi &                                         ,/*EMAP*/
+    const Eigen::MatrixXi &                                         ,/*EF*/
+    const Eigen::MatrixXi &                                         ,/*EI*/
+    const std::set<std::pair<double,int> > &                        ,/*Q*/
+    const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
+    const Eigen::MatrixXd &                                         ,/*C*/
+    const int                                                        /*e*/
+    ) -> bool { return true;};
+  const auto never_care = [](
+    const Eigen::MatrixXd &                                         ,   /*V*/
+    const Eigen::MatrixXi &                                         ,   /*F*/
+    const Eigen::MatrixXi &                                         ,   /*E*/
+    const Eigen::VectorXi &                                         ,/*EMAP*/
+    const Eigen::MatrixXi &                                         ,  /*EF*/
+    const Eigen::MatrixXi &                                         ,  /*EI*/
+    const std::set<std::pair<double,int> > &                        ,   /*Q*/
+    const std::vector<std::set<std::pair<double,int> >::iterator > &, /*Qit*/
+    const Eigen::MatrixXd &                                         ,   /*C*/
+    const int                                                       ,   /*e*/
+    const int                                                       ,  /*e1*/
+    const int                                                       ,  /*e2*/
+    const int                                                       ,  /*f1*/
+    const int                                                       ,  /*f2*/
+    const bool                                                  /*collapsed*/
+    )-> void { };
+  return igl::decimate(
+    OV,OF,cost_and_placement,stopping_condition,always_try,never_care,U,G,J,I);
+}
+
+IGL_INLINE bool igl::decimate(
+  const Eigen::MatrixXd & OV,
+  const Eigen::MatrixXi & OF,
+  const std::function<void(
+    const int,
+    const Eigen::MatrixXd &,
+    const Eigen::MatrixXi &,
+    const Eigen::MatrixXi &,
+    const Eigen::VectorXi &,
+    const Eigen::MatrixXi &,
+    const Eigen::MatrixXi &,
+    double &,
+    Eigen::RowVectorXd &)> & cost_and_placement,
+  const std::function<bool(
+      const Eigen::MatrixXd &,
+      const Eigen::MatrixXi &,
+      const Eigen::MatrixXi &,
+      const Eigen::VectorXi &,
+      const Eigen::MatrixXi &,
+      const Eigen::MatrixXi &,
+      const std::set<std::pair<double,int> > &,
+      const std::vector<std::set<std::pair<double,int> >::iterator > &,
+      const Eigen::MatrixXd &,
+      const int,
+      const int,
+      const int,
+      const int,
+      const int)> & stopping_condition,
+    const std::function<bool(
+      const Eigen::MatrixXd &                                         ,/*V*/
+      const Eigen::MatrixXi &                                         ,/*F*/
+      const Eigen::MatrixXi &                                         ,/*E*/
+      const Eigen::VectorXi &                                         ,/*EMAP*/
+      const Eigen::MatrixXi &                                         ,/*EF*/
+      const Eigen::MatrixXi &                                         ,/*EI*/
+      const std::set<std::pair<double,int> > &                        ,/*Q*/
+      const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
+      const Eigen::MatrixXd &                                         ,/*C*/
+      const int                                                        /*e*/
+      )> & pre_collapse,
+    const std::function<void(
+      const Eigen::MatrixXd &                                         ,   /*V*/
+      const Eigen::MatrixXi &                                         ,   /*F*/
+      const Eigen::MatrixXi &                                         ,   /*E*/
+      const Eigen::VectorXi &                                         ,/*EMAP*/
+      const Eigen::MatrixXi &                                         ,  /*EF*/
+      const Eigen::MatrixXi &                                         ,  /*EI*/
+      const std::set<std::pair<double,int> > &                        ,   /*Q*/
+      const std::vector<std::set<std::pair<double,int> >::iterator > &, /*Qit*/
+      const Eigen::MatrixXd &                                         ,   /*C*/
+      const int                                                       ,   /*e*/
+      const int                                                       ,  /*e1*/
+      const int                                                       ,  /*e2*/
+      const int                                                       ,  /*f1*/
+      const int                                                       ,  /*f2*/
+      const bool                                                  /*collapsed*/
+      )> & post_collapse,
+  Eigen::MatrixXd & U,
+  Eigen::MatrixXi & G,
+  Eigen::VectorXi & J,
+  Eigen::VectorXi & I
+  )
+{
+  using namespace Eigen;
+  using namespace std;
+  VectorXi EMAP;
+  MatrixXi E,EF,EI;
+  edge_flaps(OF,E,EMAP,EF,EI);
+  return igl::decimate(
+    OV,OF,
+    cost_and_placement,stopping_condition,pre_collapse,post_collapse,
+    E,EMAP,EF,EI,
+    U,G,J,I);
+}
+
+
+IGL_INLINE bool igl::decimate(
+  const Eigen::MatrixXd & OV,
+  const Eigen::MatrixXi & OF,
+  const std::function<void(
+    const int,
+    const Eigen::MatrixXd &,
+    const Eigen::MatrixXi &,
+    const Eigen::MatrixXi &,
+    const Eigen::VectorXi &,
+    const Eigen::MatrixXi &,
+    const Eigen::MatrixXi &,
+    double &,
+    Eigen::RowVectorXd &)> & cost_and_placement,
+  const std::function<bool(
+      const Eigen::MatrixXd &,
+      const Eigen::MatrixXi &,
+      const Eigen::MatrixXi &,
+      const Eigen::VectorXi &,
+      const Eigen::MatrixXi &,
+      const Eigen::MatrixXi &,
+      const std::set<std::pair<double,int> > &,
+      const std::vector<std::set<std::pair<double,int> >::iterator > &,
+      const Eigen::MatrixXd &,
+      const int,
+      const int,
+      const int,
+      const int,
+      const int)> & stopping_condition,
+    const std::function<bool(
+      const Eigen::MatrixXd &                                         ,/*V*/
+      const Eigen::MatrixXi &                                         ,/*F*/
+      const Eigen::MatrixXi &                                         ,/*E*/
+      const Eigen::VectorXi &                                         ,/*EMAP*/
+      const Eigen::MatrixXi &                                         ,/*EF*/
+      const Eigen::MatrixXi &                                         ,/*EI*/
+      const std::set<std::pair<double,int> > &                        ,/*Q*/
+      const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
+      const Eigen::MatrixXd &                                         ,/*C*/
+      const int                                                        /*e*/
+      )> & pre_collapse,
+    const std::function<void(
+      const Eigen::MatrixXd &                                         ,   /*V*/
+      const Eigen::MatrixXi &                                         ,   /*F*/
+      const Eigen::MatrixXi &                                         ,   /*E*/
+      const Eigen::VectorXi &                                         ,/*EMAP*/
+      const Eigen::MatrixXi &                                         ,  /*EF*/
+      const Eigen::MatrixXi &                                         ,  /*EI*/
+      const std::set<std::pair<double,int> > &                        ,   /*Q*/
+      const std::vector<std::set<std::pair<double,int> >::iterator > &, /*Qit*/
+      const Eigen::MatrixXd &                                         ,   /*C*/
+      const int                                                       ,   /*e*/
+      const int                                                       ,  /*e1*/
+      const int                                                       ,  /*e2*/
+      const int                                                       ,  /*f1*/
+      const int                                                       ,  /*f2*/
+      const bool                                                  /*collapsed*/
+      )> & post_collapse,
+  const Eigen::MatrixXi & OE,
+  const Eigen::VectorXi & OEMAP,
+  const Eigen::MatrixXi & OEF,
+  const Eigen::MatrixXi & OEI,
+  Eigen::MatrixXd & U,
+  Eigen::MatrixXi & G,
+  Eigen::VectorXi & J,
+  Eigen::VectorXi & I
+  )
+{
+
+  // Decimate 1
   using namespace Eigen;
   using namespace std;
   // Working copies
   Eigen::MatrixXd V = OV;
   Eigen::MatrixXi F = OF;
-  VectorXi EMAP;
-  MatrixXi E,EF,EI;
+  Eigen::MatrixXi E = OE;
+  Eigen::VectorXi EMAP = OEMAP;
+  Eigen::MatrixXi EF = OEF;
+  Eigen::MatrixXi EI = OEI;
   typedef std::set<std::pair<double,int> > PriorityQueue;
   PriorityQueue Q;
   std::vector<PriorityQueue::iterator > Qit;
-  edge_flaps(F,E,EMAP,EF,EI);
   Qit.resize(E.rows());
   // If an edge were collapsed, we'd collapse it to these points:
   MatrixXd C(E.rows(),V.cols());
@@ -155,9 +298,9 @@ IGL_INLINE bool igl::decimate(
     C.row(e) = p;
     Qit[e] = Q.insert(std::pair<double,int>(cost,e)).first;
   }
-
   int prev_e = -1;
   bool clean_finish = false;
+
   while(true)
   {
     if(Q.empty())
@@ -170,7 +313,9 @@ IGL_INLINE bool igl::decimate(
       break;
     }
     int e,e1,e2,f1,f2;
-    if(collapse_edge(cost_and_placement,V,F,E,EMAP,EF,EI,Q,Qit,C,e,e1,e2,f1,f2))
+    if(collapse_edge(
+       cost_and_placement, pre_collapse, post_collapse,
+       V,F,E,EMAP,EF,EI,Q,Qit,C,e,e1,e2,f1,f2))
     {
       if(stopping_condition(V,F,E,EMAP,EF,EI,Q,Qit,C,e,e1,e2,f1,f2))
       {

+ 146 - 0
include/igl/decimate.h

@@ -100,6 +100,152 @@ namespace igl
     Eigen::VectorXi & J,
     Eigen::VectorXi & I);
 
+  // Inputs:
+  //   pre_collapse  callback called with index of edge whose collapse is about
+  //     to be attempted (see collapse_edge)
+  //   post_collapse  callback called with index of edge whose collapse was
+  //     just attempted and a flag revealing whether this was successful (see
+  //     collapse_edge)
+  IGL_INLINE bool decimate(
+    const Eigen::MatrixXd & V,
+    const Eigen::MatrixXi & F,
+    const std::function<void(
+      const int              /*e*/,
+      const Eigen::MatrixXd &/*V*/,
+      const Eigen::MatrixXi &/*F*/,
+      const Eigen::MatrixXi &/*E*/,
+      const Eigen::VectorXi &/*EMAP*/,
+      const Eigen::MatrixXi &/*EF*/,
+      const Eigen::MatrixXi &/*EI*/,
+      double &               /*cost*/,
+      Eigen::RowVectorXd &   /*p*/
+      )> & cost_and_placement,
+    const std::function<bool(
+      const Eigen::MatrixXd &                                         ,/*V*/
+      const Eigen::MatrixXi &                                         ,/*F*/
+      const Eigen::MatrixXi &                                         ,/*E*/
+      const Eigen::VectorXi &                                         ,/*EMAP*/
+      const Eigen::MatrixXi &                                         ,/*EF*/
+      const Eigen::MatrixXi &                                         ,/*EI*/
+      const std::set<std::pair<double,int> > &                        ,/*Q*/
+      const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
+      const Eigen::MatrixXd &                                         ,/*C*/
+      const int                                                       ,/*e*/
+      const int                                                       ,/*e1*/
+      const int                                                       ,/*e2*/
+      const int                                                       ,/*f1*/
+      const int                                                        /*f2*/
+      )> & stopping_condition,
+    const std::function<bool(
+      const Eigen::MatrixXd &                                         ,/*V*/
+      const Eigen::MatrixXi &                                         ,/*F*/
+      const Eigen::MatrixXi &                                         ,/*E*/
+      const Eigen::VectorXi &                                         ,/*EMAP*/
+      const Eigen::MatrixXi &                                         ,/*EF*/
+      const Eigen::MatrixXi &                                         ,/*EI*/
+      const std::set<std::pair<double,int> > &                        ,/*Q*/
+      const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
+      const Eigen::MatrixXd &                                         ,/*C*/
+      const int                                                        /*e*/
+      )> & pre_collapse,
+    const std::function<void(
+      const Eigen::MatrixXd &                                         ,   /*V*/
+      const Eigen::MatrixXi &                                         ,   /*F*/
+      const Eigen::MatrixXi &                                         ,   /*E*/
+      const Eigen::VectorXi &                                         ,/*EMAP*/
+      const Eigen::MatrixXi &                                         ,  /*EF*/
+      const Eigen::MatrixXi &                                         ,  /*EI*/
+      const std::set<std::pair<double,int> > &                        ,   /*Q*/
+      const std::vector<std::set<std::pair<double,int> >::iterator > &, /*Qit*/
+      const Eigen::MatrixXd &                                         ,   /*C*/
+      const int                                                       ,   /*e*/
+      const int                                                       ,  /*e1*/
+      const int                                                       ,  /*e2*/
+      const int                                                       ,  /*f1*/
+      const int                                                       ,  /*f2*/
+      const bool                                                  /*collapsed*/
+      )> & post_collapse,
+    Eigen::MatrixXd & U,
+    Eigen::MatrixXi & G,
+    Eigen::VectorXi & J,
+    Eigen::VectorXi & I);
+
+  // Inputs:
+  //   EMAP #F*3 list of indices into E, mapping each directed edge to unique
+  //     unique edge in E
+  //   EF  #E by 2 list of edge flaps, EF(e,0)=f means e=(i-->j) is the edge of
+  //     F(f,:) opposite the vth corner, where EI(e,0)=v. Similarly EF(e,1) "
+  //     e=(j->i)
+  //   EI  #E by 2 list of edge flap corners (see above).
+
+  IGL_INLINE bool decimate(
+    const Eigen::MatrixXd & V,
+    const Eigen::MatrixXi & F,
+    const std::function<void(
+      const int              /*e*/,
+      const Eigen::MatrixXd &/*V*/,
+      const Eigen::MatrixXi &/*F*/,
+      const Eigen::MatrixXi &/*E*/,
+      const Eigen::VectorXi &/*EMAP*/,
+      const Eigen::MatrixXi &/*EF*/,
+      const Eigen::MatrixXi &/*EI*/,
+      double &               /*cost*/,
+      Eigen::RowVectorXd &   /*p*/
+      )> & cost_and_placement,
+    const std::function<bool(
+      const Eigen::MatrixXd &                                         ,/*V*/
+      const Eigen::MatrixXi &                                         ,/*F*/
+      const Eigen::MatrixXi &                                         ,/*E*/
+      const Eigen::VectorXi &                                         ,/*EMAP*/
+      const Eigen::MatrixXi &                                         ,/*EF*/
+      const Eigen::MatrixXi &                                         ,/*EI*/
+      const std::set<std::pair<double,int> > &                        ,/*Q*/
+      const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
+      const Eigen::MatrixXd &                                         ,/*C*/
+      const int                                                       ,/*e*/
+      const int                                                       ,/*e1*/
+      const int                                                       ,/*e2*/
+      const int                                                       ,/*f1*/
+      const int                                                        /*f2*/
+      )> & stopping_condition,
+    const std::function<bool(
+      const Eigen::MatrixXd &                                         ,/*V*/
+      const Eigen::MatrixXi &                                         ,/*F*/
+      const Eigen::MatrixXi &                                         ,/*E*/
+      const Eigen::VectorXi &                                         ,/*EMAP*/
+      const Eigen::MatrixXi &                                         ,/*EF*/
+      const Eigen::MatrixXi &                                         ,/*EI*/
+      const std::set<std::pair<double,int> > &                        ,/*Q*/
+      const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
+      const Eigen::MatrixXd &                                         ,/*C*/
+      const int                                                        /*e*/
+      )> & pre_collapse,
+    const std::function<void(
+      const Eigen::MatrixXd &                                         ,   /*V*/
+      const Eigen::MatrixXi &                                         ,   /*F*/
+      const Eigen::MatrixXi &                                         ,   /*E*/
+      const Eigen::VectorXi &                                         ,/*EMAP*/
+      const Eigen::MatrixXi &                                         ,  /*EF*/
+      const Eigen::MatrixXi &                                         ,  /*EI*/
+      const std::set<std::pair<double,int> > &                        ,   /*Q*/
+      const std::vector<std::set<std::pair<double,int> >::iterator > &, /*Qit*/
+      const Eigen::MatrixXd &                                         ,   /*C*/
+      const int                                                       ,   /*e*/
+      const int                                                       ,  /*e1*/
+      const int                                                       ,  /*e2*/
+      const int                                                       ,  /*f1*/
+      const int                                                       ,  /*f2*/
+      const bool                                                  /*collapsed*/
+      )> & post_collapse,
+    const Eigen::MatrixXi & E,
+    const Eigen::VectorXi & EMAP,
+    const Eigen::MatrixXi & EF,
+    const Eigen::MatrixXi & EI,
+    Eigen::MatrixXd & U,
+    Eigen::MatrixXi & G,
+    Eigen::VectorXi & J,
+    Eigen::VectorXi & I);
+
 }
 
 #ifndef IGL_STATIC_LIBRARY

+ 1 - 0
include/igl/deform_skeleton.h

@@ -10,6 +10,7 @@
 #include "igl_inline.h"
 #include <Eigen/Core>
 #include <Eigen/Geometry>
+#include <Eigen/StdVector>
 #include <vector>
 namespace igl
 {

+ 1 - 0
include/igl/directed_edge_orientations.h

@@ -12,6 +12,7 @@
 #include <Eigen/Core>
 #include <Eigen/Geometry>
 #include <Eigen/StdVector>
+#include <vector>
 
 namespace igl
 {

+ 2 - 2
include/igl/dot_row.cpp

@@ -8,7 +8,7 @@
 #include "igl/dot_row.h"
 
 template <typename DerivedV>
-IGL_INLINE Eigen::PlainObjectBase<DerivedV> igl::dot_row(
+IGL_INLINE DerivedV igl::dot_row(
   const Eigen::PlainObjectBase<DerivedV>& A,
   const Eigen::PlainObjectBase<DerivedV>& B
   )
@@ -22,5 +22,5 @@ IGL_INLINE Eigen::PlainObjectBase<DerivedV> igl::dot_row(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // generated by autoexplicit.sh
-template Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > igl::dot_row<Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&);
+template Eigen::Matrix<double, -1, -1, 0, -1, -1> igl::dot_row<Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&);
 #endif

+ 1 - 1
include/igl/dot_row.h

@@ -23,7 +23,7 @@ namespace igl
   //   d a column vector with r entries that contains the dot product of each corresponding row of A and B
   //
   template <typename DerivedV>
-  IGL_INLINE Eigen::PlainObjectBase<DerivedV> dot_row(
+  IGL_INLINE DerivedV dot_row(
     const Eigen::PlainObjectBase<DerivedV>& A,
     const Eigen::PlainObjectBase<DerivedV>& B);
 

+ 1 - 1
include/igl/doublearea.cpp

@@ -43,7 +43,7 @@ IGL_INLINE void igl::doublearea(
   {
     case 3:
     {
-      dblA = Eigen::PlainObjectBase<DeriveddblA>::Zero(m,1);
+      dblA = DeriveddblA::Zero(m,1);
       for(size_t f = 0;f<m;f++)
       {
         for(int d = 0;d<3;d++)

+ 1 - 1
include/igl/face_areas.cpp

@@ -16,7 +16,7 @@ IGL_INLINE void igl::face_areas(
   Eigen::PlainObjectBase<DerivedA>& A)
 {
   assert(T.cols() == 4);
-  typename Eigen::PlainObjectBase<DerivedA> L;
+  DerivedA L;
   edge_lengths(V,T,L);
   return face_areas(L,A);
 }

+ 1 - 1
include/igl/floor.cpp

@@ -15,7 +15,7 @@ IGL_INLINE void igl::floor(
   Eigen::PlainObjectBase<DerivedY>& Y)
 {
   using namespace std;
-  //Y = Eigen::PlainObjectBase<DerivedY>::Zero(m,n);
+  //Y = DerivedY::Zero(m,n);
 //#pragma omp parallel for
   //for(int i = 0;i<m;i++)
   //{

+ 4 - 0
include/igl/hausdorff.cpp

@@ -35,3 +35,7 @@ IGL_INLINE void igl::hausdorff(
   const Scalar dab = sqr_DAB.maxCoeff();
   d = sqrt(std::max(dba,dab));
 }
+
+#ifdef IGL_STATIC_LIBRARY
+template void igl::hausdorff<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>, double>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, double&);
+#endif

+ 11 - 2
include/igl/hausdorff.h

@@ -19,6 +19,15 @@ namespace igl
   // d(A,B) = max ( max min d(a,b) , max min d(b,a) )
   //                a∈A b∈B          b∈B a∈A
   //
+  // Known issue: This is only computing max(min(va,B),min(vb,A)). This is
+  // better than max(min(va,Vb),min(vb,Va)). This (at least) is missing
+  // "edge-edge" cases like the distance between the two different
+  // triangulations of a non-planar quad in 3D. Even simpler, consider the
+  // Hausdorff distance between the non-convex, block letter V polygon (with 7
+  // vertices) in 2D and its convex hull. The Hausdorff distance is defined by
+  // the midpoint in the middle of the segment across the concavity and some
+  // non-vertex point _on the edge_ of the V.
+  //
   // Inputs:
   //   VA  #VA by 3 list of vertex positions
   //   FA  #FA by 3 list of face indices into VA
@@ -26,8 +35,8 @@ namespace igl
   //   FB  #FB by 3 list of face indices into VB
   // Outputs:
   //   d  hausdorff distance
-  //   pair  2 by 3 list of "determiner points" so that pair(1,:) is from A and
-  //     pair(2,:) is from B
+  //   //pair  2 by 3 list of "determiner points" so that pair(1,:) is from A
+  //   //  and pair(2,:) is from B
   //
   template <
     typename DerivedVA, 

+ 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
+

+ 7 - 1
include/igl/jet.cpp

@@ -118,9 +118,15 @@ IGL_INLINE void igl::jet(
   Eigen::PlainObjectBase<DerivedC> & C)
 {
   C.resize(Z.rows(),3);
+  double denom = (max_z-min_z);
+  denom = denom==0?1:denom;
   for(int r = 0;r<Z.rows();r++)
   {
-    jet((-min_z+Z(r,0))/(max_z-min_z),C(r,0),C(r,1),C(r,2));
+    jet(
+      (typename DerivedC::Scalar)((-min_z+Z(r,0))/denom),
+      C(r,0),
+      C(r,1),
+      C(r,2));
   }
 }
 

+ 1 - 1
include/igl/jet.h

@@ -37,7 +37,7 @@ namespace igl
   template <typename T>
   IGL_INLINE void jet(const T f, T & r, T & g, T & b);
   // Inputs:
-  //   Z  #Z list of factos 
+  //   Z  #Z list of factors
   //   normalize  whether to normalize Z to be tightly between [0,1]
   // Outputs:
   //   C  #C by 3 list of rgb colors

+ 5 - 6
include/igl/line_field_missmatch.cpp

@@ -31,16 +31,15 @@ public:
     const Eigen::PlainObjectBase<DerivedF> &F;
     const Eigen::PlainObjectBase<DerivedV> &PD1;
     const Eigen::PlainObjectBase<DerivedV> &PD2;
-//#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
-    Eigen::PlainObjectBase<DerivedV> N;
+    DerivedV N;
 
 private:
     // internal
     std::vector<bool> V_border; // bool
     std::vector<std::vector<int> > VF;
     std::vector<std::vector<int> > VFi;
-    Eigen::PlainObjectBase<DerivedF> TT;
-    Eigen::PlainObjectBase<DerivedF> TTi;
+    DerivedF TT;
+    DerivedF TTi;
 
 
 private:
@@ -123,8 +122,8 @@ IGL_INLINE void igl::line_field_missmatch(const Eigen::PlainObjectBase<DerivedV>
                                 const bool isCombed,
                                 Eigen::PlainObjectBase<DerivedO> &missmatch)
 {
-    Eigen::PlainObjectBase<DerivedV> PD1_combed;
-    Eigen::PlainObjectBase<DerivedV> PD2_combed;
+    DerivedV PD1_combed;
+    DerivedV PD2_combed;
 
     if (!isCombed)
         igl::comb_line_field(V,F,PD1,PD1_combed);

+ 5 - 3
include/igl/list_to_matrix.cpp

@@ -86,10 +86,10 @@ IGL_INLINE bool igl::list_to_matrix(const std::vector<T > & V,Eigen::PlainObject
   {
     //fprintf(stderr,"Error: list_to_matrix() list is empty()\n");
     //return false;
-    if(Eigen::PlainObjectBase<Derived>::ColsAtCompileTime == 1)
+    if(Derived::ColsAtCompileTime == 1)
     {
       M.resize(0,1);
-    }else if(Eigen::PlainObjectBase<Derived>::RowsAtCompileTime == 1)
+    }else if(Derived::RowsAtCompileTime == 1)
     {
       M.resize(1,0);
     }else
@@ -99,7 +99,7 @@ IGL_INLINE bool igl::list_to_matrix(const std::vector<T > & V,Eigen::PlainObject
     return true;
   }
   // Resize output
-  if(Eigen::PlainObjectBase<Derived>::RowsAtCompileTime == 1)
+  if(Derived::RowsAtCompileTime == 1)
   {
     M.resize(1,m);
   }else
@@ -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> > &);
@@ -160,5 +161,6 @@ template bool igl::list_to_matrix<double, Eigen::Matrix<double, -1, -1, 0, -1, -
 template bool igl::list_to_matrix<double, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(std::vector<double, std::allocator<double> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -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<unsigned __int64, class Eigen::Matrix<int, -1, -1, 0, -1, -1> >(class std::vector<unsigned __int64, class std::allocator<unsigned __int64> > const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1> > &);
+template bool igl::list_to_matrix<unsigned __int64,class Eigen::Matrix<long,-1,1,0,-1,1> >(class std::vector<unsigned __int64,class std::allocator<unsigned __int64> > const &,class Eigen::PlainObjectBase<class Eigen::Matrix<long,-1,1,0,-1,1> > &);
 #endif
 #endif

+ 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

+ 1 - 0
include/igl/matrix_to_list.cpp

@@ -68,4 +68,5 @@ template void igl::matrix_to_list<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen:
 template void igl::matrix_to_list<Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, std::vector<Eigen::Matrix<int, -1, 1, 0, -1, 1>::Scalar, std::allocator<Eigen::Matrix<int, -1, 1, 0, -1, 1>::Scalar> >&);
 template void igl::matrix_to_list<Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, std::vector<std::vector<Eigen::Matrix<int, -1, 1, 0, -1, 1>::Scalar, std::allocator<Eigen::Matrix<int, -1, 1, 0, -1, 1>::Scalar> >, std::allocator<std::vector<Eigen::Matrix<int, -1, 1, 0, -1, 1>::Scalar, std::allocator<Eigen::Matrix<int, -1, 1, 0, -1, 1>::Scalar> > > >&);
 template void igl::matrix_to_list<Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, std::vector<Eigen::Matrix<double, -1, -1, 0, -1, -1>::Scalar, std::allocator<Eigen::Matrix<double, -1, -1, 0, -1, -1>::Scalar> >&);
+template void igl::matrix_to_list<Eigen::Matrix<int, 1, -1, 1, 1, -1> >(Eigen::MatrixBase<Eigen::Matrix<int, 1, -1, 1, 1, -1> > const&, std::vector<Eigen::Matrix<int, 1, -1, 1, 1, -1>::Scalar, std::allocator<Eigen::Matrix<int, 1, -1, 1, 1, -1>::Scalar> >&);
 #endif

+ 10 - 3
include/igl/matrix_to_list.h

@@ -14,22 +14,29 @@
 namespace igl
 {
   // Convert a matrix to a list (std::vector) of row vectors of the same size
+  //
   // Template: 
   //   Mat  Matrix type, must implement:
   //     .resize(m,n)
   //     .row(i) = Row
   //   T  type that can be safely cast to type in Mat via '='
   // Inputs:
-  //   V  a m-long list of vectors of size n
-  // Outputs:
   //   M  an m by n matrix
+  // Outputs:
+  //   V  a m-long list of vectors of size n
   //
   // See also: list_to_matrix
   template <typename DerivedM>
   IGL_INLINE void matrix_to_list(
     const Eigen::MatrixBase<DerivedM> & M, 
     std::vector<std::vector<typename DerivedM::Scalar > > & V);
-  // For vector input
+  // Convert a matrix to a list (std::vector) of elements in column-major
+  // ordering.
+  //
+  // Inputs:
+  //    M  an m by n matrix
+  // Outputs:
+  //    V  an m*n list of elements
   template <typename DerivedM>
   IGL_INLINE void matrix_to_list(
     const Eigen::MatrixBase<DerivedM> & M, 

+ 16 - 5
include/igl/max_faces_stopping_condition.cpp

@@ -1,7 +1,15 @@
+// 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 "max_faces_stopping_condition.h"
 
 IGL_INLINE void igl::max_faces_stopping_condition(
   int & m,
+  const int orig_m,
   const int max_m,
   std::function<bool(
     const Eigen::MatrixXd &,
@@ -20,7 +28,7 @@ IGL_INLINE void igl::max_faces_stopping_condition(
     const int)> & stopping_condition)
 {
   stopping_condition = 
-    [max_m,&m](
+    [orig_m,max_m,&m](
     const Eigen::MatrixXd &,
     const Eigen::MatrixXi &,
     const Eigen::MatrixXi &,
@@ -33,10 +41,12 @@ IGL_INLINE void igl::max_faces_stopping_condition(
     const int,
     const int,
     const int,
-    const int,
-    const int)->bool
+    const int f1,
+    const int f2)->bool
     {
-      m-=2;
+      // Only subtract if we're collapsing a real face
+      if(f1 < orig_m) m-=1;
+      if(f2 < orig_m) m-=1;
       return m<=(int)max_m;
     };
 }
@@ -59,6 +69,7 @@ IGL_INLINE
     const int)> 
   igl::max_faces_stopping_condition(
     int & m,
+    const int orig_m,
     const int max_m)
 {
   std::function<bool(
@@ -77,6 +88,6 @@ IGL_INLINE
     const int,
     const int)> stopping_condition;
   max_faces_stopping_condition(
-      m,max_m,stopping_condition);
+      m,orig_m,max_m,stopping_condition);
   return stopping_condition;
 }

+ 5 - 0
include/igl/max_faces_stopping_condition.h

@@ -20,12 +20,16 @@ namespace igl
   // Inputs:
   //   m  reference to working variable initially should be set to current
   //    number of faces.
+  //   orig_m  number (size) of original face list _**not**_ including any
+  //     faces added to handle phony boundary faces connecting to point at
+  //     infinity. For closed meshes it's safe to set this to F.rows()
   //   max_m  maximum number of faces
   // Outputs:
   //   stopping_condition
   //
   IGL_INLINE void max_faces_stopping_condition(
     int & m,
+    const int orig_m,
     const int max_m,
     std::function<bool(
       const Eigen::MatrixXd &,
@@ -60,6 +64,7 @@ namespace igl
       const int)> 
     max_faces_stopping_condition(
       int & m,
+      const int orign_m,
       const int max_m);
 }
 

+ 10 - 10
include/igl/min_quad_with_fixed.cpp

@@ -486,15 +486,15 @@ IGL_INLINE bool igl::min_quad_with_fixed_solve(
   }else
   {
     assert(data.solver_type == min_quad_with_fixed_data<T>::QR_LLT);
-    PlainObjectBase<DerivedBeq> eff_Beq;
+    DerivedBeq eff_Beq;
     // Adjust Aeq rhs to include known parts
     eff_Beq =
       //data.AeqTQR.colsPermutation().transpose() * (-data.Aeqk * Y + Beq);
       data.AeqTET * (-data.Aeqk * Y + Beq);
     // Where did this -0.5 come from? Probably the same place as above.
-    PlainObjectBase<DerivedB> Bu;
+    DerivedB Bu;
     slice(B,data.unknown,Bu);
-    PlainObjectBase<DerivedB> NB;
+    DerivedB NB;
     NB = -0.5*(Bu + data.preY * Y);
     // Trim eff_Beq
     const int nc = data.AeqTQR.rank();
@@ -502,24 +502,24 @@ IGL_INLINE bool igl::min_quad_with_fixed_solve(
     eff_Beq = eff_Beq.topLeftCorner(nc,1).eval();
     data.AeqTR1T.template triangularView<Lower>().solveInPlace(eff_Beq);
     // Now eff_Beq = (data.AeqTR1T \ (data.AeqTET * (-data.Aeqk * Y + Beq)))
-    PlainObjectBase<DerivedB> lambda_0;
+    DerivedB lambda_0;
     lambda_0 = data.AeqTQ1 * eff_Beq;
     //cout<<matlab_format(lambda_0,"lambda_0")<<endl;
-    PlainObjectBase<DerivedB> QRB;
+    DerivedB QRB;
     QRB = -data.AeqTQ2T * (data.Auu * lambda_0) + data.AeqTQ2T * NB;
-    PlainObjectBase<Derivedsol> lambda;
+    Derivedsol lambda;
     lambda = data.llt.solve(QRB);
     // prepare output
-    PlainObjectBase<Derivedsol> solu;
+    Derivedsol solu;
     solu = data.AeqTQ2 * lambda + lambda_0;
     //  http://www.math.uh.edu/~rohop/fall_06/Chapter3.pdf
-    PlainObjectBase<Derivedsol> solLambda;
+    Derivedsol solLambda;
     {
-      PlainObjectBase<Derivedsol> temp1,temp2;
+      Derivedsol temp1,temp2;
       temp1 = (data.AeqTQ1T * NB - data.AeqTQ1T * data.Auu * solu);
       data.AeqTR1.template triangularView<Upper>().solveInPlace(temp1);
       //cout<<matlab_format(temp1,"temp1")<<endl;
-      temp2 = PlainObjectBase<Derivedsol>::Zero(neq,1);
+      temp2 = Derivedsol::Zero(neq,1);
       temp2.topLeftCorner(nc,1) = temp1;
       //solLambda = data.AeqTQR.colsPermutation() * temp2;
       solLambda = data.AeqTE * temp2;

+ 1 - 1
include/igl/on_boundary.cpp

@@ -123,7 +123,7 @@ IGL_INLINE void igl::on_boundary(
   using namespace std;
   using namespace Eigen;
   // Cop out: use vector of vectors version
-  vector<vector<typename Eigen::PlainObjectBase<DerivedT>::Scalar> > vT;
+  vector<vector<typename DerivedT::Scalar> > vT;
   matrix_to_list(T,vT);
   vector<bool> vI;
   vector<vector<bool> > vC;

+ 1 - 1
include/igl/orient_outward.cpp

@@ -40,7 +40,7 @@ IGL_INLINE void igl::orient_outward(
   {
     FF = F;
   }
-  PlainObjectBase<DerivedV> N,BC,BCmean;
+  DerivedV N,BC,BCmean;
   Matrix<typename DerivedV::Scalar,Dynamic,1> A;
   VectorXd totA(num_cc), dot(num_cc);
   Matrix<typename DerivedV::Scalar,3,1> Z(1,1,1);

+ 5 - 1
include/igl/parula.cpp

@@ -57,7 +57,11 @@ IGL_INLINE void igl::parula(
   denom = denom==0?1:denom;
   for(int r = 0;r<Z.rows();r++)
   {
-    parula((-min_z+Z(r,0))/denom,C(r,0),C(r,1),C(r,2));
+    parula(
+      (typename DerivedC::Scalar)((-min_z+Z(r,0))/denom),
+      C(r,0),
+      C(r,1),
+      C(r,2));
   }
 }
 

+ 1 - 1
include/igl/per_vertex_attribute_smoothing.cpp

@@ -15,7 +15,7 @@ IGL_INLINE void igl::per_vertex_attribute_smoothing(
     Eigen::PlainObjectBase<DerivedV> & Aout)
 {
     std::vector<double> denominator(Ain.rows(), 0);
-    Aout = Eigen::PlainObjectBase<DerivedV>::Zero(Ain.rows(), Ain.cols());
+    Aout = DerivedV::Zero(Ain.rows(), Ain.cols());
     for (int i = 0; i < F.rows(); ++i) {
         for (int j = 0; j < 3; ++j) {
             int j1 = (j + 1) % 3;

+ 157 - 0
include/igl/per_vertex_point_to_plane_quadrics.cpp

@@ -0,0 +1,157 @@
+// 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 "per_vertex_point_to_plane_quadrics.h"
+#include "quadric_binary_plus_operator.h"
+#include <Eigen/QR>
+#include <cassert>
+#include <cmath>
+
+
+IGL_INLINE void igl::per_vertex_point_to_plane_quadrics(
+  const Eigen::MatrixXd & V,
+  const Eigen::MatrixXi & F,
+  const Eigen::MatrixXi & EMAP,
+  const Eigen::MatrixXi & EF,
+  const Eigen::MatrixXi & EI,
+  std::vector<
+    std::tuple<Eigen::MatrixXd,Eigen::RowVectorXd,double> > & quadrics)
+{
+  using namespace std;
+  typedef std::tuple<Eigen::MatrixXd,Eigen::RowVectorXd,double> Quadric;
+  const int dim = V.cols();
+  //// Quadrics per face
+  //std::vector<Quadric> face_quadrics(F.rows());
+  // Initialize each vertex quadric to zeros
+  quadrics.resize(
+    V.rows(),
+    // gcc <=4.8 can't handle initializer lists correctly
+    Quadric{Eigen::MatrixXd::Zero(dim,dim),Eigen::RowVectorXd::Zero(dim),0});
+  Eigen::MatrixXd I = Eigen::MatrixXd::Identity(dim,dim);
+  // Rather initial with zeros, initial with a small amount of energy pull
+  // toward original vertex position
+  const double w = 1e-10;
+  for(int v = 0;v<V.rows();v++)
+  {
+    std::get<0>(quadrics[v]) = w*I;
+    Eigen::RowVectorXd Vv = V.row(v);
+    std::get<1>(quadrics[v]) = w*-Vv;
+    std::get<2>(quadrics[v]) = w*Vv.dot(Vv);
+  }
+  // Generic nD qslim from "Simplifying Surfaces with Color and Texture
+  // using Quadric Error Metric" (follow up to original QSlim)
+  for(int f = 0;f<F.rows();f++)
+  {
+    int infinite_corner = -1;
+    for(int c = 0;c<3;c++)
+    {
+      if(
+         std::isinf(V(F(f,c),0)) || 
+         std::isinf(V(F(f,c),1)) || 
+         std::isinf(V(F(f,c),2)))
+      {
+        assert(infinite_corner == -1 && "Should only be one infinite corner");
+        infinite_corner = c;
+      }
+    }
+    // Inputs:
+    //   p  1 by n row point on the subspace 
+    //   S  m by n matrix where rows coorespond to orthonormal spanning
+    //     vectors of the subspace to which we're measuring distance (usually
+    //     a plane, m=2)
+    //   weight  scalar weight
+    // Returns quadric triple {A,b,c} so that A-2*b+c measures the quadric
+    const auto subspace_quadric = [&I](
+      const Eigen::RowVectorXd & p,
+      const Eigen::MatrixXd & S,
+      const double  weight)->Quadric
+    {
+      // Dimension of subspace
+      const int m = S.rows();
+      // Weight face's quadric (v'*A*v + 2*b'*v + c) by area
+      // e1 and e2 should be perpendicular
+      Eigen::MatrixXd A = I;
+      Eigen::RowVectorXd b = -p;
+      double c = p.dot(p);
+      for(int i = 0;i<m;i++)
+      {
+        Eigen::RowVectorXd ei = S.row(i);
+        for(int j = 0;j<i;j++) assert(std::abs(S.row(j).dot(ei)) < 1e-10);
+        A += -ei.transpose()*ei;
+        b += p.dot(ei)*ei;
+        c += -pow(p.dot(ei),2);
+      }
+      // gcc <=4.8 can't handle initializer lists correctly: needs explicit
+      // cast
+      return Quadric{ weight*A, weight*b, weight*c };
+    };
+    if(infinite_corner == -1)
+    {
+      // Finite (non-boundary) face
+      Eigen::RowVectorXd p = V.row(F(f,0));
+      Eigen::RowVectorXd q = V.row(F(f,1));
+      Eigen::RowVectorXd r = V.row(F(f,2));
+      Eigen::RowVectorXd pq = q-p;
+      Eigen::RowVectorXd pr = r-p;
+      // Gram Determinant = squared area of parallelogram 
+      double area = sqrt(pq.squaredNorm()*pr.squaredNorm()-pow(pr.dot(pq),2));
+      Eigen::RowVectorXd e1 = pq.normalized();
+      Eigen::RowVectorXd e2 = (pr-e1.dot(pr)*e1).normalized();
+      Eigen::MatrixXd S(2,V.cols());
+      S<<e1,e2;
+      Quadric face_quadric = subspace_quadric(p,S,area);
+      // Throw at each corner
+      for(int c = 0;c<3;c++)
+      {
+        quadrics[F(f,c)] = quadrics[F(f,c)] + face_quadric;
+      }
+    }else
+    {
+      // cth corner is infinite --> edge opposite cth corner is boundary
+      // Boundary edge vector
+      const Eigen::RowVectorXd p = V.row(F(f,(infinite_corner+1)%3));
+      Eigen::RowVectorXd ev = V.row(F(f,(infinite_corner+2)%3)) - p;
+      const double length = ev.norm();
+      ev /= length;
+      // Face neighbor across boundary edge
+      int e = EMAP(f+F.rows()*infinite_corner);
+      int opp = EF(e,0) == f ? 1 : 0;
+      int n =  EF(e,opp);
+      int nc = EI(e,opp);
+      assert(
+        ((F(f,(infinite_corner+1)%3) == F(n,(nc+1)%3) && 
+          F(f,(infinite_corner+2)%3) == F(n,(nc+2)%3)) || 
+          (F(f,(infinite_corner+1)%3) == F(n,(nc+2)%3) 
+          && F(f,(infinite_corner+2)%3) == F(n,(nc+1)%3))) && 
+        "Edge flaps not agreeing on shared edge");
+      // Edge vector on opposite face
+      const Eigen::RowVectorXd eu = V.row(F(n,nc)) - p;
+      assert(!std::isinf(eu(0)));
+      // Matrix with vectors spanning plane as columns
+      Eigen::MatrixXd A(ev.size(),2);
+      A<<ev.transpose(),eu.transpose();
+      // Use QR decomposition to find basis for orthogonal space
+      Eigen::HouseholderQR<Eigen::MatrixXd> qr(A);
+      const Eigen::MatrixXd Q = qr.householderQ();
+      const Eigen::MatrixXd N = 
+        Q.topRightCorner(ev.size(),ev.size()-2).transpose();
+      assert(N.cols() == ev.size());
+      assert(N.rows() == ev.size()-2);
+      Eigen::MatrixXd S(N.rows()+1,ev.size());
+      S<<ev,N;
+      Quadric boundary_edge_quadric = subspace_quadric(p,S,length);
+      for(int c = 0;c<3;c++)
+      {
+        if(c != infinite_corner)
+        {
+          quadrics[F(f,c)] = quadrics[F(f,c)] + boundary_edge_quadric;
+        }
+      }
+    }
+  }
+}
+

+ 53 - 0
include/igl/per_vertex_point_to_plane_quadrics.h

@@ -0,0 +1,53 @@
+// 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_PER_VERTEX_POINT_TO_PLANE_QUADRICS_H
+#define IGL_PER_VERTEX_POINT_TO_PLANE_QUADRICS_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+#include <vector>
+#include <tuple>
+namespace igl
+{
+  // Compute quadrics per vertex of a "closed" triangle mesh (V,F). Rather than
+  // follow the qslim paper, this implements the lesser-known _follow up_
+  // "Simplifying Surfaces with Color and Texture using Quadric Error Metrics".
+  // This allows V to be n-dimensional (where the extra coordiantes store
+  // texture UVs, color RGBs, etc.
+  //
+  // Inputs:
+  //   V  #V by n list of vertex positions. Assumes that vertices with
+  //     infinite coordinates are "points at infinity" being used to close up
+  //     boundary edges with faces. This allows special subspace quadrice for
+  //     boundary edges: There should never be more than one "point at
+  //     infinity" in a single triangle.
+  //   F  #F by 3 list of triangle indices into V
+  //   E  #E by 2 list of edge indices into V.
+  //   EMAP #F*3 list of indices into E, mapping each directed edge to unique
+  //     unique edge in E
+  //   EF  #E by 2 list of edge flaps, EF(e,0)=f means e=(i-->j) is the edge of
+  //     F(f,:) opposite the vth corner, where EI(e,0)=v. Similarly EF(e,1) "
+  //     e=(j->i)
+  //   EI  #E by 2 list of edge flap corners (see above).
+  // Outputs:
+  //   quadrics  #V list of quadrics, where a quadric is a tuple {A,b,c} such
+  //     that the quadratic energy of moving this vertex to position x is
+  //     given by x'Ax - 2b + c
+  //
+  IGL_INLINE void per_vertex_point_to_plane_quadrics(
+    const Eigen::MatrixXd & V,
+    const Eigen::MatrixXi & F,
+    const Eigen::MatrixXi & EMAP,
+    const Eigen::MatrixXi & EF,
+    const Eigen::MatrixXi & EI,
+    std::vector<
+      std::tuple<Eigen::MatrixXd,Eigen::RowVectorXd,double> > & quadrics);
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "per_vertex_point_to_plane_quadrics.cpp"
+#endif
+#endif

+ 1 - 0
include/igl/point_mesh_squared_distance.cpp

@@ -48,4 +48,5 @@ IGL_INLINE void igl::point_mesh_squared_distance(
 #ifdef IGL_STATIC_LIBRARY
 template void igl::point_mesh_squared_distance<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 template void igl::point_mesh_squared_distance<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+template void igl::point_mesh_squared_distance<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
 #endif

+ 26 - 14
include/igl/point_simplex_squared_distance.cpp

@@ -28,13 +28,14 @@ IGL_INLINE void igl::point_simplex_squared_distance(
   const Eigen::MatrixBase<DerivedEle> & Ele,
   const typename DerivedEle::Index primitive,
   Derivedsqr_d & sqr_d,
-  Eigen::PlainObjectBase<Derivedc> & c,
-  Eigen::PlainObjectBase<Derivedb> & bary)
+  Eigen::MatrixBase<Derivedc> & c,
+  Eigen::MatrixBase<Derivedb> & bary)
 {
   typedef typename Derivedp::Scalar Scalar;
   typedef typename Eigen::Matrix<Scalar,1,DIM> Vector;
   typedef Vector Point;
-  typedef Eigen::PlainObjectBase<Derivedb> BaryPoint;
+  //typedef Derivedb BaryPoint;
+  typedef Eigen::Matrix<typename Derivedb::Scalar,1,3> BaryPoint;
 
   const auto & Dot = [](const Point & a, const Point & b)->Scalar
   {
@@ -114,15 +115,25 @@ IGL_INLINE void igl::point_simplex_squared_distance(
   assert(Ele.cols() <= 3 && "Only simplices up to triangles are considered");
 
   assert((Derivedb::RowsAtCompileTime == 1 || Derivedb::ColsAtCompileTime == 1) && "bary must be Eigen Vector or Eigen RowVector");
-  bary.resize( Derivedb::RowsAtCompileTime == 1 ? 1 : DIM, Derivedb::ColsAtCompileTime == 1 ? 1 : DIM );
+  assert(
+    ((Derivedb::RowsAtCompileTime == -1 || Derivedb::ColsAtCompileTime == -1) ||
+      (Derivedb::RowsAtCompileTime == Ele.cols() || Derivedb::ColsAtCompileTime == -Ele.cols())
+    ) && "bary must be Dynamic or size of Ele.cols()");
+
+  BaryPoint tmp_bary;
   c = ClosestBaryPtPointTriangle(
     p,
     V.row(Ele(primitive,0)),
+    // modulo is a HACK to handle points, segments and triangles. Because of
+    // this, we need 3d buffer for bary
     V.row(Ele(primitive,1%Ele.cols())),
     V.row(Ele(primitive,2%Ele.cols())),
-    bary);
+    tmp_bary);
+  bary.resize( Derivedb::RowsAtCompileTime == 1 ? 1 : Ele.cols(), Derivedb::ColsAtCompileTime == 1 ? 1 : Ele.cols());
+  bary.head(Ele.cols()) = tmp_bary.head(Ele.cols());
   sqr_d = (p-c).squaredNorm();
 }
+
 template <
   int DIM,
   typename Derivedp,
@@ -136,18 +147,19 @@ IGL_INLINE void igl::point_simplex_squared_distance(
   const Eigen::MatrixBase<DerivedEle> & Ele,
   const typename DerivedEle::Index primitive,
   Derivedsqr_d & sqr_d,
-  Eigen::PlainObjectBase<Derivedc> & c)
+  Eigen::MatrixBase<Derivedc> & c)
 {
-    Eigen::PlainObjectBase<Derivedc> b;
-    point_simplex_squared_distance<DIM>( p, V, Ele, primitive, sqr_d, c, b );
+  // Use Dynamic because we don't know Ele.cols() at compile time.
+  Eigen::Matrix<typename Derivedc::Scalar,1,Eigen::Dynamic> b;
+  point_simplex_squared_distance<DIM>( p, V, Ele, primitive, sqr_d, c, b );
 }
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instanciation
-template void igl::point_simplex_squared_distance<3, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
-template void igl::point_simplex_squared_distance<2, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 2, 1, 1, 2> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&);
-template void igl::point_simplex_squared_distance<3, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
-template void igl::point_simplex_squared_distance<3, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 1, 1, 3> >&);
-template void igl::point_simplex_squared_distance<2, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 2, 1, 1, 2> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&);
-template void igl::point_simplex_squared_distance<2, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 2, 1, 1, 2> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 2, 1, 1, 1, 2> >&);
+template void igl::point_simplex_squared_distance<3, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
+template void igl::point_simplex_squared_distance<2, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 2, 1, 1, 2> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&);
+template void igl::point_simplex_squared_distance<3, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
+template void igl::point_simplex_squared_distance<3, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&, Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 1, 1, 3> >&);
+template void igl::point_simplex_squared_distance<2, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 2, 1, 1, 2> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&);
+template void igl::point_simplex_squared_distance<2, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 2, 1, 1, 2> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&, Eigen::MatrixBase<Eigen::Matrix<double, 2, 1, 1, 1, 2> >&);
 #endif

+ 3 - 3
include/igl/point_simplex_squared_distance.h

@@ -35,7 +35,7 @@ namespace igl
     const Eigen::MatrixBase<DerivedEle> & Ele,
     const typename DerivedEle::Index i,
     Derivedsqr_d & sqr_d,
-    Eigen::PlainObjectBase<Derivedc> & c);
+    Eigen::MatrixBase<Derivedc> & c);
   // Determine squared distance from a point to linear simplex.
   // Also return barycentric coordinate of closest point. 
   //
@@ -63,8 +63,8 @@ namespace igl
     const Eigen::MatrixBase<DerivedEle> & Ele,
     const typename DerivedEle::Index i,
     Derivedsqr_d & sqr_d,
-    Eigen::PlainObjectBase<Derivedc> & c,
-    Eigen::PlainObjectBase<Derivedb> & b);
+    Eigen::MatrixBase<Derivedc> & c,
+    Eigen::MatrixBase<Derivedb> & b);
 }
 #ifndef IGL_STATIC_LIBRARY
 #  include "point_simplex_squared_distance.cpp"

+ 2 - 2
include/igl/project_isometrically_to_plane.cpp

@@ -24,14 +24,14 @@ IGL_INLINE void igl::project_isometrically_to_plane(
   using namespace std;
   using namespace Eigen;
   assert(F.cols() == 3 && "F should contain triangles");
-  typedef Eigen::PlainObjectBase<DerivedV> MatrixX;
+  typedef DerivedV MatrixX;
   MatrixX l;
   edge_lengths(V,F,l);
   // Number of faces
   const int m = F.rows();
 
   // First corner at origin
-  U = Eigen::PlainObjectBase<DerivedU>::Zero(m*3,2);
+  U = DerivedU::Zero(m*3,2);
   // Second corner along x-axis
   U.block(m,0,m,1) = l.col(2);
   // Third corner rotated onto plane

+ 112 - 0
include/igl/qslim.cpp

@@ -0,0 +1,112 @@
+// 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 "qslim.h"
+
+#include "collapse_edge.h"
+#include "connect_boundary_to_infinity.h"
+#include "decimate.h"
+#include "edge_flaps.h"
+#include "max_faces_stopping_condition.h"
+#include "per_vertex_point_to_plane_quadrics.h"
+#include "qslim_optimal_collapse_edge_callbacks.h"
+#include "quadric_binary_plus_operator.h"
+#include "remove_unreferenced.h"
+#include "slice.h"
+#include "slice_mask.h"
+
+IGL_INLINE bool igl::qslim(
+  const Eigen::MatrixXd & V,
+  const Eigen::MatrixXi & F,
+  const size_t max_m,
+  Eigen::MatrixXd & U,
+  Eigen::MatrixXi & G,
+  Eigen::VectorXi & J,
+  Eigen::VectorXi & I)
+{
+  using namespace igl;
+
+  // Original number of faces
+  const int orig_m = F.rows();
+  // Tracking number of faces
+  int m = F.rows();
+  typedef Eigen::MatrixXd DerivedV;
+  typedef Eigen::MatrixXi DerivedF;
+  DerivedV VO;
+  DerivedF FO;
+  igl::connect_boundary_to_infinity(V,F,VO,FO);
+  Eigen::VectorXi EMAP;
+  Eigen::MatrixXi E,EF,EI;
+  edge_flaps(FO,E,EMAP,EF,EI);
+  // Quadrics per vertex
+  typedef std::tuple<Eigen::MatrixXd,Eigen::RowVectorXd,double> Quadric;
+  std::vector<Quadric> quadrics;
+  per_vertex_point_to_plane_quadrics(VO,FO,EMAP,EF,EI,quadrics);
+  // State variables keeping track of edge we just collapsed
+  int v1 = -1;
+  int v2 = -1;
+  // Callbacks for computing and updating metric
+  std::function<void(
+    const int e,
+    const Eigen::MatrixXd &,
+    const Eigen::MatrixXi &,
+    const Eigen::MatrixXi &,
+    const Eigen::VectorXi &,
+    const Eigen::MatrixXi &,
+    const Eigen::MatrixXi &,
+    double &,
+    Eigen::RowVectorXd &)> cost_and_placement;
+  std::function<bool(
+    const Eigen::MatrixXd &                                         ,/*V*/
+    const Eigen::MatrixXi &                                         ,/*F*/
+    const Eigen::MatrixXi &                                         ,/*E*/
+    const Eigen::VectorXi &                                         ,/*EMAP*/
+    const Eigen::MatrixXi &                                         ,/*EF*/
+    const Eigen::MatrixXi &                                         ,/*EI*/
+    const std::set<std::pair<double,int> > &                        ,/*Q*/
+    const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
+    const Eigen::MatrixXd &                                         ,/*C*/
+    const int                                                        /*e*/
+    )> pre_collapse;
+  std::function<void(
+    const Eigen::MatrixXd &                                         ,   /*V*/
+    const Eigen::MatrixXi &                                         ,   /*F*/
+    const Eigen::MatrixXi &                                         ,   /*E*/
+    const Eigen::VectorXi &                                         ,/*EMAP*/
+    const Eigen::MatrixXi &                                         ,  /*EF*/
+    const Eigen::MatrixXi &                                         ,  /*EI*/
+    const std::set<std::pair<double,int> > &                        ,   /*Q*/
+    const std::vector<std::set<std::pair<double,int> >::iterator > &, /*Qit*/
+    const Eigen::MatrixXd &                                         ,   /*C*/
+    const int                                                       ,   /*e*/
+    const int                                                       ,  /*e1*/
+    const int                                                       ,  /*e2*/
+    const int                                                       ,  /*f1*/
+    const int                                                       ,  /*f2*/
+    const bool                                                  /*collapsed*/
+    )> post_collapse;
+  qslim_optimal_collapse_edge_callbacks(
+    E,quadrics,v1,v2, cost_and_placement, pre_collapse,post_collapse);
+  // Call to greedy decimator
+  bool ret = decimate(
+    VO, FO,
+    cost_and_placement,
+    max_faces_stopping_condition(m,orig_m,max_m),
+    pre_collapse,
+    post_collapse,
+    E, EMAP, EF, EI,
+    U, G, J, I);
+  // Remove phony boundary faces and clean up
+  const Eigen::Array<bool,Eigen::Dynamic,1> keep = (J.array()<orig_m);
+  igl::slice_mask(Eigen::MatrixXi(G),keep,1,G);
+  igl::slice_mask(Eigen::VectorXi(J),keep,1,J);
+  Eigen::VectorXi _1,I2;
+  igl::remove_unreferenced(Eigen::MatrixXd(U),Eigen::MatrixXi(G),U,G,_1,I2);
+  igl::slice(Eigen::VectorXi(I),I2,1,I);
+
+  return ret;
+}

+ 41 - 0
include/igl/qslim.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_QSLIM_H
+#define IGL_QSLIM_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+namespace igl
+{
+
+  // Decimate (simplify) a triangle mesh in nD according to the paper
+  // "Simplifying Surfaces with Color and Texture using Quadric Error Metrics"
+  // by [Garland and Heckbert, 1987] (technically a followup to qslim). The
+  // mesh can have open boundaries but should be edge-manifold.
+  //
+  // Inputs:
+  //   V  #V by dim list of vertex positions. Assumes that vertices w
+  //   F  #F by 3 list of triangle indices into V
+  //   max_m  desired number of output faces
+  // Outputs:
+  //   U  #U by dim list of output vertex posistions (can be same ref as V)
+  //   G  #G by 3 list of output face indices into U (can be same ref as G)
+  //   J  #G list of indices into F of birth face
+  //   I  #U list of indices into V of birth vertices
+  IGL_INLINE bool qslim(
+    const Eigen::MatrixXd & V,
+    const Eigen::MatrixXi & F,
+    const size_t max_m,
+    Eigen::MatrixXd & U,
+    Eigen::MatrixXi & G,
+    Eigen::VectorXi & J,
+    Eigen::VectorXi & I);
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "qslim.cpp"
+#endif
+#endif

+ 130 - 0
include/igl/qslim_optimal_collapse_edge_callbacks.cpp

@@ -0,0 +1,130 @@
+// 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 "qslim_optimal_collapse_edge_callbacks.h"
+#include "quadric_binary_plus_operator.h"
+#include <Eigen/LU>
+
+IGL_INLINE void igl::qslim_optimal_collapse_edge_callbacks(
+  Eigen::MatrixXi & E,
+  std::vector<std::tuple<Eigen::MatrixXd,Eigen::RowVectorXd,double> > & 
+    quadrics,
+  int & v1,
+  int & v2,
+  std::function<void(
+    const int e,
+    const Eigen::MatrixXd &,
+    const Eigen::MatrixXi &,
+    const Eigen::MatrixXi &,
+    const Eigen::VectorXi &,
+    const Eigen::MatrixXi &,
+    const Eigen::MatrixXi &,
+    double &,
+    Eigen::RowVectorXd &)> & cost_and_placement,
+  std::function<bool(
+    const Eigen::MatrixXd &                                         ,/*V*/
+    const Eigen::MatrixXi &                                         ,/*F*/
+    const Eigen::MatrixXi &                                         ,/*E*/
+    const Eigen::VectorXi &                                         ,/*EMAP*/
+    const Eigen::MatrixXi &                                         ,/*EF*/
+    const Eigen::MatrixXi &                                         ,/*EI*/
+    const std::set<std::pair<double,int> > &                        ,/*Q*/
+    const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
+    const Eigen::MatrixXd &                                         ,/*C*/
+    const int                                                        /*e*/
+    )> & pre_collapse,
+  std::function<void(
+    const Eigen::MatrixXd &                                         ,   /*V*/
+    const Eigen::MatrixXi &                                         ,   /*F*/
+    const Eigen::MatrixXi &                                         ,   /*E*/
+    const Eigen::VectorXi &                                         ,/*EMAP*/
+    const Eigen::MatrixXi &                                         ,  /*EF*/
+    const Eigen::MatrixXi &                                         ,  /*EI*/
+    const std::set<std::pair<double,int> > &                        ,   /*Q*/
+    const std::vector<std::set<std::pair<double,int> >::iterator > &, /*Qit*/
+    const Eigen::MatrixXd &                                         ,   /*C*/
+    const int                                                       ,   /*e*/
+    const int                                                       ,  /*e1*/
+    const int                                                       ,  /*e2*/
+    const int                                                       ,  /*f1*/
+    const int                                                       ,  /*f2*/
+    const bool                                                  /*collapsed*/
+    )> & post_collapse)
+{
+  typedef std::tuple<Eigen::MatrixXd,Eigen::RowVectorXd,double> Quadric;
+  cost_and_placement = [&quadrics,&v1,&v2](
+    const int e,
+    const Eigen::MatrixXd & V,
+    const Eigen::MatrixXi & /*F*/,
+    const Eigen::MatrixXi & E,
+    const Eigen::VectorXi & /*EMAP*/,
+    const Eigen::MatrixXi & /*EF*/,
+    const Eigen::MatrixXi & /*EI*/,
+    double & cost,
+    Eigen::RowVectorXd & p)
+  {
+    // Combined quadric
+    Quadric quadric_p;
+    quadric_p = quadrics[E(e,0)] + quadrics[E(e,1)];
+    // Quadric: p'Ap + 2b'p + c
+    // optimal point: Ap = -b, or rather because we have row vectors: pA=-b
+    const auto & A = std::get<0>(quadric_p);
+    const auto & b = std::get<1>(quadric_p);
+    const auto & c = std::get<2>(quadric_p);
+    p = -b*A.inverse();
+    cost = p.dot(p*A) + 2*p.dot(b) + c;
+    // Force infs and nans to infinity
+    if(std::isinf(cost) || cost!=cost)
+    {
+      cost = std::numeric_limits<double>::infinity();
+      // Prevent NaNs. Actually NaNs might be useful for debugging.
+      p.setConstant(0);
+    }
+  };
+  // Remember endpoints
+  pre_collapse = [&v1,&v2](
+    const Eigen::MatrixXd &                                         ,/*V*/
+    const Eigen::MatrixXi &                                         ,/*F*/
+    const Eigen::MatrixXi & E,
+    const Eigen::VectorXi &                                         ,/*EMAP*/
+    const Eigen::MatrixXi &                                         ,/*EF*/
+    const Eigen::MatrixXi &                                         ,/*EI*/
+    const std::set<std::pair<double,int> > &                        ,/*Q*/
+    const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
+    const Eigen::MatrixXd &                                         ,/*C*/
+    const int e)->bool
+  {
+    v1 = E(e,0);
+    v2 = E(e,1);
+    return true;
+  };
+  // update quadric
+  post_collapse = [&v1,&v2,&quadrics](
+      const Eigen::MatrixXd &                                         ,   /*V*/
+      const Eigen::MatrixXi &                                         ,   /*F*/
+      const Eigen::MatrixXi &                                         ,   /*E*/
+      const Eigen::VectorXi &                                         ,/*EMAP*/
+      const Eigen::MatrixXi &                                         ,  /*EF*/
+      const Eigen::MatrixXi &                                         ,  /*EI*/
+      const std::set<std::pair<double,int> > &                        ,   /*Q*/
+      const std::vector<std::set<std::pair<double,int> >::iterator > &, /*Qit*/
+      const Eigen::MatrixXd &                                         ,   /*C*/
+      const int                                                       ,   /*e*/
+      const int                                                       ,  /*e1*/
+      const int                                                       ,  /*e2*/
+      const int                                                       ,  /*f1*/
+      const int                                                       ,  /*f2*/
+      const bool                                                  collapsed
+      )->void
+  {
+    if(collapsed)
+    {
+      quadrics[v1<v2?v1:v2] = quadrics[v1] + quadrics[v2];
+    }
+  };
+}
+

+ 81 - 0
include/igl/qslim_optimal_collapse_edge_callbacks.h

@@ -0,0 +1,81 @@
+// 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_QSLIM_OPTIMAL_COLLAPSE_EDGE_CALLBACKS_H
+#define IGL_QSLIM_OPTIMAL_COLLAPSE_EDGE_CALLBACKS_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+#include <functional>
+#include <vector>
+#include <tuple>
+#include <set>
+namespace igl
+{
+
+  // Prepare callbacks for decimating edges using the qslim optimal placement
+  // metric.
+  //
+  // Inputs:
+  //   E  #E by 2 list of working edges
+  //   quadrics  reference to list of working per vertex quadrics 
+  //   v1  working variable to maintain end point of collapsed edge
+  //   v2  working variable to maintain end point of collapsed edge
+  // Outputs
+  //   cost_and_placement  callback for evaluating cost of edge collapse and
+  //     determining placement of vertex (see collapse_edge)
+  //   pre_collapse  callback before edge collapse (see collapse_edge)
+  //   post_collapse  callback after edge collapse (see collapse_edge)
+  IGL_INLINE void qslim_optimal_collapse_edge_callbacks(
+    Eigen::MatrixXi & E,
+    std::vector<std::tuple<Eigen::MatrixXd,Eigen::RowVectorXd,double> > & 
+      quadrics,
+    int & v1,
+    int & v2,
+    std::function<void(
+      const int e,
+      const Eigen::MatrixXd &,
+      const Eigen::MatrixXi &,
+      const Eigen::MatrixXi &,
+      const Eigen::VectorXi &,
+      const Eigen::MatrixXi &,
+      const Eigen::MatrixXi &,
+      double &,
+      Eigen::RowVectorXd &)> & cost_and_placement,
+    std::function<bool(
+      const Eigen::MatrixXd &                                         ,/*V*/
+      const Eigen::MatrixXi &                                         ,/*F*/
+      const Eigen::MatrixXi &                                         ,/*E*/
+      const Eigen::VectorXi &                                         ,/*EMAP*/
+      const Eigen::MatrixXi &                                         ,/*EF*/
+      const Eigen::MatrixXi &                                         ,/*EI*/
+      const std::set<std::pair<double,int> > &                        ,/*Q*/
+      const std::vector<std::set<std::pair<double,int> >::iterator > &,/*Qit*/
+      const Eigen::MatrixXd &                                         ,/*C*/
+      const int                                                        /*e*/
+      )> & pre_collapse,
+    std::function<void(
+      const Eigen::MatrixXd &                                         ,   /*V*/
+      const Eigen::MatrixXi &                                         ,   /*F*/
+      const Eigen::MatrixXi &                                         ,   /*E*/
+      const Eigen::VectorXi &                                         ,/*EMAP*/
+      const Eigen::MatrixXi &                                         ,  /*EF*/
+      const Eigen::MatrixXi &                                         ,  /*EI*/
+      const std::set<std::pair<double,int> > &                        ,   /*Q*/
+      const std::vector<std::set<std::pair<double,int> >::iterator > &, /*Qit*/
+      const Eigen::MatrixXd &                                         ,   /*C*/
+      const int                                                       ,   /*e*/
+      const int                                                       ,  /*e1*/
+      const int                                                       ,  /*e2*/
+      const int                                                       ,  /*f1*/
+      const int                                                       ,  /*f2*/
+      const bool                                                  /*collapsed*/
+      )> & post_collapse);
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "qslim_optimal_collapse_edge_callbacks.cpp"
+#endif
+#endif

+ 2 - 1
include/igl/quad_planarity.cpp

@@ -23,7 +23,8 @@ IGL_INLINE void igl::quad_planarity(
     const Eigen::Matrix<typename DerivedV::Scalar,1,3> &v3 = V.row(F(i,2));
     const Eigen::Matrix<typename DerivedV::Scalar,1,3> &v4 = V.row(F(i,3));
     Eigen::Matrix<typename DerivedV::Scalar,1,3> diagCross=(v3-v1).cross(v4-v2);
-    typename Eigen::PlainObjectBase<DerivedV>::Scalar denom = diagCross.norm()*(((v3-v1).norm()+(v4-v2).norm())/2);
+    typename DerivedV::Scalar denom = 
+      diagCross.norm()*(((v3-v1).norm()+(v4-v2).norm())/2);
     if (fabs(denom)<1e-8)
       //degenerate quad is still planar
       P[i] = 0;

+ 24 - 0
include/igl/quadric_binary_plus_operator.cpp

@@ -0,0 +1,24 @@
+// 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 "quadric_binary_plus_operator.h"
+
+IGL_INLINE std::tuple< Eigen::MatrixXd, Eigen::RowVectorXd, double> 
+  igl::operator+(
+    const std::tuple< Eigen::MatrixXd, Eigen::RowVectorXd, double>  & a, 
+    const std::tuple< Eigen::MatrixXd, Eigen::RowVectorXd, double>  & b)
+{
+  std::tuple<
+    Eigen::MatrixXd,
+    Eigen::RowVectorXd,
+    double>  c;
+  std::get<0>(c) = (std::get<0>(a) + std::get<0>(b)).eval();
+  std::get<1>(c) = (std::get<1>(a) + std::get<1>(b)).eval();
+  std::get<2>(c) = (std::get<2>(a) + std::get<2>(b));
+  return c;
+}
+

+ 35 - 0
include/igl/quadric_binary_plus_operator.h

@@ -0,0 +1,35 @@
+// 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_QUADRIC_BINARY_PLUS_OPERATOR_H
+#define IGL_QUADRIC_BINARY_PLUS_OPERATOR_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+#include <tuple>
+
+namespace igl
+{
+  // A binary addition operator for Quadric tuples compatible with qslim,
+  // computing c = a+b
+  //
+  // Inputs:
+  //   a  QSlim quadric
+  //   b  QSlim quadric
+  // Output
+  //   c  QSlim quadric
+  //
+  IGL_INLINE std::tuple< Eigen::MatrixXd, Eigen::RowVectorXd, double> 
+    operator+(
+      const std::tuple< Eigen::MatrixXd, Eigen::RowVectorXd, double>  & a, 
+      const std::tuple< Eigen::MatrixXd, Eigen::RowVectorXd, double>  & b);
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "quadric_binary_plus_operator.cpp"
+#endif
+
+#endif

+ 0 - 9
include/igl/randperm.cpp

@@ -20,17 +20,8 @@ IGL_INLINE void igl::randperm(
   std::random_shuffle(I.data(),I.data()+n);
 }
 
-//template <typename DerivedI>
-//IGL_INLINE Eigen::PlainObjectBase<DerivedI> igl::randperm( const int n)
-//{
-//  Eigen::PlainObjectBase<DerivedI> I;
-//  randperm(n,I);
-//  return I;
-//}
-
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 template void igl::randperm<Eigen::Matrix<int, -1, 1, 0, -1, 1> >(int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::randperm<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
-//template Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > igl::randperm<Eigen::Matrix<int, -1, 1, 0, -1, 1> >(int);
 #endif

+ 0 - 2
include/igl/randperm.h

@@ -21,8 +21,6 @@ namespace igl
   IGL_INLINE void randperm(
     const int n,
     Eigen::PlainObjectBase<DerivedI> & I);
-  //template <typename DerivedI>
-  //IGL_INLINE DerivedI randperm( const int n);
 }
 #ifndef IGL_STATIC_LIBRARY
 #  include "randperm.cpp"

+ 5 - 2
include/igl/serialize.h

@@ -187,8 +187,11 @@ namespace igl
  
   public:
  
-    // Override this function to add your member variables which should be serialized
-    inline virtual void InitSerialization() = 0;
+    // 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.
     // Return false to prevent the de-/serialization of an object.

+ 1 - 1
include/igl/setdiff.cpp

@@ -42,7 +42,7 @@ IGL_INLINE void igl::setdiff(
   typedef Matrix<typename DerivedB::Scalar,Dynamic,1> VectorB;
   VectorA uA;
   VectorB uB;
-  typedef PlainObjectBase<DerivedIA> IAType;
+  typedef DerivedIA IAType;
   IAType uIA,uIuA,uIB,uIuB;
   unique(A,uA,uIA,uIuA);
   unique(B,uB,uIB,uIuB);

+ 23 - 0
include/igl/shortest_edge_and_midpoint.cpp

@@ -0,0 +1,23 @@
+// 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 "shortest_edge_and_midpoint.h"
+
+IGL_INLINE void igl::shortest_edge_and_midpoint(
+  const int e,
+  const Eigen::MatrixXd & V,
+  const Eigen::MatrixXi & /*F*/,
+  const Eigen::MatrixXi & E,
+  const Eigen::VectorXi & /*EMAP*/,
+  const Eigen::MatrixXi & /*EF*/,
+  const Eigen::MatrixXi & /*EI*/,
+  double & cost,
+  Eigen::RowVectorXd & p)
+{
+  cost = (V.row(E(e,0))-V.row(E(e,1))).norm();
+  p = 0.5*(V.row(E(e,0))+V.row(E(e,1)));
+}

+ 48 - 0
include/igl/shortest_edge_and_midpoint.h

@@ -0,0 +1,48 @@
+// 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_SHORTEST_EDGE_AND_MIDPOINT_H
+#define IGL_SHORTEST_EDGE_AND_MIDPOINT_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+#include <vector>
+namespace igl
+{
+  // Cost and placement function compatible with igl::decimate. The cost of
+  // collapsing an edge is its length (prefer to collapse short edges) and the
+  // placement strategy for the new vertex is the midpoint of the collapsed
+  // edge.
+  //
+  // Inputs:
+  //   e  index into E of edge to be considered for collapse
+  //   V  #V by dim list of vertex positions
+  //   F  #F by 3 list of faces (ignored)
+  //   E  #E by 2 list of edge indices into V
+  //   EMAP  #F*3 list of half-edges indices into E (ignored)
+  //   EF  #E by 2 list of edge-face flaps into F (ignored)
+  //   EI  #E by 2 list of edge-face opposite corners (ignored)
+  // Outputs:
+  //   cost  set to edge length
+  //   p  placed point set to edge midpoint
+  IGL_INLINE void shortest_edge_and_midpoint(
+    const int e,
+    const Eigen::MatrixXd & V,
+    const Eigen::MatrixXi & /*F*/,
+    const Eigen::MatrixXi & E,
+    const Eigen::VectorXi & /*EMAP*/,
+    const Eigen::MatrixXi & /*EF*/,
+    const Eigen::MatrixXi & /*EI*/,
+    double & cost,
+    Eigen::RowVectorXd & p);
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "shortest_edge_and_midpoint.cpp"
+#endif
+#endif
+
+

+ 2 - 2
include/igl/signed_distance.cpp

@@ -93,8 +93,8 @@ IGL_INLINE void igl::signed_distance(
           for(int e = 0;e<F.rows();e++)
           {
             // rotate edge vector
-            FN(e,0) = -(V(F(e,1),1)-V(F(e,0),1));
-            FN(e,1) =  (V(F(e,1),0)-V(F(e,0),0));
+            FN(e,0) =  (V(F(e,1),1)-V(F(e,0),1));
+            FN(e,1) = -(V(F(e,1),0)-V(F(e,0),0));
             FN.row(e).normalize();
             // add to vertex normal
             VN.row(F(e,1)) += FN.row(e);

+ 4 - 1
include/igl/simplify_polyhedron.cpp

@@ -99,6 +99,9 @@ IGL_INLINE void igl::simplify_polyhedron(
   igl::per_face_normals(OV,OF,N);
   Eigen::VectorXi I;
   igl::decimate(
-    OV,OF,perfect,igl::infinite_cost_stopping_condition(perfect),V,F,J,I);
+    OV,OF,
+    perfect,
+    igl::infinite_cost_stopping_condition(perfect),
+    V,F,J,I);
 }
 

+ 19 - 20
include/igl/slice_into.cpp

@@ -47,12 +47,12 @@ IGL_INLINE void igl::slice_into(
   Y = Eigen::SparseMatrix<T>(dyn_Y);
 }
 
-template <typename DerivedX>
+template <typename DerivedX, typename DerivedY>
 IGL_INLINE void igl::slice_into(
   const Eigen::PlainObjectBase<DerivedX> & X,
   const Eigen::Matrix<int,Eigen::Dynamic,1> & R,
   const Eigen::Matrix<int,Eigen::Dynamic,1> & C,
-  Eigen::PlainObjectBase<DerivedX> & Y)
+  Eigen::PlainObjectBase<DerivedY> & Y)
 {
 
   int xm = X.rows();
@@ -80,12 +80,12 @@ IGL_INLINE void igl::slice_into(
   }
 }
 
-template <typename Mat>
+template <typename MatX, typename MatY>
 IGL_INLINE void igl::slice_into(
-  const Mat& X,
+  const MatX& X,
   const Eigen::Matrix<int,Eigen::Dynamic,1> & R,
   const int dim,
-  Mat& Y)
+  MatY& Y)
 {
   Eigen::VectorXi C;
   switch(dim)
@@ -114,11 +114,11 @@ IGL_INLINE void igl::slice_into(
   }
 }
 
-template <typename DerivedX>
+template <typename DerivedX, typename DerivedY>
 IGL_INLINE void igl::slice_into(
   const Eigen::PlainObjectBase<DerivedX> & X,
   const Eigen::Matrix<int,Eigen::Dynamic,1> & R,
-  Eigen::PlainObjectBase<DerivedX> & Y)
+  Eigen::PlainObjectBase<DerivedY> & Y)
 {
   // phony column indices
   Eigen::Matrix<int,Eigen::Dynamic,1> C;
@@ -130,17 +130,16 @@ IGL_INLINE void igl::slice_into(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // generated by autoexplicit.sh
-template void igl::slice_into<Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
-template void igl::slice_into<Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
-template void igl::slice_into<Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, int, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
-template void igl::slice_into<Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template void igl::slice_into<Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::Matrix<double, -1, 1, 0, -1, 1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, int, Eigen::Matrix<double, -1, 1, 0, -1, 1>&);
-template void igl::slice_into<Eigen::SparseMatrix<double, 0, int> >(Eigen::SparseMatrix<double, 0, int> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, int, Eigen::SparseMatrix<double, 0, int>&);
-template void igl::slice_into<Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, int, Eigen::Matrix<int, -1, 1, 0, -1, 1>&);
-template void igl::slice_into<Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
-template void igl::slice_into<Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
-template void igl::slice_into<Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
-template void igl::slice_into<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
-template void igl::slice_into<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, int, Eigen::Matrix<int, -1, -1, 0, -1, -1>&);
-template void igl::slice_into<int>(Eigen::SparseMatrix<int, 0, int> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::SparseMatrix<int, 0, int>&);
+template void igl::slice_into<double>(Eigen::SparseMatrix<double, 0, int> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::SparseMatrix<double, 0, int>&);
+// generated by autoexplicit.sh
+template void igl::slice_into<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::Matrix<double, -1, 1, 0, -1, 1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, int, Eigen::Matrix<double, -1, 1, 0, -1, 1>&);
+// generated by autoexplicit.sh
+template void igl::slice_into<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
+// generated by autoexplicit.sh
+template void igl::slice_into<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > >(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+// generated by autoexplicit.sh
+template void igl::slice_into<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > >(Eigen::Matrix<double, -1, 1, 0, -1, 1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
+template void igl::slice_into<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, int, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
+template void igl::slice_into<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::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+template void igl::slice_into<Eigen::SparseMatrix<double, 0, int>, Eigen::SparseMatrix<double, 0, int> >(Eigen::SparseMatrix<double, 0, int> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, int, Eigen::SparseMatrix<double, 0, int>&);
 #endif

+ 7 - 7
include/igl/slice_into.h

@@ -30,30 +30,30 @@ namespace igl
     const Eigen::Matrix<int,Eigen::Dynamic,1> & C,
     Eigen::SparseMatrix<T>& Y);
 
-  template <typename DerivedX>
+  template <typename DerivedX, typename DerivedY>
   IGL_INLINE void slice_into(
     const Eigen::PlainObjectBase<DerivedX> & X,
     const Eigen::Matrix<int,Eigen::Dynamic,1> & R,
     const Eigen::Matrix<int,Eigen::Dynamic,1> & C,
-    Eigen::PlainObjectBase<DerivedX> & Y);
+    Eigen::PlainObjectBase<DerivedY> & Y);
   // Wrapper to only slice in one direction
   //
   // Inputs:
   //   dim  dimension to slice in 1 or 2, dim=1 --> X(R,:), dim=2 --> X(:,R)
   //
   // Note: For now this is just a cheap wrapper.
-  template <typename Mat>
+  template <typename MatX, typename MatY>
   IGL_INLINE void slice_into(
-    const Mat& X,
+    const MatX & X,
     const Eigen::Matrix<int,Eigen::Dynamic,1> & R,
     const int dim,
-    Mat& Y);
+    MatY& Y);
 
-  template <typename DerivedX>
+  template <typename DerivedX, typename DerivedY>
   IGL_INLINE void slice_into(
     const Eigen::PlainObjectBase<DerivedX> & X,
     const Eigen::Matrix<int,Eigen::Dynamic,1> & R,
-    Eigen::PlainObjectBase<DerivedX> & Y);
+    Eigen::PlainObjectBase<DerivedY> & Y);
 }
 
 #ifndef IGL_STATIC_LIBRARY

+ 15 - 14
include/igl/sort.cpp

@@ -158,23 +158,23 @@ IGL_INLINE void igl::sort2(
 {
   using namespace Eigen;
   using namespace std;
-  typedef typename Eigen::PlainObjectBase<DerivedY>::Scalar YScalar;
+  typedef typename DerivedY::Scalar YScalar;
   Y = X.template cast<YScalar>();
   // get number of columns (or rows)
   int num_outer = (dim == 1 ? X.cols() : X.rows() );
   // get number of rows (or columns)
   int num_inner = (dim == 1 ? X.rows() : X.cols() );
   assert(num_inner == 2);(void)num_inner;
-  typedef typename Eigen::PlainObjectBase<DerivedIX>::Scalar Index;
+  typedef typename DerivedIX::Scalar Index;
   IX.resize(X.rows(),X.cols());
   if(dim==1)
   {
-    IX.row(0).setConstant(0);// = Eigen::PlainObjectBase<DerivedIX>::Zero(1,IX.cols());
-    IX.row(1).setConstant(1);// = Eigen::PlainObjectBase<DerivedIX>::Ones (1,IX.cols());
+    IX.row(0).setConstant(0);// = DerivedIX::Zero(1,IX.cols());
+    IX.row(1).setConstant(1);// = DerivedIX::Ones (1,IX.cols());
   }else
   {
-    IX.col(0).setConstant(0);// = Eigen::PlainObjectBase<DerivedIX>::Zero(IX.rows(),1);
-    IX.col(1).setConstant(1);// = Eigen::PlainObjectBase<DerivedIX>::Ones (IX.rows(),1);
+    IX.col(0).setConstant(0);// = DerivedIX::Zero(IX.rows(),1);
+    IX.col(1).setConstant(1);// = DerivedIX::Ones (IX.rows(),1);
   }
   // loop over columns (or rows)
   for(int i = 0;i<num_outer;i++)
@@ -201,25 +201,25 @@ IGL_INLINE void igl::sort3(
 {
   using namespace Eigen;
   using namespace std;
-  typedef typename Eigen::PlainObjectBase<DerivedY>::Scalar YScalar;
+  typedef typename DerivedY::Scalar YScalar;
   Y = X.template cast<YScalar>();
   // get number of columns (or rows)
   int num_outer = (dim == 1 ? X.cols() : X.rows() );
   // get number of rows (or columns)
   int num_inner = (dim == 1 ? X.rows() : X.cols() );
   assert(num_inner == 3);(void)num_inner;
-  typedef typename Eigen::PlainObjectBase<DerivedIX>::Scalar Index;
+  typedef typename DerivedIX::Scalar Index;
   IX.resize(X.rows(),X.cols());
   if(dim==1)
   {
-    IX.row(0).setConstant(0);// = Eigen::PlainObjectBase<DerivedIX>::Zero(1,IX.cols());
-    IX.row(1).setConstant(1);// = Eigen::PlainObjectBase<DerivedIX>::Ones (1,IX.cols());
-    IX.row(2).setConstant(2);// = Eigen::PlainObjectBase<DerivedIX>::Ones (1,IX.cols());
+    IX.row(0).setConstant(0);// = DerivedIX::Zero(1,IX.cols());
+    IX.row(1).setConstant(1);// = DerivedIX::Ones (1,IX.cols());
+    IX.row(2).setConstant(2);// = DerivedIX::Ones (1,IX.cols());
   }else
   {
-    IX.col(0).setConstant(0);// = Eigen::PlainObjectBase<DerivedIX>::Zero(IX.rows(),1);
-    IX.col(1).setConstant(1);// = Eigen::PlainObjectBase<DerivedIX>::Ones (IX.rows(),1);
-    IX.col(2).setConstant(2);// = Eigen::PlainObjectBase<DerivedIX>::Ones (IX.rows(),1);
+    IX.col(0).setConstant(0);// = DerivedIX::Zero(IX.rows(),1);
+    IX.col(1).setConstant(1);// = DerivedIX::Ones (IX.rows(),1);
+    IX.col(2).setConstant(2);// = DerivedIX::Ones (IX.rows(),1);
   }
 
 
@@ -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

+ 2 - 2
include/igl/viewer/TextRenderer.cpp

@@ -45,9 +45,9 @@ IGL_INLINE int igl::viewer::TextRenderer::Shut()
 }
 
 IGL_INLINE void igl::viewer::TextRenderer::BeginDraw(
-  const Eigen::Matrix4f &view, 
+  const Eigen::Matrix4f &view,
   const Eigen::Matrix4f &proj,
-  const Eigen::Vector4f &_viewport, 
+  const Eigen::Vector4f &_viewport,
   float _object_scale)
 {
   using namespace std;

+ 9 - 7
include/igl/viewer/Viewer.cpp

@@ -33,10 +33,13 @@
 
 #include <Eigen/LU>
 
-#define GLFW_INCLUDE_GLU
-#ifndef _WIN32
-  #define GLFW_INCLUDE_GLCOREARB
+//#define GLFW_INCLUDE_GLU
+#if defined(__APPLE__)
+#define GLFW_INCLUDE_GLCOREARB
+#else
+#define GL_GLEXT_PROTOTYPES
 #endif
+
 #include <GLFW/glfw3.h>
 
 #include <cmath>
@@ -80,7 +83,6 @@ static igl::viewer::Viewer * __viewer;
 static double highdpi = 1;
 static double scroll_x = 0;
 static double scroll_y = 0;
-//static int global_KMod = 0;
 
 static void glfw_mouse_press(GLFWwindow* window, int button, int action, int modifier)
 {
@@ -779,8 +781,8 @@ namespace viewer
         break;
 
 #ifdef IGL_VIEWER_WITH_NANOGUI
-    ngui->refresh();
-    screen->drawWidgets();
+	screen->drawContents();
+	screen->drawWidgets();
 #endif
   }
 
@@ -871,7 +873,7 @@ namespace viewer
 
     glfwWindowHint(GLFW_SAMPLES, 8);
     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
-    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
+    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
 
     #ifdef __APPLE__
       glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

+ 19 - 39
include/igl/viewer/ViewerCore.cpp

@@ -114,23 +114,17 @@ IGL_INLINE void igl::viewer::ViewerCore::get_scale_and_shift_to_fit_mesh(
 
   Eigen::MatrixXd BC;
   if (F.rows() <= 1)
+  {
     BC = V;
-  else
+  } else
+  {
     igl::barycenter(V,F,BC);
-
-  Eigen::RowVector3d min_point = BC.colwise().minCoeff();
-  Eigen::RowVector3d max_point = BC.colwise().maxCoeff();
-  Eigen::RowVector3d centroid  = 0.5*(min_point + max_point);
-
-  shift = -centroid.cast<float>();
-  double x_scale = fabs(max_point[0] - min_point[0]);
-  double y_scale = fabs(max_point[1] - min_point[1]);
-  double z_scale = fabs(max_point[2] - min_point[2]);
-  zoom = 2.0 / std::max(z_scale,std::max(x_scale,y_scale));
+  }
+  return get_scale_and_shift_to_fit_mesh(BC,zoom,shift);
 }
 
 IGL_INLINE void igl::viewer::ViewerCore::align_camera_center(
-                                                     const Eigen::MatrixXd& V)
+  const Eigen::MatrixXd& V)
 {
   if(V.rows() == 0)
     return;
@@ -144,36 +138,19 @@ IGL_INLINE void igl::viewer::ViewerCore::align_camera_center(
 }
 
 IGL_INLINE void igl::viewer::ViewerCore::get_scale_and_shift_to_fit_mesh(
-                                                                 const Eigen::MatrixXd& V,
-                                                                 float& zoom,
-                                                                 Eigen::Vector3f& shift)
+  const Eigen::MatrixXd& V,
+  float& zoom,
+  Eigen::Vector3f& shift)
 {
   if (V.rows() == 0)
     return;
 
-  Eigen::RowVector3d min_point;
-  Eigen::RowVector3d max_point;
-  Eigen::RowVector3d centroid;
-
-  if (V.cols() == 3)
-  {
-    min_point = V.colwise().minCoeff();
-    max_point = V.colwise().maxCoeff();
-  }
-  else if (V.cols() == 2)
-  {
-    min_point << V.colwise().minCoeff(),0;
-    max_point << V.colwise().maxCoeff(),0;
-  }
-  else
-    return;
-
-  centroid = 0.5 * (min_point + max_point);
-  shift = -centroid.cast<float>();
-  double x_scale = fabs(max_point[0] - min_point[0]);
-  double y_scale = fabs(max_point[1] - min_point[1]);
-  double z_scale = fabs(max_point[2] - min_point[2]);
-  zoom = 2.0 / std::max(z_scale,std::max(x_scale,y_scale));
+  auto min_point = V.colwise().minCoeff().eval();
+  auto max_point = V.colwise().maxCoeff().eval();
+  auto centroid  = 0.5*(min_point + max_point).eval();
+  shift.setConstant(0);
+  shift.head(centroid.size())= -centroid.cast<float>();
+  zoom = 2.0 / (max_point-min_point).array().abs().maxCoeff();
 }
 
 
@@ -186,7 +163,10 @@ IGL_INLINE void igl::viewer::ViewerCore::clear_framebuffers()
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 }
 
-IGL_INLINE void igl::viewer::ViewerCore::draw(ViewerData& data, OpenGL_state& opengl, bool update_matrices)
+IGL_INLINE void igl::viewer::ViewerCore::draw(
+  ViewerData& data, 
+  OpenGL_state& opengl, 
+  bool update_matrices)
 {
   using namespace std;
   using namespace Eigen;

+ 1 - 1
include/igl/winding_number.cpp

@@ -208,7 +208,7 @@ IGL_INLINE void igl::winding_number_2(
         }
       }
       double val =
-        atan2(o2vd[0]*o2vs[1]-o2vd[1]*o2vs[0],o2vd[0]*o2vs[0]+o2vd[1]*o2vs[1])/
+        -atan2(o2vd[0]*o2vs[1]-o2vd[1]*o2vs[0],o2vd[0]*o2vs[0]+o2vd[1]*o2vs[1])/
         (2.*igl::PI);
 #pragma omp atomic
       S[o] += val;

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików