Эх сурвалжийг харах

Merge pull request #1067 from libigl/boundary-faces-extend

Extend boundary_facets with outputs revealing which element facet comes from
Alec Jacobson 6 жил өмнө
parent
commit
77eb3f88fd

+ 0 - 2
include/igl/WindingNumberTree.h

@@ -164,7 +164,6 @@ inline igl::WindingNumberTree<Point,DerivedV,DerivedF>::WindingNumberTree():
   V(dummyV),
   V(dummyV),
   SV(),
   SV(),
   F(),
   F(),
-  //boundary(igl::boundary_facets<Eigen::MatrixXi,Eigen::MatrixXi>(F))
   cap(),
   cap(),
   radius(std::numeric_limits<typename DerivedV::Scalar>::infinity()),
   radius(std::numeric_limits<typename DerivedV::Scalar>::infinity()),
   center(0,0,0)
   center(0,0,0)
@@ -180,7 +179,6 @@ inline igl::WindingNumberTree<Point,DerivedV,DerivedF>::WindingNumberTree(
   V(dummyV),
   V(dummyV),
   SV(),
   SV(),
   F(),
   F(),
-  //boundary(igl::boundary_facets<Eigen::MatrixXi,Eigen::MatrixXi>(F))
   cap(),
   cap(),
   radius(std::numeric_limits<typename DerivedV::Scalar>::infinity()),
   radius(std::numeric_limits<typename DerivedV::Scalar>::infinity()),
   center(0,0,0)
   center(0,0,0)

+ 21 - 1
include/igl/accumarray.cpp

@@ -19,6 +19,7 @@ void igl::accumarray(
   Eigen::PlainObjectBase<DerivedA> & A)
   Eigen::PlainObjectBase<DerivedA> & A)
 {
 {
   assert(V.size() == S.size() && "S and V should be same size");
   assert(V.size() == S.size() && "S and V should be same size");
+  if(S.size() == 0) { A.resize(0,1); return; }
   A.setZero(S.maxCoeff()+1,1);
   A.setZero(S.maxCoeff()+1,1);
   for(int s = 0;s<S.size();s++)
   for(int s = 0;s<S.size();s++)
   {
   {
@@ -26,7 +27,26 @@ void igl::accumarray(
   }
   }
 }
 }
 
 
+template <
+  typename DerivedS,
+  typename DerivedA
+  >
+void igl::accumarray(
+  const Eigen::MatrixBase<DerivedS> & S,
+  const typename DerivedA::Scalar V,
+  Eigen::PlainObjectBase<DerivedA> & A)
+{
+  if(S.size() == 0) { A.resize(0,1); return; }
+  A.setZero(S.maxCoeff()+1,1);
+  for(int s = 0;s<S.size();s++)
+  {
+    A(S(s)) += V;
+  }
+}
+
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
-// Explicit template instantiations
+// Explicit template instantiation
+// generated by autoexplicit.sh
+template void igl::accumarray<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1>::Scalar, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::accumarray<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::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 template void igl::accumarray<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::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 #endif
 #endif

+ 13 - 0
include/igl/accumarray.h

@@ -28,6 +28,19 @@ namespace igl
     const Eigen::MatrixBase<DerivedS> & S,
     const Eigen::MatrixBase<DerivedS> & S,
     const Eigen::MatrixBase<DerivedV> & V,
     const Eigen::MatrixBase<DerivedV> & V,
     Eigen::PlainObjectBase<DerivedA> & A);
     Eigen::PlainObjectBase<DerivedA> & A);
+  // Inputs:
+  //   S  #S list of subscripts
+  //   V  single value used for all
+  // Outputs:
+  //   A  max(subs)+1 list of accumulated values
+  template <
+    typename DerivedS,
+    typename DerivedA
+    >
+  void accumarray(
+    const Eigen::MatrixBase<DerivedS> & S,
+    const typename DerivedA::Scalar V,
+    Eigen::PlainObjectBase<DerivedA> & A);
 }
 }
 
 
 #ifndef IGL_STATIC_LIBRARY
 #ifndef IGL_STATIC_LIBRARY

+ 105 - 24
include/igl/boundary_facets.cpp

@@ -7,31 +7,120 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "boundary_facets.h"
 #include "boundary_facets.h"
 #include "face_occurrences.h"
 #include "face_occurrences.h"
-
-// IGL includes
+#include "list_to_matrix.h"
+#include "matrix_to_list.h"
+#include "matlab_format.h"
 #include "sort.h"
 #include "sort.h"
+#include "unique_rows.h"
+#include "accumarray.h"
+#include "slice_mask.h"
+
+#include <Eigen/Core>
 
 
-// STL includes
 #include <map>
 #include <map>
 #include <iostream>
 #include <iostream>
 
 
