Browse Source

fix some bad uses of Eigen::PlainObjectBase

Former-commit-id: f1afcae0c1e460b24b99ad553b735bf5ff5d8224
Alec Jacobson 9 years ago
parent
commit
c9be59b49f

+ 0 - 21
include/igl/fit_rigid.cpp

@@ -1,21 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2014 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 "fit_rigid.h"
-#include "procrustes.h"
-
-IGL_INLINE void igl::fit_rigid(
-  const Eigen::MatrixXd & A,
-  const Eigen::MatrixXd & B,
-  Eigen::Rotation2Dd & R,
-  Eigen::RowVector2d & t)
-{
-  using namespace Eigen;
-  Matrix2d Rmat;
-  procrustes(A,B,Rmat,t);
-  R.fromRotationMatrix(Rmat);
-}

+ 0 - 37
include/igl/fit_rigid.h

@@ -1,37 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2014 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_FIT_RIGID_H
-#define IGL_FIT_RIGID_H
-
-#if defined(_WIN32)
-  #pragma message("Deprecated. Use igl/procrustes.h instead")
-#else
-  #warning "Deprecated. Use igl/procrustes.h instead"
-#endif
-
-#include "igl_inline.h"
-#include <Eigen/Core>
-#include <Eigen/Geometry>
-
-namespace igl
-{
-  // Deprecated: please use procrustes(...) instead.
-  // Fit a rigid 
-  IGL_INLINE void fit_rigid(
-    const Eigen::MatrixXd & A,
-    const Eigen::MatrixXd & B,
-    Eigen::Rotation2Dd & R,
-    Eigen::RowVector2d & t);
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "fit_rigid.cpp"
-#endif
-
-#endif
-

+ 0 - 159
include/igl/lu_lagrange.cpp

@@ -1,159 +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 "lu_lagrange.h"
-
-// Cholesky LLT decomposition for symmetric positive definite
-//#include <Eigen/SparseExtra>
-// Bug in unsupported/Eigen/SparseExtra needs iostream first
-#include <iostream>
-#include <unsupported/Eigen/SparseExtra>
-#include <cassert>
-#include <cstdio>
-#include "find.h"
-#include "sparse.h"
-
-template <typename T>
-IGL_INLINE bool igl::lu_lagrange(
-  const Eigen::SparseMatrix<T> & ATA,
-  const Eigen::SparseMatrix<T> & C,
-  Eigen::SparseMatrix<T> & L,
-  Eigen::SparseMatrix<T> & U)
-{
-#if EIGEN_VERSION_AT_LEAST(3,0,92)
-#if defined(_WIN32)
-  #pragma message("lu_lagrange has not yet been implemented for your Eigen Version")
-#else
-  #warning lu_lagrange has not yet been implemented for your Eigen Version
-#endif
-
-  return false;
-#else
-  // number of unknowns
-  int n = ATA.rows();
-  // number of lagrange multipliers
-  int m = C.cols();
-
-  assert(ATA.cols() == n);
-  if(m != 0)
-  {
-    assert(C.rows() == n);
-    if(C.nonZeros() == 0)
-    {
-      // See note above about empty columns in C
-      fprintf(stderr,"Error: lu_lagrange() C has columns but no entries\n");
-      return false;
-    }
-  }
-
-  // Check that each column of C has at least one entry
-  std::vector<bool> has_entry; has_entry.resize(C.cols(),false);
-  // Iterate over outside
-  for(int k=0; k<C.outerSize(); ++k)
-  {
-    // Iterate over inside
-    for(typename Eigen::SparseMatrix<T>::InnerIterator it (C,k); it; ++it)
-    {
-      has_entry[it.col()] = true;
-    }
-  }
-  for(int i=0;i<(int)has_entry.size();i++)
-  {
-    if(!has_entry[i])
-    {
-      // See note above about empty columns in C
-      fprintf(stderr,"Error: lu_lagrange() C(:,%d) has no entries\n",i);
-      return false;
-    }
-  }
-
-
-
-  // Cholesky factorization of ATA
-  //// Eigen fails if you give a full view of the matrix like this:
-  //Eigen::SparseLLT<SparseMatrix<T> > ATA_LLT(ATA);
-  Eigen::SparseMatrix<T> ATA_LT = ATA.template triangularView<Eigen::Lower>();
-  Eigen::SparseLLT<Eigen::SparseMatrix<T> > ATA_LLT(ATA_LT);
-
-  Eigen::SparseMatrix<T> J = ATA_LLT.matrixL();
-
-  //if(!ATA_LLT.succeeded())
-  if(!((J*0).eval().nonZeros() == 0))
-  {
-    fprintf(stderr,"Error: lu_lagrange() failed to factor ATA\n");
-    return false;
-  }
-
-  if(m == 0)
-  {
-    // If there are no constraints (C is empty) then LU decomposition is just L
-    // and L' from cholesky decomposition
-    L = J;
-    U = J.transpose();
-  }else
-  {
-    // Construct helper matrix M
-    Eigen::SparseMatrix<T> M = C;
-    J.template triangularView<Eigen::Lower>().solveInPlace(M);
-
-    // Compute cholesky factorizaiton of M'*M
-    Eigen::SparseMatrix<T> MTM = M.transpose() * M;
-
-    Eigen::SparseLLT<Eigen::SparseMatrix<T> > MTM_LLT(MTM.template triangularView<Eigen::Lower>());
-
-    Eigen::SparseMatrix<T> K = MTM_LLT.matrixL();
-
-    //if(!MTM_LLT.succeeded())
-    if(!((K*0).eval().nonZeros() == 0))
-    {
-      fprintf(stderr,"Error: lu_lagrange() failed to factor MTM\n");
-      return false;
-    }
-
-    // assemble LU decomposition of Q
-    Eigen::Matrix<int,Eigen::Dynamic,1> MI;
-    Eigen::Matrix<int,Eigen::Dynamic,1> MJ;
-    Eigen::Matrix<T,Eigen::Dynamic,1> MV;
-    igl::find(M,MI,MJ,MV);
-
-    Eigen::Matrix<int,Eigen::Dynamic,1> KI;
-    Eigen::Matrix<int,Eigen::Dynamic,1> KJ;
-    Eigen::Matrix<T,Eigen::Dynamic,1> KV;
-    igl::find(K,KI,KJ,KV);
-
-    Eigen::Matrix<int,Eigen::Dynamic,1> JI;
-    Eigen::Matrix<int,Eigen::Dynamic,1> JJ;
-    Eigen::Matrix<T,Eigen::Dynamic,1> JV;
-    igl::find(J,JI,JJ,JV);
-
-    int nnz = JV.size()  + MV.size() + KV.size();
-
-    Eigen::Matrix<int,Eigen::Dynamic,1> UI(nnz);
-    Eigen::Matrix<int,Eigen::Dynamic,1> UJ(nnz);
-    Eigen::Matrix<T,Eigen::Dynamic,1> UV(nnz);
-    UI << JJ,                        MI, (KJ.array() + n).matrix();
-    UJ << JI, (MJ.array() + n).matrix(), (KI.array() + n).matrix(); 
-    UV << JV,                        MV,                     KV*-1;
-    igl::sparse(UI,UJ,UV,U);
-
-    Eigen::Matrix<int,Eigen::Dynamic,1> LI(nnz);
-    Eigen::Matrix<int,Eigen::Dynamic,1> LJ(nnz);
-    Eigen::Matrix<T,Eigen::Dynamic,1> LV(nnz);
-    LI << JI, (MJ.array() + n).matrix(), (KI.array() + n).matrix();
-    LJ << JJ,                        MI, (KJ.array() + n).matrix(); 
-    LV << JV,                        MV,                        KV;
-    igl::sparse(LI,LJ,LV,L);
-  }
-
-  return true;
-  #endif
-}
-
-#ifdef IGL_STATIC_LIBRARY
-// Explicit template specialization
-template bool igl::lu_lagrange<double>(Eigen::SparseMatrix<double, 0, int> const&, Eigen::SparseMatrix<double, 0, int> const&, Eigen::SparseMatrix<double, 0, int>&, Eigen::SparseMatrix<double, 0, int>&);
-#endif

+ 0 - 67
include/igl/lu_lagrange.h

@@ -1,67 +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_LU_LAGRANGE_H
-#define IGL_LU_LAGRANGE_H
-#include "igl_inline.h"
-
-#define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
-#include <Eigen/Dense>
-#include <Eigen/Sparse>
-namespace igl
-{
-  // KNOWN BUGS: This does not seem to be correct for non-empty C
-  //
-  // LU_LAGRANGE Compute a LU decomposition for a special type of
-  // matrix Q that is symmetric but not positive-definite:
-  // Q = [A'*A C
-  //      C'   0];
-  // where A'*A, or ATA, is given as a symmetric positive definite matrix and C
-  // has full column-rank(?)
-  //
-  // [J] = lu_lagrange(ATA,C)
-  //
-  // Templates:
-  //   T  should be a eigen matrix primitive type like int or double
-  // Inputs:
-  //   ATA   n by n square, symmetric, positive-definite system matrix, usually
-  //     the quadratic coefficients corresponding to the original unknowns in a
-  //     system
-  //   C  n by m rectangular matrix corresponding the quadratic coefficients of
-  //     the original unknowns times the lagrange multipliers enforcing linear
-  //     equality constraints
-  // Outputs:
-  //   L  lower triangular matrix such that Q = L*U
-  //   U  upper triangular matrix such that Q = L*U
-  // Returns true on success, false on error
-  //
-  // Note: C should *not* have any empty columns. Typically C is the slice of
-  // the linear constraints matrix Aeq concerning the unknown variables of a
-  // quadratic optimization. Generally constraints may deal with unknowns as
-  // well as knowns. Each linear constraint corresponds to a column of Aeq. As
-  // long as each constraint concerns at least one unknown then the
-  // corresponding column in C will have at least one non zero entry. If a
-  // constraint concerns *no* unknowns, you should double check that this is a
-  // valid constraint. How can you constrain known values to each other? This
-  // is either a contradiction to the knowns' values or redundent. In either
-  // case, it's not this functions responsiblilty to handle empty constraints
-  // so you will get an error.
-  //
-  template <typename T>
-  IGL_INLINE bool lu_lagrange(
-    const Eigen::SparseMatrix<T> & ATA,
-    const Eigen::SparseMatrix<T> & C,
-    Eigen::SparseMatrix<T> & L,
-    Eigen::SparseMatrix<T> & U);
-
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "lu_lagrange.cpp"
-#endif
-
-#endif

+ 1 - 2
include/igl/min_quad_with_fixed.cpp

@@ -1,6 +1,6 @@
 // This file is part of libigl, a simple c++ geometry processing library.
 //
-// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
+// 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
@@ -12,7 +12,6 @@
 #include "find.h"
 #include "sparse.h"
 #include "repmat.h"
-//#include "lu_lagrange.h"
 #include "matlab_format.h"
 #include "EPS.h"
 #include "cat.h"

+ 7 - 5
include/igl/mod.cpp

@@ -14,17 +14,19 @@ IGL_INLINE void igl::mod(
   Eigen::PlainObjectBase<DerivedB> & B)
 {
   B.resize(A.rows(),A.cols());
-  for(int i = 0;i<B.size();i++)
+  for(int i = 0;i<A.rows();i++)
   {
-    *(B.data()+i) = (*(A.data()+i))%base;
+    for(int j = 0;j<A.cols();j++)
+    {
+      B(i,j) = A(i,j)%base;
+    }
   }
 }
 template <typename DerivedA>
-IGL_INLINE Eigen::PlainObjectBase<DerivedA> igl::mod(
+IGL_INLINE DerivedA igl::mod(
   const Eigen::PlainObjectBase<DerivedA> & A, const int base)
 {
-#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
-  Eigen::PlainObjectBase<DerivedA> B;
+  DerivedA B;
   mod(A,base,B);
   return B;
 }

+ 1 - 1
include/igl/mod.h

@@ -24,7 +24,7 @@ namespace igl
     const int base,
     Eigen::PlainObjectBase<DerivedB> & B);
   template <typename DerivedA>
-  IGL_INLINE Eigen::PlainObjectBase<DerivedA> mod(
+  IGL_INLINE DerivedA mod(
     const Eigen::PlainObjectBase<DerivedA> & A, const int base);
 }
 #ifndef IGL_STATIC_LIBRARY

+ 8 - 10
include/igl/randperm.cpp

@@ -20,18 +20,16 @@ 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)
-{
-
-#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
-  Eigen::PlainObjectBase<DerivedI> I;
-  randperm(n,I);
-  return I;
-}
+//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 Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > igl::randperm<Eigen::Matrix<int, -1, 1, 0, -1, 1> >(int);
+//template Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > igl::randperm<Eigen::Matrix<int, -1, 1, 0, -1, 1> >(int);
 #endif

+ 2 - 2
include/igl/randperm.h

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

+ 11 - 13
include/igl/slice.cpp

@@ -225,24 +225,22 @@ IGL_INLINE void igl::slice(
 }
 
 template <typename DerivedX>
-IGL_INLINE Eigen::PlainObjectBase<DerivedX> igl::slice(
+IGL_INLINE DerivedX igl::slice(
   const Eigen::PlainObjectBase<DerivedX> & X,
   const Eigen::Matrix<int,Eigen::Dynamic,1> & R)
 {
-#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
-  Eigen::PlainObjectBase<DerivedX> Y;
+  DerivedX Y;
   igl::slice(X,R,Y);
   return Y;
 }
 
 template <typename DerivedX>
-IGL_INLINE Eigen::PlainObjectBase<DerivedX> igl::slice(
+IGL_INLINE DerivedX igl::slice(
   const Eigen::PlainObjectBase<DerivedX>& X,
   const Eigen::Matrix<int,Eigen::Dynamic,1> & R,
   const int dim)
 {
-#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
-  Eigen::PlainObjectBase<DerivedX> Y;
+  DerivedX Y;
   igl::slice(X,R,dim,Y);
   return Y;
 }
@@ -250,14 +248,14 @@ IGL_INLINE Eigen::PlainObjectBase<DerivedX> igl::slice(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // generated by autoexplicit.sh
-template Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > igl::slice<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);
-template Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > igl::slice<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);
-template Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > igl::slice<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&);
-template Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > igl::slice<Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, int);
-template Eigen::PlainObjectBase<Eigen::Matrix<double, 1, -1, 1, 1, -1> > igl::slice<Eigen::Matrix<double, 1, -1, 1, 1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 1, -1, 1, 1, -1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, int);
-template Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > igl::slice<Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, int);
+template Eigen::Matrix<double, -1, 1, 0, -1, 1>  igl::slice<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);
+template Eigen::Matrix<double, -1, -1, 0, -1, -1>  igl::slice<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);
+template Eigen::Matrix<double, -1, 1, 0, -1, 1>  igl::slice<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&);
+template Eigen::Matrix<double, -1, 3, 0, -1, 3>  igl::slice<Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, int);
+template Eigen::Matrix<double, 1, -1, 1, 1, -1>  igl::slice<Eigen::Matrix<double, 1, -1, 1, 1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 1, -1, 1, 1, -1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, int);
+template Eigen::Matrix<int, -1, 3, 0, -1, 3>  igl::slice<Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, int);
+template Eigen::Matrix<int, -1, -1, 0, -1, -1 > igl::slice<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&, int);
 template void igl::slice<std::complex<double>, std::complex<double> >(Eigen::SparseMatrix<std::complex<double>, 0, int> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::SparseMatrix<std::complex<double>, 0, int>&);