-#include "list_to_matrix.h"
-#include "matrix_to_list.h"
+template <
+  typename DerivedT, 
+  typename DerivedF,
+  typename DerivedJ,
+  typename DerivedK>
+IGL_INLINE void igl::boundary_facets(
+  const Eigen::MatrixBase<DerivedT>& T,
+  Eigen::PlainObjectBase<DerivedF>& F,
+  Eigen::PlainObjectBase<DerivedJ>& J,
+  Eigen::PlainObjectBase<DerivedK>& K)
+{
+  const int simplex_size = T.cols();
+  // Handle boring base case
+  if(T.rows() == 0)
+  {
+    F.resize(0,simplex_size-1);
+    J.resize(0,1);
+    K.resize(0,1);
+    return;
+  }
+  // Get a list of all facets
+  DerivedF allF(T.rows()*simplex_size,simplex_size-1);
+  // Gather faces (e.g., loop over tets)
+  for(int i = 0; i< (int)T.rows();i++)
+  {
+    switch(simplex_size)
+    {
+      case 4:
+        // get face in correct order
+        allF(i*simplex_size+0,0) = T(i,1);
+        allF(i*simplex_size+0,1) = T(i,3);
+        allF(i*simplex_size+0,2) = T(i,2);
+        // get face in correct order
+        allF(i*simplex_size+1,0) = T(i,0);
+        allF(i*simplex_size+1,1) = T(i,2);
+        allF(i*simplex_size+1,2) = T(i,3);
+        // get face in correct order
+        allF(i*simplex_size+2,0) = T(i,0);
+        allF(i*simplex_size+2,1) = T(i,3);
+        allF(i*simplex_size+2,2) = T(i,1);
+        // get face in correct order
+        allF(i*simplex_size+3,0) = T(i,0);
+        allF(i*simplex_size+3,1) = T(i,1);
+        allF(i*simplex_size+3,2) = T(i,2);
+        break;
+      case 3:
+        allF(i*simplex_size+0,0) = T(i,1);
+        allF(i*simplex_size+0,1) = T(i,2);
+        allF(i*simplex_size+1,0) = T(i,2);
+        allF(i*simplex_size+1,1) = T(i,0);
+        allF(i*simplex_size+2,0) = T(i,0);
+        allF(i*simplex_size+2,1) = T(i,1);
+        break;
+    }
+  }
+  DerivedF sortedF;
+  igl::sort(allF,2,true,sortedF);
+  Eigen::VectorXi m,n;
+  {
+    DerivedF _1;
+    igl::unique_rows(sortedF,_1,m,n);
+  }
+  Eigen::VectorXi C;
+  igl::accumarray(n,1,C);
+  const int ones = (C.array()==1).count();
+  // Resize output to fit number of non-twos
+  F.resize(ones, allF.cols());
+  J.resize(F.rows(),1);
+  K.resize(F.rows(),1);
+  int k = 0;
+  for(int c = 0;c< (int)C.size();c++)
+  {
+    if(C(c) == 1)
+    {
+      const int i = m(c);
+      assert(k<(int)F.rows());
+      F.row(k) = allF.row(i);
+      J(k) = i/simplex_size;
+      K(k) = i%simplex_size;
+      k++;
+    }
+  }
+  assert(k==(int)F.rows());
+}
 
 
 template <typename DerivedT, typename DerivedF>
 template <typename DerivedT, typename DerivedF>
 IGL_INLINE void igl::boundary_facets(
 IGL_INLINE void igl::boundary_facets(
   const Eigen::MatrixBase<DerivedT>& T,
   const Eigen::MatrixBase<DerivedT>& T,
   Eigen::PlainObjectBase<DerivedF>& F)
   Eigen::PlainObjectBase<DerivedF>& F)
 {
 {
-  assert(T.cols() == 0 || T.cols() == 4 || T.cols() == 3);
-  using namespace std;
-  using namespace Eigen;
-  // Cop out: use vector of vectors version
-  vector<vector<typename DerivedT::Scalar> > vT;
-  matrix_to_list(T,vT);
-  vector<vector<typename DerivedF::Scalar> > vF;
-  boundary_facets(vT,vF);
-  list_to_matrix(vF,F);
+  Eigen::VectorXi J,K;
+  return boundary_facets(T,F,J,K);
+}
+
+template <typename DerivedT, typename Ret>
+Ret igl::boundary_facets(
+  const Eigen::MatrixBase<DerivedT>& T)
+{
+  Ret F;
+  igl::boundary_facets(T,F);
+  return F;
 }
 }
 
 
 template <typename IntegerT, typename IntegerF>
 template <typename IntegerT, typename IntegerF>
@@ -118,23 +207,15 @@ IGL_INLINE void igl::boundary_facets(
 
 
 }
 }
 
 
-template <typename DerivedT, typename Ret>
-Ret igl::boundary_facets(
-  const Eigen::MatrixBase<DerivedT>& T)
-{
-  Ret F;
-  igl::boundary_facets(T,F);
-  return F;
-}
-
 
 
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
 // Explicit template instantiation
 // generated by autoexplicit.sh
 // generated by autoexplicit.sh
+template void igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+// generated by autoexplicit.sh
 template void igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >&);
 template void igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >&);
 // generated by autoexplicit.sh
 // generated by autoexplicit.sh
 template void igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
 template void igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
-template void igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::boundary_facets<int, int>(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&);
 template void igl::boundary_facets<int, int>(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&);
 //template Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > igl::boundary_facets(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
 //template Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > igl::boundary_facets(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
 template Eigen::Matrix<int, -1, -1, 0, -1, -1> igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
 template Eigen::Matrix<int, -1, -1, 0, -1, -1> igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);

+ 4 - 12
include/igl/boundary_facets.h

@@ -37,18 +37,6 @@ namespace igl
     Eigen::PlainObjectBase<DerivedJ>& J,
     Eigen::PlainObjectBase<DerivedJ>& J,
     Eigen::PlainObjectBase<DerivedK>& K);
     Eigen::PlainObjectBase<DerivedK>& K);
   template <typename DerivedT, typename DerivedF>
   template <typename DerivedT, typename DerivedF>
-  IGL_INLINE void boundary_facets(
-    const Eigen::MatrixBase<DerivedT>& T,
-    Eigen::PlainObjectBase<DerivedF>& F);
-  template <typename IntegerT, typename IntegerF>
-  IGL_INLINE void boundary_facets(
-    const std::vector<std::vector<IntegerT> > & T,
-    std::vector<std::vector<IntegerF> > & F);
-
-  // Templates:
-  //   DerivedT  integer-value: i.e. from MatrixXi
-  //   DerivedF  integer-value: i.e. from MatrixXi
-  template <typename DerivedT, typename DerivedF>
   IGL_INLINE void boundary_facets(
   IGL_INLINE void boundary_facets(
     const Eigen::MatrixBase<DerivedT>& T,
     const Eigen::MatrixBase<DerivedT>& T,
     Eigen::PlainObjectBase<DerivedF>& F);
     Eigen::PlainObjectBase<DerivedF>& F);
@@ -56,6 +44,10 @@ namespace igl
   template <typename DerivedT, typename Ret>
   template <typename DerivedT, typename Ret>
   Ret boundary_facets(
   Ret boundary_facets(
     const Eigen::MatrixBase<DerivedT>& T);
     const Eigen::MatrixBase<DerivedT>& T);
+  template <typename IntegerT, typename IntegerF>
+  IGL_INLINE void boundary_facets(
+    const std::vector<std::vector<IntegerT> > & T,
+    std::vector<std::vector<IntegerF> > & F);
 }
 }
 
 
 #ifndef IGL_STATIC_LIBRARY
 #ifndef IGL_STATIC_LIBRARY

+ 15 - 0
include/igl/face_occurrences.cpp

@@ -6,6 +6,8 @@
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can 
 // 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/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "face_occurrences.h"
 #include "face_occurrences.h"
+#include "list_to_matrix.h"
+#include "matrix_to_list.h"
 
 
 #include <map>
 #include <map>
 #include "sort.h"
 #include "sort.h"
@@ -50,6 +52,19 @@ IGL_INLINE void igl::face_occurrences(
   }
   }
 }
 }
 
 
+template <typename DerivedF, typename DerivedC>
+IGL_INLINE void igl::face_occurrences(
+  const Eigen::MatrixBase<DerivedF> & F,
+  Eigen::PlainObjectBase<DerivedC> & C)
+{
+  // Should really just rewrite using Eigen+libigl ...
+  std::vector<std::vector<typename DerivedF::Scalar> > vF;
+  matrix_to_list(F,vF);
+  std::vector<std::vector<typename DerivedC::Scalar> > vC;
+  igl::face_occurrences(vF,vC);
+  list_to_matrix(vC,C);
+}
+
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
 // Explicit template instantiation
 // generated by autoexplicit.sh
 // generated by autoexplicit.sh

+ 6 - 1
include/igl/face_occurrences.h