-template Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > igl::slice<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&, int);
 template void igl::slice<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<double, 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>&);
 template void igl::slice<Eigen::SparseMatrix<double, 0, int>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::SparseMatrix<double, 0, int> >(Eigen::SparseMatrix<double, 0, int> const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::SparseMatrix<double, 0, int>&);

+ 7 - 2
include/igl/slice.h

@@ -63,12 +63,17 @@ namespace igl
     const Eigen::Matrix<int,Eigen::Dynamic,1> & R,
     Eigen::PlainObjectBase<DerivedY> & Y);
   // VectorXi Y = slice(X,R);
+  //
+  // This templating is bad because the return type might not have the same
+  // size as `DerivedX`. This will probably only work if DerivedX has Dynamic
+  // as it's non-trivial sizes or if the number of rows in R happens to equal
+  // the number of rows in `DerivedX`.
   template <typename DerivedX>
-  IGL_INLINE Eigen::PlainObjectBase<DerivedX> slice(
+  IGL_INLINE DerivedX slice(
     const Eigen::PlainObjectBase<DerivedX> & X,
     const Eigen::Matrix<int,Eigen::Dynamic,1> & R);
   template <typename DerivedX>
-  IGL_INLINE Eigen::PlainObjectBase<DerivedX> slice(
+  IGL_INLINE DerivedX slice(
     const Eigen::PlainObjectBase<DerivedX>& X,
     const Eigen::Matrix<int,Eigen::Dynamic,1> & R,
     const int dim);

+ 4 - 6
include/igl/slice_mask.cpp

@@ -94,25 +94,23 @@ IGL_INLINE void igl::slice_mask(
 }
 
 template <typename DerivedX>
-IGL_INLINE Eigen::PlainObjectBase<DerivedX> igl::slice_mask(
+IGL_INLINE DerivedX igl::slice_mask(
   const Eigen::PlainObjectBase<DerivedX> & X,
   const Eigen::Array<bool,Eigen::Dynamic,1> & R,
   const Eigen::Array<bool,Eigen::Dynamic,1> & C)
 {
-#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
-  Eigen::PlainObjectBase<DerivedX> Y;
+  DerivedX Y;
   igl::slice_mask(X,R,C,Y);
   return Y;
 }
 
 template <typename DerivedX>
-IGL_INLINE Eigen::PlainObjectBase<DerivedX> igl::slice_mask(
+IGL_INLINE DerivedX igl::slice_mask(
   const Eigen::PlainObjectBase<DerivedX>& X,
   const Eigen::Array<bool,Eigen::Dynamic,1> & R,
   const int dim)
 {
-#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
-  Eigen::PlainObjectBase<DerivedX> Y;
+  DerivedX Y;
   igl::slice_mask(X,R,dim,Y);
   return Y;
 }

+ 7 - 3
include/igl/slice_mask.h

@@ -37,14 +37,18 @@ namespace igl
     const Eigen::Array<bool,Eigen::Dynamic,1> & R,
     const int dim,
     Eigen::PlainObjectBase<DerivedX> & Y);
-
+  //
+  // This templating is bad because the return type might not have the same
+  // size as `DerivedX`. This will probably only work if DerivedX has Dynamic
+  // as it's non-trivial sizes or if the number of rows in R happens to equal
+  // the number of rows in `DerivedX`.
   template <typename DerivedX>
-  IGL_INLINE Eigen::PlainObjectBase<DerivedX> slice_mask(
+  IGL_INLINE DerivedX slice_mask(
     const Eigen::PlainObjectBase<DerivedX> & X,
     const Eigen::Array<bool,Eigen::Dynamic,1> & R,
     const Eigen::Array<bool,Eigen::Dynamic,1> & C);
   template <typename DerivedX>
-  IGL_INLINE Eigen::PlainObjectBase<DerivedX> slice_mask(
+  IGL_INLINE DerivedX slice_mask(
     const Eigen::PlainObjectBase<DerivedX> & X,
     const Eigen::Array<bool,Eigen::Dynamic,1> & R,
     const int dim);

+ 76 - 3
style-guidelines.md

@@ -39,8 +39,6 @@ namespace igl
   // This is an example of a function, it takes a templated parameter and
   // shovels it into cout
   //
-  // Templates:
-  //   T  type that supports
   // Input:
   //   input  some input of a Printable type
   // Returns true for the sake of returning something
@@ -164,7 +162,7 @@ than pointers (e.g. `Matrix * mat`) or value (e.g. `Matrix mat`).
 All functions should be implemented with at least one overload that has a
 `void` or simple return type (e.g. `bool` on success/failure). With this
 implementation its then possible to write an overload that returns a single
-output.
+output. Please see [Templating with Eigen](#templatingwitheigen).
 
 For example:
 
@@ -176,6 +174,81 @@ template <typename Atype>
 Eigen::SparseMatrix<Atype> adjacency_matrix(const ... & F);
 ```
 
+## Templating with Eigen
+
+Functions taking Eigen dense matrices/arrays as inputs and outputs (but **not**
+return arguments), should template on top of `Eigen::PlainObjectBase`. **Each
+parameter** should be derived using its own template.
+
+For example,
+
+```cpp
+template <typename DerivedV, typename DerivedF, typename DerivedBC>
+void barycenter(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::PlainObjectBase<DerivedF> & F,
+  const Eigen::PlainObjectBase<DerivedBC> & BC);
+```
+
+The `Derived*` template encodes the scalar type (e.g. `double`, `int`), the
+number of rows and cols at compile time, and the data storage (Row-major vs.
+column-major). 
+
+Returning Eigen types is discouraged. In cases where the size and scalar type
+are a fixed **and matching** function of an input `Derived*` template, then
+return that `Derived*` type. **Do not** return
+`Eigen::PlainObjectBase<...>` types. For example, this function scales fits a
+given set of points to the unit cube. The return is a new set of vertex
+positions so its type should _match_ that of the input points:
+
+```cpp
+template <typename DerivedV>
+void DerivedV fit_to_unit_cube(const Eigen::PlainObjectBase<DerivedV> & V);
+```
+
+To implement this function, it is **required** to implement a more generic
+output-argument version and call that. So a full implementation looks like:
+
+In `igl/fit_in_unit_cube.h`:
+
+```cpp
+template <typename DerivedV, typename DerivedW>
+void fit_to_unit_cube(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  Eigen::PlainObjectBase<DerivedW> & W);
+template <typename DerivedV>
+void DerivedV fit_to_unit_cube(const Eigen::PlainObjectBase<DerivedV> & V);
+```
+
+In `igl/fit_in_unit_cube.cpp`:
+
+```
+template <typename DerivedV, typename DerivedW>
+void fit_to_unit_cube(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  Eigen::PlainObjectBase<DerivedW> & W)
+{
+  W = (V.rowwise()-V.colwise().minCoeff()).array() /
+    (V.maxCoeff()-V.minCoeff());
+}
+
+template <typename DerivedV>
+void DerivedV fit_to_unit_cube(const Eigen::PlainObjectBase<DerivedV> & V)
+{
+  DerivedV W;
+  fit_to_unit_cube(V,W);
+  return W;
+}
+```
+
+Notice that `W` is declared as a `DerivedV` type and **not**
+`Eigen::PlainObjectBase<DerivedV>` type.
+
+**Note:** Not all functions are suitable for returning Eigen types. For example
+`igl::barycenter` above outputs a #F by dim list of barycenters. Returning a
+`DerivedV` type would be inappropriate since the number of rows in `DerivedV`
+will be #V and may not match the number of rows in `DerivedF` (#F).
+
 ## Function naming conventions 
 
 Functions (and [thus also files](#filefunction)) should have simple,