@@ -8,11 +8,12 @@
 #ifndef IGL_FACE_OCCURRENCES
 #ifndef IGL_FACE_OCCURRENCES
 #define IGL_FACE_OCCURRENCES
 #define IGL_FACE_OCCURRENCES
 #include "igl_inline.h"
 #include "igl_inline.h"
+#include <Eigen/Core>
 
 
 #include <vector>
 #include <vector>
 namespace igl
 namespace igl
 {
 {
-  // Count the occruances of each face (row) in a list of face indices
+  // Count the occurances of each face (row) in a list of face indices
   // (irrespecitive of order)
   // (irrespecitive of order)
   // Inputs:
   // Inputs:
   //   F  #F by simplex-size
   //   F  #F by simplex-size
@@ -23,6 +24,10 @@ namespace igl
   IGL_INLINE void face_occurrences(
   IGL_INLINE void face_occurrences(
     const std::vector<std::vector<IntegerF> > & F,
     const std::vector<std::vector<IntegerF> > & F,
     std::vector<IntegerC> & C);
     std::vector<IntegerC> & C);
+  template <typename DerivedF, typename DerivedC>
+  IGL_INLINE void face_occurrences(
+    const Eigen::MatrixBase<DerivedF> & F,
+    Eigen::PlainObjectBase<DerivedC> & C);
 }
 }
 
 
 #ifndef IGL_STATIC_LIBRARY
 #ifndef IGL_STATIC_LIBRARY

+ 4 - 0
include/igl/matlab_format.cpp

@@ -113,6 +113,10 @@ IGL_INLINE const std::string igl::matlab_format(
 
 
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
 // Explicit template instantiation
+// generated by autoexplicit.sh
+template Eigen::WithFormat<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> > const igl::matlab_format<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >(Eigen::DenseBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >);
+// generated by autoexplicit.sh
+template Eigen::WithFormat<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const igl::matlab_format<Eigen::Matrix<int, -1, 3, 1, -1, 3> >(Eigen::DenseBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >);
 #if EIGEN_VERSION_AT_LEAST(3,3,0)
 #if EIGEN_VERSION_AT_LEAST(3,3,0)
 #else
 #else
 // generated by autoexplicit.sh
 // generated by autoexplicit.sh

+ 3 - 0
include/igl/reorder.cpp

@@ -31,6 +31,8 @@ IGL_INLINE void igl::reorder(
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
 // Explicit template instantiation
 // generated by autoexplicit.sh
 // generated by autoexplicit.sh
+template void igl::reorder<unsigned int>(std::vector<unsigned int, std::allocator<unsigned int> > const&, std::vector<unsigned long, std::allocator<unsigned long> > const&, std::vector<unsigned int, std::allocator<unsigned int> >&);
+// generated by autoexplicit.sh
 template void igl::reorder<float>(std::vector<float, std::allocator<float> > const&, std::vector<unsigned long, std::allocator<unsigned long> > const&, std::vector<float, std::allocator<float> >&);
 template void igl::reorder<float>(std::vector<float, std::allocator<float> > const&, std::vector<unsigned long, std::allocator<unsigned long> > const&, std::vector<float, std::allocator<float> >&);
 template void igl::reorder<double>(std::vector<double, std::allocator<double> > const&, std::vector<size_t, std::allocator<size_t> > const&, std::vector<double, std::allocator<double> >&);
 template void igl::reorder<double>(std::vector<double, std::allocator<double> > const&, std::vector<size_t, std::allocator<size_t> > const&, std::vector<double, std::allocator<double> >&);
 template void igl::reorder<int>(std::vector<int, std::allocator<int> > const&, std::vector<size_t, std::allocator<size_t> > const&, std::vector<int, std::allocator<int> >&);
 template void igl::reorder<int>(std::vector<int, std::allocator<int> > const&, std::vector<size_t, std::allocator<size_t> > const&, std::vector<int, std::allocator<int> >&);
@@ -40,6 +42,7 @@ template void igl::reorder<int>(std::vector<int, std::allocator<int> > const&, s
 #  endif
 #  endif
 template void igl::reorder<long>(std::vector<long, std::allocator<long> > const&, std::vector<size_t, std::allocator<size_t> > const&, std::vector<long, std::allocator<long> >&);
 template void igl::reorder<long>(std::vector<long, std::allocator<long> > const&, std::vector<size_t, std::allocator<size_t> > const&, std::vector<long, std::allocator<long> >&);
 #ifdef WIN32
 #ifdef WIN32
+template void igl::reorder<unsigned int>(class std::vector<unsigned int,class std::allocator<unsigned int> > const &,class std::vector<unsigned __int64,class std::allocator<unsigned __int64> > const &,class std::vector<unsigned int,class std::allocator<unsigned int> > &);
 template void igl::reorder<float>(class std::vector<float,class std::allocator<float> > const &,class std::vector<unsigned __int64,class std::allocator<unsigned __int64> > const &,class std::vector<float,class std::allocator<float> > &);
 template void igl::reorder<float>(class std::vector<float,class std::allocator<float> > const &,class std::vector<unsigned __int64,class std::allocator<unsigned __int64> > const &,class std::vector<float,class std::allocator<float> > &);
 template void igl::reorder<__int64>(class std::vector<__int64,class std::allocator<__int64> > const &,class std::vector<unsigned __int64,class std::allocator<unsigned __int64> > const &,class std::vector<__int64,class std::allocator<__int64> > &);
 template void igl::reorder<__int64>(class std::vector<__int64,class std::allocator<__int64> > const &,class std::vector<unsigned __int64,class std::allocator<unsigned __int64> > const &,class std::vector<__int64,class std::allocator<__int64> > &);
 #endif
 #endif

+ 24 - 0
include/igl/sort.cpp

@@ -81,6 +81,17 @@ IGL_INLINE void igl::sort(
   }
   }
 }
 }
 
 
+template <typename DerivedX, typename DerivedY>
+IGL_INLINE void igl::sort(
+  const Eigen::DenseBase<DerivedX>& X,
+  const int dim,
+  const bool ascending,
+  Eigen::PlainObjectBase<DerivedY>& Y)
+{
+  Eigen::Matrix< int, DerivedX::RowsAtCompileTime, DerivedX::ColsAtCompileTime > IX;
+  return sort(X,dim,ascending,Y,IX);
+}
+
 template <typename DerivedX, typename DerivedY, typename DerivedIX>
 template <typename DerivedX, typename DerivedY, typename DerivedIX>
 IGL_INLINE void igl::sort_new(
 IGL_INLINE void igl::sort_new(
   const Eigen::DenseBase<DerivedX>& X,
   const Eigen::DenseBase<DerivedX>& X,
@@ -317,6 +328,18 @@ if(!ascending)
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
 // Explicit template instantiation
 // generated by autoexplicit.sh
 // generated by autoexplicit.sh
+template void igl::sort<Eigen::Matrix<int, 1, 3, 1, 1, 3>, Eigen::Matrix<int, 1, 3, 1, 1, 3> >(Eigen::DenseBase<Eigen::Matrix<int, 1, 3, 1, 1, 3> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, 1, 3, 1, 1, 3> >&);
+// generated by autoexplicit.sh
+template void igl::sort<Eigen::Block<Eigen::Matrix<int, -1, -1, 0, -1, -1>, 1, -1, false>, Eigen::Matrix<int, 1, 3, 1, 1, 3> >(Eigen::DenseBase<Eigen::Block<Eigen::Matrix<int, -1, -1, 0, -1, -1>, 1, -1, false> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, 1, 3, 1, 1, 3> >&);
+// generated by autoexplicit.sh
+template void igl::sort<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3>, Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >(Eigen::DenseBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >&);
+// generated by autoexplicit.sh
+template void igl::sort<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::DenseBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
+// generated by autoexplicit.sh
+template void igl::sort<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+// generated by autoexplicit.sh
+template void igl::sort<Eigen::Matrix<int, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(Eigen::DenseBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
+// generated by autoexplicit.sh
 template void igl::sort<Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::DenseBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::sort<Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::DenseBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 // generated by autoexplicit.sh
 // generated by autoexplicit.sh
 template void igl::sort<Eigen::Matrix<int, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::DenseBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > 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, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::DenseBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
@@ -343,6 +366,7 @@ template void igl::sort<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<flo
 template void igl::sort<Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::DenseBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::sort<Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::DenseBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::sort<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::DenseBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::sort<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::DenseBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 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::DenseBase<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<float, -1, 3, 0, -1, 3>, Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::DenseBase<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::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, bool, 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::DenseBase<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<int, -1, -1, 0, -1, -1> >(Eigen::DenseBase<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::DenseBase<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> >&);
 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::DenseBase<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> >&);
 template void igl::sort<Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 2, 0, -1, 2> >(Eigen::DenseBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&);
 template void igl::sort<Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 2, 0, -1, 2> >(Eigen::DenseBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&);

+ 6 - 0
include/igl/sort.h

@@ -37,6 +37,12 @@ namespace igl
     const bool ascending,
     const bool ascending,
     Eigen::PlainObjectBase<DerivedY>& Y,
     Eigen::PlainObjectBase<DerivedY>& Y,
     Eigen::PlainObjectBase<DerivedIX>& IX);
     Eigen::PlainObjectBase<DerivedIX>& IX);
+  template <typename DerivedX, typename DerivedY>
+  IGL_INLINE void sort(
+    const Eigen::DenseBase<DerivedX>& X,
+    const int dim,
+    const bool ascending,
+    Eigen::PlainObjectBase<DerivedY>& Y);
   template <typename DerivedX, typename DerivedY, typename DerivedIX>
   template <typename DerivedX, typename DerivedY, typename DerivedIX>
   // Only better if size(X,dim) is small
   // Only better if size(X,dim) is small
   IGL_INLINE void sort_new(
   IGL_INLINE void sort_new(

+ 17 - 0
include/igl/sortrows.cpp

@@ -105,8 +105,24 @@ IGL_INLINE void igl::sortrows(
   }
   }
 }
 }
 
 
+template <typename DerivedX >
+IGL_INLINE void igl::sortrows(
+  const Eigen::DenseBase<DerivedX>& X,
+  const bool ascending,
+  Eigen::PlainObjectBase<DerivedX>& Y)
+{
+  Eigen::Matrix<int, DerivedX::RowsAtCompileTime, 1> I;
+  return igl::sortrows(X,ascending,Y,I);
+}
+
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
 // Explicit template instantiation
+// generated by autoexplicit.sh
+template void igl::sortrows<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+// generated by autoexplicit.sh
+template void igl::sortrows<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+// generated by autoexplicit.sh
+template void igl::sortrows<Eigen::Matrix<int, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::sortrows<Eigen::Matrix<int, -1, 4, 0, -1, 4>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<int, -1, 4, 0, -1, 4> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 4, 0, -1, 4> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::sortrows<Eigen::Matrix<int, -1, 4, 0, -1, 4>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<int, -1, 4, 0, -1, 4> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 4, 0, -1, 4> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::sortrows<Eigen::Matrix<int, -1, 4, 0, -1, 4>, Eigen::Matrix<long long, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<int, -1, 4, 0, -1, 4> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 4, 0, -1, 4> >&, Eigen::PlainObjectBase<Eigen::Matrix<long long, -1, 1, 0, -1, 1> >&);
 template void igl::sortrows<Eigen::Matrix<int, -1, 4, 0, -1, 4>, Eigen::Matrix<long long, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<int, -1, 4, 0, -1, 4> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 4, 0, -1, 4> >&, Eigen::PlainObjectBase<Eigen::Matrix<long long, -1, 1, 0, -1, 1> >&);
 template void igl::sortrows<Eigen::Matrix<int, 12, 4, 0, 12, 4>, Eigen::Matrix<long long, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<int, 12, 4, 0, 12, 4> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, 12, 4, 0, 12, 4> >&, Eigen::PlainObjectBase<Eigen::Matrix<long long, -1, 1, 0, -1, 1> >&);
 template void igl::sortrows<Eigen::Matrix<int, 12, 4, 0, 12, 4>, Eigen::Matrix<long long, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<int, 12, 4, 0, 12, 4> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, 12, 4, 0, 12, 4> >&, Eigen::PlainObjectBase<Eigen::Matrix<long long, -1, 1, 0, -1, 1> >&);
@@ -133,6 +149,7 @@ template void igl::sortrows<Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matri
 template void igl::sortrows<Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::sortrows<Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::sortrows<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::sortrows<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::sortrows<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<long, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&);
 template void igl::sortrows<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<long, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&);
+template void igl::sortrows<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 #ifdef WIN32
 #ifdef WIN32
 template void igl::sortrows<class Eigen::Matrix<double,-1,-1,0,-1,-1>,class Eigen::Matrix<__int64,-1,1,0,-1,1> >(class Eigen::DenseBase<class Eigen::Matrix<double,-1,-1,0,-1,-1> > const &,bool,class Eigen::PlainObjectBase<class Eigen::Matrix<double,-1,-1,0,-1,-1> > &,class Eigen::PlainObjectBase<class Eigen::Matrix<__int64,-1,1,0,-1,1> > &);
 template void igl::sortrows<class Eigen::Matrix<double,-1,-1,0,-1,-1>,class Eigen::Matrix<__int64,-1,1,0,-1,1> >(class Eigen::DenseBase<class Eigen::Matrix<double,-1,-1,0,-1,-1> > const &,bool,class Eigen::PlainObjectBase<class Eigen::Matrix<double,-1,-1,0,-1,-1> > &,class Eigen::PlainObjectBase<class Eigen::Matrix<__int64,-1,1,0,-1,1> > &);
 template void igl::sortrows<class Eigen::Matrix<int,-1,2,0,-1,2>,class Eigen::Matrix<__int64,-1,1,0,-1,1> >(class Eigen::DenseBase<class Eigen::Matrix<int,-1,2,0,-1,2> > const &,bool,class Eigen::PlainObjectBase<class Eigen::Matrix<int,-1,2,0,-1,2> > &,class Eigen::PlainObjectBase<class Eigen::Matrix<__int64,-1,1,0,-1,1> > &);
 template void igl::sortrows<class Eigen::Matrix<int,-1,2,0,-1,2>,class Eigen::Matrix<__int64,-1,1,0,-1,1> >(class Eigen::DenseBase<class Eigen::Matrix<int,-1,2,0,-1,2> > const &,bool,class Eigen::PlainObjectBase<class Eigen::Matrix<int,-1,2,0,-1,2> > &,class Eigen::PlainObjectBase<class Eigen::Matrix<__int64,-1,1,0,-1,1> > &);

+ 5 - 0
include/igl/sortrows.h

@@ -32,6 +32,11 @@ namespace igl
     const bool ascending,
     const bool ascending,
     Eigen::PlainObjectBase<DerivedX>& Y,
     Eigen::PlainObjectBase<DerivedX>& Y,
     Eigen::PlainObjectBase<DerivedI>& I);
     Eigen::PlainObjectBase<DerivedI>& I);
+  template <typename DerivedX >
+  IGL_INLINE void sortrows(
+    const Eigen::DenseBase<DerivedX>& X,
+    const bool ascending,
+    Eigen::PlainObjectBase<DerivedX>& Y);
 }
 }
 
 
 #ifndef IGL_STATIC_LIBRARY
 #ifndef IGL_STATIC_LIBRARY

+ 6 - 0
include/igl/unique_rows.cpp

@@ -74,6 +74,12 @@ IGL_INLINE void igl::unique_rows(
 
 
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
 // Explicit template instantiation
+// generated by autoexplicit.sh
+template void igl::unique_rows<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3>, Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+// generated by autoexplicit.sh
+template void igl::unique_rows<Eigen::Matrix<int, -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::DenseBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, 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::unique_rows<Eigen::Matrix<int, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::unique_rows<Eigen::Matrix<int, -1, 4, 0, -1, 4>, Eigen::Matrix<int, -1, 4, 0, -1, 4>, Eigen::Matrix<long long, -1, 1, 0, -1, 1>, Eigen::Matrix<long long, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<int, -1, 4, 0, -1, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 4, 0, -1, 4> >&, Eigen::PlainObjectBase<Eigen::Matrix<long long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long long, -1, 1, 0, -1, 1> >&);
 template void igl::unique_rows<Eigen::Matrix<int, -1, 4, 0, -1, 4>, Eigen::Matrix<int, -1, 4, 0, -1, 4>, Eigen::Matrix<long long, -1, 1, 0, -1, 1>, Eigen::Matrix<long long, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<int, -1, 4, 0, -1, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 4, 0, -1, 4> >&, Eigen::PlainObjectBase<Eigen::Matrix<long long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long long, -1, 1, 0, -1, 1> >&);
 template void igl::unique_rows<Eigen::Matrix<int, 12, 4, 0, 12, 4>, Eigen::Matrix<int, 12, 4, 0, 12, 4>, Eigen::Matrix<long long, -1, 1, 0, -1, 1>, Eigen::Matrix<long long, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<int, 12, 4, 0, 12, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, 12, 4, 0, 12, 4> >&, Eigen::PlainObjectBase<Eigen::Matrix<long long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long long, -1, 1, 0, -1, 1> >&);
 template void igl::unique_rows<Eigen::Matrix<int, 12, 4, 0, 12, 4>, Eigen::Matrix<int, 12, 4, 0, 12, 4>, Eigen::Matrix<long long, -1, 1, 0, -1, 1>, Eigen::Matrix<long long, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<int, 12, 4, 0, 12, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, 12, 4, 0, 12, 4> >&, Eigen::PlainObjectBase<Eigen::Matrix<long long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long long, -1, 1, 0, -1, 1> >&);
 // generated by autoexplicit.sh
 // generated by autoexplicit.sh

+ 1 - 3
include/igl/vector_area_matrix.cpp

@@ -6,15 +6,13 @@
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can
 // 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/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "vector_area_matrix.h"
 #include "vector_area_matrix.h"
+#include "boundary_facets.h"
 #include <vector>
 #include <vector>
 
 
 // Bug in unsupported/Eigen/SparseExtra needs iostream first
 // Bug in unsupported/Eigen/SparseExtra needs iostream first
 #include <iostream>
 #include <iostream>
 #include <unsupported/Eigen/SparseExtra>
 #include <unsupported/Eigen/SparseExtra>
 
 
-//#include <igl/boundary_loop.h>
-#include <igl/boundary_facets.h>
-
 template <typename DerivedF, typename Scalar>
 template <typename DerivedF, typename Scalar>
 IGL_INLINE void igl::vector_area_matrix(
 IGL_INLINE void igl::vector_area_matrix(
   const Eigen::PlainObjectBase<DerivedF> & F,
   const Eigen::PlainObjectBase<DerivedF> & F,

+ 11 - 0
tests/include/igl/accumarray.cpp

@@ -20,3 +20,14 @@ TEST_CASE("accumarray: matlab_help", "[igl]")
     (Eigen::VectorXd(4) << 101,0,206,208).finished();
     (Eigen::VectorXd(4) << 101,0,206,208).finished();
   test_common::assert_eq(A,Agt);
   test_common::assert_eq(A,Agt);
 }
 }
+
+TEST_CASE("accumarray: scalar", "[igl]")
+{
+  const auto n = 
+    (Eigen::VectorXi(5) << 1,2,2,4,5).finished();
+  Eigen::VectorXi C;
+  igl::accumarray(n,1,C);
+  const auto Cgt = 
+    (Eigen::VectorXi(6) << 0,1,2,0,1,1).finished();
+  test_common::assert_eq(C,Cgt);
+}

+ 30 - 4
tests/include/igl/boundary_facets.cpp

@@ -4,6 +4,9 @@
 #include <igl/sortrows.h>
 #include <igl/sortrows.h>
 #include <igl/setxor.h>
 #include <igl/setxor.h>
 
 
+#include <igl/matlab_format.h>
+#include <iostream>
+
 
 
 TEST_CASE("boundary_facets: single_tet", "[igl]")
 TEST_CASE("boundary_facets: single_tet", "[igl]")
 {
 {
@@ -55,16 +58,39 @@ TEST_CASE("boundary_facets: single_cube", "[igl]")
     5,7,4,
     5,7,4,
     7,6,4).finished();
     7,6,4).finished();
   Eigen::MatrixXi F;
   Eigen::MatrixXi F;
-  igl::boundary_facets(T,F);
+  Eigen::VectorXi J,K;
+  igl::boundary_facets(T,F,J,K);
   const auto sortF = [](const Eigen::MatrixXi & F)-> Eigen::MatrixXi
   const auto sortF = [](const Eigen::MatrixXi & F)-> Eigen::MatrixXi
   {
   {
     Eigen::MatrixXi sorted_F;
     Eigen::MatrixXi sorted_F;
-    Eigen::MatrixXi _1;
-    igl::sort(F,2,true, sorted_F,_1);
-    igl::sortrows(Eigen::MatrixXi(sorted_F),true,sorted_F,_1);
+    igl::sort(F,2,true, sorted_F);
+    igl::sortrows(Eigen::MatrixXi(sorted_F),true,sorted_F);
     return sorted_F;
     return sorted_F;
   };
   };
   Eigen::MatrixXi sorted_F = sortF(F);
   Eigen::MatrixXi sorted_F = sortF(F);
   Eigen::MatrixXi sorted_Fgt = sortF(Fgt);
   Eigen::MatrixXi sorted_Fgt = sortF(Fgt);
   test_common::assert_eq(sorted_Fgt,sorted_F);
   test_common::assert_eq(sorted_Fgt,sorted_F);
+  for(int f = 0;f<F.rows();f++)
+  {
+    Eigen::RowVector3i Ff;
+    igl::sort(F.row(f),2,true,Ff);
+    Eigen::RowVector3i Gf(
+      T(J(f), (K(f)+1)%4 ),
+      T(J(f), (K(f)+2)%4 ),
+      T(J(f), (K(f)+3)%4 ));
+    igl::sort(Eigen::RowVector3i(Gf),2,true,Gf);
+    test_common::assert_eq(Ff,Gf);
+  }
+}
+
+TEST_CASE("boundary_facets: non-manifold", "[igl]")
+{
+  const auto F = (Eigen::MatrixXi(3,3)<<0,1,2,1,0,3,0,1,4).finished();
+  auto Egt = (Eigen::MatrixXi(6,2)<<1,2,2,0,3,1,0,3,4,0,1,4).finished();
+  igl::sortrows(Eigen::MatrixXi(Egt),true,Egt);
+  Eigen::MatrixXi E;
+  igl::boundary_facets(F,E);
+  std::cerr<<igl::matlab_format(E,"E")<<std::endl;
+  igl::sortrows(Eigen::MatrixXi(E),true,E);
+  test_common::assert_eq(Egt,E);
 }
 }