Browse Source

path to executable (working on OSX), dated copy of file with permissions, draw_mesh less kruft

Former-commit-id: 1b7a32cab78c9e1442c3e73d8351721b178cde43
Alec Jacobson (jalec 11 years ago
parent
commit
0d2b528651

+ 81 - 0
include/igl/dated_copy.cpp

@@ -0,0 +1,81 @@
+#include "dated_copy.h"
+#include "dirname.h"
+#include "basename.h"
+
+#include <ctime>
+#include <fstream>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <iostream>
+
+bool igl::dated_copy(const std::string & src_path, const std::string & dir)
+{
+  using namespace std;
+  using namespace igl;
+  // Get time and date as string
+  char buffer[80];
+  time_t rawtime;
+  struct tm * timeinfo;
+  time (&rawtime);
+  timeinfo = localtime (&rawtime);
+  // ISO 8601 format with hyphens instead of colons and no timezone offset
+  strftime (buffer,80,"%Y-%m-%dT%H-%M-%S",timeinfo);
+  string src_basename = basename(src_path);
+  string dst_basename = src_basename+"-"+buffer;
+  string dst_path = dir+"/"+dst_basename;
+  cerr<<"Saving binary to "<<dst_path;
+  {
+    // http://stackoverflow.com/a/10195497/148668
+    ifstream src(src_path,ios::binary);
+    if (!src.is_open()) 
+    {
+      cerr<<" failed."<<endl;
+      return false;
+    }
+    ofstream dst(dst_path,ios::binary);
+    if(!dst.is_open())
+    {
+      cerr<<" failed."<<endl;
+      return false;
+    }
+    dst << src.rdbuf();
+  }
+  cerr<<" succeeded."<<endl;
+  cerr<<"Setting permissions of "<<dst_path;
+  {
+    int src_posix = fileno(fopen(src_path.c_str(),"r"));
+    if(src_posix == -1)
+    {
+      cerr<<" failed."<<endl;
+      return false;
+    }
+    struct stat fst;
+    fstat(src_posix,&fst);
+    int dst_posix = fileno(fopen(dst_path.c_str(),"r"));
+    if(dst_posix == -1)
+    {
+      cerr<<" failed."<<endl;
+      return false;
+    }
+    //update to the same uid/gid
+    if(fchown(dst_posix,fst.st_uid,fst.st_gid))
+    {
+      cerr<<" failed."<<endl;
+      return false;
+    }
+    //update the permissions 
+    if(fchmod(dst_posix,fst.st_mode) == -1)
+    {
+      cerr<<" failed."<<endl;
+      return false;
+    }
+    cerr<<" succeeded."<<endl;
+  }
+  return true;
+}
+
+bool igl::dated_copy(const std::string & src_path)
+{
+  return dated_copy(src_path,dirname(src_path));
+}

+ 31 - 0
include/igl/dated_copy.h

@@ -0,0 +1,31 @@
+// 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_DATED_COPY_H
+#define IGL_DATED_COPY_H
+#include "igl_inline.h"
+#include <string>
+namespace igl
+{
+  // Copy the given file to a new file with the same basename in `dir`
+  // directory with the current date and time as a suffix.
+  //
+  // Inputs:
+  //   src_path  path to source file
+  //   dir  directory of destination file
+  // Example:
+  //   dated_copy("/path/to/foo","/bar/");
+  //   // copies /path/to/foo to /bar/foo-2013-12-12T18-10-56
+  bool dated_copy(const std::string & src_path, const std::string & dir);
+  // Wrapper using directory of source file
+  bool dated_copy(const std::string & src_path);
+}
+#ifdef IGL_HEADER_ONLY
+#  include "dated_copy.cpp"
+#endif
+#endif 
+

+ 157 - 318
include/igl/draw_mesh.cpp

@@ -13,27 +13,10 @@ IGL_INLINE void igl::draw_mesh(
   const Eigen::MatrixXi & F,
   const Eigen::MatrixXd & N)
 {
-  glBegin(GL_TRIANGLES);
-  // loop over faces
-  for(int i = 0; i<F.rows();i++)
-  {
-    // loop over corners of triangle
-    for(int j = 0;j<3;j++)
-    {
-      if(N.rows() == V.rows())
-      {
-        glNormal3d(N(F(i,j),0),N(F(i,j),1),N(F(i,j),2));
-      }else if(N.rows() == F.rows()*3)
-      {
-        glNormal3d(N(i*3+j,0),N(i*3+j,1),N(i*3+j,2));
-      }else if(N.rows() == F.rows())
-      {
-        glNormal3d(N(i,0),N(i,1),N(i,2));
-      }
-      glVertex3d(V(F(i,j),0),V(F(i,j),1),V(F(i,j),2));
-    }
-  }
-  glEnd();
+  using namespace Eigen;
+  MatrixXd _d;
+  MatrixXi _i;
+  return draw_mesh(V,F,N,_i,_d,_d,_i,_d,0,_i,0);
 }
 
 IGL_INLINE void igl::draw_mesh(
@@ -42,43 +25,10 @@ IGL_INLINE void igl::draw_mesh(
   const Eigen::MatrixXd & N,
   const Eigen::MatrixXd & C)
 {
-  glBegin(GL_TRIANGLES);
-  // loop over faces
-  for(int i = 0; i<F.rows();i++)
-  {
-    // loop over corners of triangle
-    for(int j = 0;j<3;j++)
-    {
-      if(C.rows() == 1)
-      {
-        glColor3d(C(0,0),C(0,1),C(0,2));
-      }else if(C.rows() == V.rows())
-      {
-        glColor3d(C(F(i,j),0),C(F(i,j),1),C(F(i,j),2));
-      }else if(C.rows() == F.rows()*3)
-      {
-        glColor3d(C(i*3+j,0),C(i*3+j,1),C(i*3+j,2));
-      }else if(C.rows() == F.rows())
-      {
-        glColor3d(C(i,0),C(i,1),C(i,2));
-      }else
-      {
-        assert(C.size() == 0);
-      }
-      if(N.rows() == V.rows())
-      {
-        glNormal3d(N(F(i,j),0),N(F(i,j),1),N(F(i,j),2));
-      }else if(N.rows() == F.rows()*3)
-      {
-        glNormal3d(N(i*3+j,0),N(i*3+j,1),N(i*3+j,2));
-      }else if(N.rows() == F.rows())
-      {
-        glNormal3d(N(i,0),N(i,1),N(i,2));
-      }
-      glVertex3d(V(F(i,j),0),V(F(i,j),1),V(F(i,j),2));
-    }
-  }
-  glEnd();
+  using namespace Eigen;
+  MatrixXd _d;
+  MatrixXi _i;
+  return draw_mesh(V,F,N,_i,C,_d,_i,_d,0,_i,0);
 }
 
 IGL_INLINE void igl::draw_mesh(
@@ -88,65 +38,10 @@ IGL_INLINE void igl::draw_mesh(
   const Eigen::MatrixXd & C,
   const Eigen::MatrixXd & TC)
 {
-  glBegin(GL_TRIANGLES);
-  // loop over faces
-  for(int i = 0; i<F.rows();i++)
-  {
-    // loop over corners of triangle
-    for(int j = 0;j<3;j++)
-    {
-
-      if(TC.rows() == 1)
-      {
-        glTexCoord2d(TC(F(i,j),0),TC(F(i,j),1));
-      }else if(TC.rows() == V.rows())
-      {
-        glTexCoord2d(TC(F(i,j),0),TC(F(i,j),1));
-      }else if(TC.rows() == F.rows()*2)
-      {
-        glTexCoord2d(TC(i*2+j,0),TC(i*2+j,1));
-      }else if(TC.rows() == F.rows())
-      {
-        glTexCoord2d(TC(i,0),TC(i,1));
-      }else
-      {
-        assert(TC.size() == 0);
-      }
-
-      if(C.rows() == 1)
-      {
-        glColor3d(C(0,0),C(0,1),C(0,2));
-      }else if(C.rows() == V.rows())
-      {
-        glColor3d(C(F(i,j),0),C(F(i,j),1),C(F(i,j),2));
-      }else if(C.rows() == F.rows()*3)
-      {
-        glColor3d(C(i*3+j,0),C(i*3+j,1),C(i*3+j,2));
-      }else if(C.rows() == F.rows())
-      {
-        glColor3d(C(i,0),C(i,1),C(i,2));
-      }else
-      {
-        assert(C.size() == 0);
-      }
-
-      if(N.rows() == V.rows())
-      {
-        glNormal3d(N(F(i,j),0),N(F(i,j),1),N(F(i,j),2));
-      }else if(N.rows() == F.rows()*3)
-      {
-        glNormal3d(N(i*3+j,0),N(i*3+j,1),N(i*3+j,2));
-      }else if(N.rows() == F.rows())
-      {
-        glNormal3d(N(i,0),N(i,1),N(i,2));
-      }else
-      {
-        assert(N.size() == 0);
-      }
-      glVertex3d(V(F(i,j),0),V(F(i,j),1),V(F(i,j),2));
-    }
-  }
-  glEnd();
+  using namespace Eigen;
+  MatrixXd _d;
+  MatrixXi _i;
+  return draw_mesh(V,F,N,_i,C,TC,_i,_d,0,_i,0);
 }
 
 IGL_INLINE void igl::draw_mesh(
@@ -160,120 +55,8 @@ IGL_INLINE void igl::draw_mesh(
   const Eigen::MatrixXi & WI,
   const GLuint WI_index)
 {
-  using namespace std;
-  if(F.size() > 0)
-  {
-    assert(F.maxCoeff() < V.rows());
-    assert(V.cols() == 3);
-    assert(C.rows() == V.rows() || C.rows() == F.rows()*3 || C.size() == 0);
-    assert(TC.rows() == V.rows() || TC.rows() == F.rows()*3 || TC.size() == 0);
-    assert(C.cols() == 3 || C.size() == 0);
-    assert(
-      N.rows() == V.rows() || N.rows() == F.rows()*3 || N.rows() ==F.rows());
-    assert(N.cols() == 3);
-  }
-  if(W.size()>0)
-  {
-    assert(W.rows() == V.rows());
-    assert(WI.rows() == V.rows());
-    assert(W.cols() == WI.cols());
-  }
-
-  glBegin(GL_TRIANGLES);
-  // loop over faces
-  for(int i = 0; i<F.rows();i++)
-  {
-    // loop over corners of triangle
-    for(int j = 0;j<3;j++)
-    {
-      if(W.size()>0 && W_index !=0 && WI_index != 0)
-      {
-        int weights_left = W.cols();
-        while(weights_left != 0)
-        {
-          int pass_size = std::min(4,weights_left);
-          int weights_already_passed = W.cols()-weights_left;
-          // Get attribute location of next 4 weights
-          int pass_W_index = W_index + weights_already_passed/4;
-          int pass_WI_index = WI_index + weights_already_passed/4;
-          switch(pass_size)
-          {
-            case 1:
-              glVertexAttrib1d(
-                pass_W_index,
-                W(F(i,j),0+weights_already_passed));
-              glVertexAttrib1d(
-                pass_WI_index,
-                WI(F(i,j),0+weights_already_passed));
-              break;
-            case 2:
-              glVertexAttrib2d(
-                pass_W_index,
-                W(F(i,j),0+weights_already_passed),
-                W(F(i,j),1+weights_already_passed));
-              glVertexAttrib2d(
-                pass_WI_index,
-                WI(F(i,j),0+weights_already_passed),
-                WI(F(i,j),1+weights_already_passed));
-              break;
-            case 3:
-              glVertexAttrib3d(
-                pass_W_index,
-                W(F(i,j),0+weights_already_passed),
-                W(F(i,j),1+weights_already_passed),
-                W(F(i,j),2+weights_already_passed));
-              glVertexAttrib3d(
-                pass_WI_index,
-                WI(F(i,j),0+weights_already_passed),
-                WI(F(i,j),1+weights_already_passed),
-                WI(F(i,j),2+weights_already_passed));
-              break;
-            default:
-              glVertexAttrib4d(
-                pass_W_index,
-                W(F(i,j),0+weights_already_passed),
-                W(F(i,j),1+weights_already_passed),
-                W(F(i,j),2+weights_already_passed),
-                W(F(i,j),3+weights_already_passed));
-              glVertexAttrib4d(
-                pass_WI_index,
-                WI(F(i,j),0+weights_already_passed),
-                WI(F(i,j),1+weights_already_passed),
-                WI(F(i,j),2+weights_already_passed),
-                WI(F(i,j),3+weights_already_passed));
-              break;
-          }
-          weights_left -= pass_size;
-        }
-      }
-      if(TC.rows() == V.rows())
-      {
-        glTexCoord2d(TC(F(i,j),0),TC(F(i,j),1));
-      }else if(TC.rows() == F.rows()*3)
-      {
-        glTexCoord2d(TC(F(i,j),0),TC(F(i,j),1));
-      }
-      if(C.rows() == V.rows())
-      {
-        glColor3d(C(F(i,j),0),C(F(i,j),1),C(F(i,j),2));
-      }else if(C.rows() == F.rows()*3)
-      {
-        glColor3d(C(i*3+j,0), C(i*3+j,1), C(i*3+j,2));
-      }
-      if(N.rows() == V.rows())
-      {
-        glNormal3d(N(F(i,j),0),N(F(i,j),1),N(F(i,j),2));
-      }else if(N.rows() == F.rows()*3)
-      {
-        glNormal3d(N(i*3+j,0),N(i*3+j,1),N(i*3+j,2));
-      }else if(N.rows() == F.rows())
-      {
-        glNormal3d(N(i,0),N(i,1),N(i,2));
-      }
-      glVertex3d(V(F(i,j),0),V(F(i,j),1),V(F(i,j),2));
-    }
-  }
-  glEnd();
+  using namespace Eigen;
+  return draw_mesh(V,F,N,MatrixXi(),C,TC,MatrixXi(),W,W_index,WI,WI_index);
 }
 
 IGL_INLINE void igl::draw_mesh(
@@ -290,6 +73,18 @@ IGL_INLINE void igl::draw_mesh(
   const GLuint WI_index)
 {
   using namespace std;
+  using namespace Eigen;
+  const int rF = F.rows();
+  const int cC = C.cols();
+  const int rC = C.rows();
+  const int cW = W.cols();
+  const int rW = W.rows();
+  const int rV = V.rows();
+  const int rTC = TC.rows();
+  const int rTF = TF.rows();
+  const int rNF = NF.rows();
+  const int rN = N.rows();
+
   if(F.size() > 0)
   {
     assert(F.maxCoeff() < V.rows());
@@ -308,112 +103,156 @@ IGL_INLINE void igl::draw_mesh(
 
   glBegin(GL_TRIANGLES);
   // loop over faces
-  for(int i = 0; i<F.rows();i++)
+  for(int i = 0; i<rF;i++)
   {
     // loop over corners of triangle
     for(int j = 0;j<3;j++)
     {
-      if(W.size()>0 && W_index !=0 && WI_index != 0)
+
+      int tc = -1;
+      if(rTF != 0)
       {
-        int weights_left = W.cols();
-        while(weights_left != 0)
-        {
-          int pass_size = std::min(4,weights_left);
-          int weights_already_passed = W.cols()-weights_left;
-          // Get attribute location of next 4 weights
-          int pass_W_index = W_index + weights_already_passed/4;
-          int pass_WI_index = WI_index + weights_already_passed/4;
-          switch(pass_size)
-          {
-            case 1:
-              glVertexAttrib1d(
-                pass_W_index,
-                W(F(i,j),0+weights_already_passed));
-              glVertexAttrib1d(
-                pass_WI_index,
-                WI(F(i,j),0+weights_already_passed));
-              break;
-            case 2:
-              glVertexAttrib2d(
-                pass_W_index,
-                W(F(i,j),0+weights_already_passed),
-                W(F(i,j),1+weights_already_passed));
-              glVertexAttrib2d(
-                pass_WI_index,
-                WI(F(i,j),0+weights_already_passed),
-                WI(F(i,j),1+weights_already_passed));
-              break;
-            case 3:
-              glVertexAttrib3d(
-                pass_W_index,
-                W(F(i,j),0+weights_already_passed),
-                W(F(i,j),1+weights_already_passed),
-                W(F(i,j),2+weights_already_passed));
-              glVertexAttrib3d(
-                pass_WI_index,
-                WI(F(i,j),0+weights_already_passed),
-                WI(F(i,j),1+weights_already_passed),
-                WI(F(i,j),2+weights_already_passed));
-              break;
-            default:
-              glVertexAttrib4d(
-                pass_W_index,
-                W(F(i,j),0+weights_already_passed),
-                W(F(i,j),1+weights_already_passed),
-                W(F(i,j),2+weights_already_passed),
-                W(F(i,j),3+weights_already_passed));
-              glVertexAttrib4d(
-                pass_WI_index,
-                WI(F(i,j),0+weights_already_passed),
-                WI(F(i,j),1+weights_already_passed),
-                WI(F(i,j),2+weights_already_passed),
-                WI(F(i,j),3+weights_already_passed));
-              break;
-          }
-          weights_left -= pass_size;
-        }
-      }
-      if(TC.rows() > 0 && TF.rows() > 0)
+        tc = TF(i,j);
+      } else if(rTC == 1)
       {
-        if(TF(i,j) >=  0 && TF(i,j)<TC.rows())
-        {
-          glTexCoord2d(TC(TF(i,j),0),TC(TF(i,j),1));
-          //printf("TexCoord: %d %g %g\n",TF(i,j), TC(TF(i,j),0),TC(TF(i,j),1));
-        }// else what?
+        tc = 0;
+      }else if(rTC == rV)
+      {
+        tc = F(i,j);
+      }else if(rTC == rF*2)
+      {
+        tc = i*2 + j;
+      }else if(rTC == rF)
+      {
+        tc = i;
+      }else
+      {
+        assert(TC.size() == 0);
       }
-      if(C.rows() == V.rows())
+
+      // RGB(A)
+      Matrix<MatrixXd::Scalar,1,Dynamic> color;
+      if(rC == 1)
+      {
+        color = C.row(0);
+      }else if(rC == rV)
+      {
+        color = C.row(F(i,j));
+      }else if(rC == rF*3)
+      {
+        color = C.row(i*3+j);
+      }else if(rC == rF)
       {
-        glColor3d(C(F(i,j),0),C(F(i,j),1),C(F(i,j),2));
-      }else if(C.rows() == F.rows()*3)
+        color = C.row(i);
+      }else
       {
-        glColor3d(C(i*3+j,0), C(i*3+j,1), C(i*3+j,2));
+        assert(C.size() == 0);
       }
-      if(NF.rows() > 0)
+
+      int n = -1;
+      if(rNF != 0)
       {
-        const int nfij = NF(i,j);
-        if(nfij >=  0 && nfij<N.rows())
-        {
-          glNormal3d(N(nfij,0),N(nfij,1),N(nfij,2));
-          //printf("Normal: %d %g %g %g\n",nfij, N(nfij,0),N(nfij,1),N(nfij,2));
-        }// else what?
+        n = NF(i,j);
+      } else if(rN == 1)
+      {
+        n = 0;
+      }else if(rN == rV)
+      {
+        n = F(i,j);
+      }else if(rN == rF*2)
+      {
+        n = i*2 + j;
+      }else if(rN == rF)
+      {
+        n = i;
+      }else
+      {
+        assert(N.size() == 0);
+      }
 
-      } else
       {
-        if(N.rows() == V.rows())
+        if(rW>0 && W_index !=0 && WI_index != 0)
         {
-          glNormal3d(N(F(i,j),0),N(F(i,j),1),N(F(i,j),2));
-        }else if(N.rows() == F.rows()*3)
+          int weights_left = cW;
+          while(weights_left != 0)
+          {
+            int pass_size = std::min(4,weights_left);
+            int weights_already_passed = cW-weights_left;
+            // Get attribute location of next 4 weights
+            int pass_W_index = W_index + weights_already_passed/4;
+            int pass_WI_index = WI_index + weights_already_passed/4;
+            switch(pass_size)
+            {
+              case 1:
+                glVertexAttrib1d(
+                  pass_W_index,
+                  W(F(i,j),0+weights_already_passed));
+                glVertexAttrib1d(
+                  pass_WI_index,
+                  WI(F(i,j),0+weights_already_passed));
+                break;
+              case 2:
+                glVertexAttrib2d(
+                  pass_W_index,
+                  W(F(i,j),0+weights_already_passed),
+                  W(F(i,j),1+weights_already_passed));
+                glVertexAttrib2d(
+                  pass_WI_index,
+                  WI(F(i,j),0+weights_already_passed),
+                  WI(F(i,j),1+weights_already_passed));
+                break;
+              case 3:
+                glVertexAttrib3d(
+                  pass_W_index,
+                  W(F(i,j),0+weights_already_passed),
+                  W(F(i,j),1+weights_already_passed),
+                  W(F(i,j),2+weights_already_passed));
+                glVertexAttrib3d(
+                  pass_WI_index,
+                  WI(F(i,j),0+weights_already_passed),
+                  WI(F(i,j),1+weights_already_passed),
+                  WI(F(i,j),2+weights_already_passed));
+                break;
+              default:
+                glVertexAttrib4d(
+                  pass_W_index,
+                  W(F(i,j),0+weights_already_passed),
+                  W(F(i,j),1+weights_already_passed),
+                  W(F(i,j),2+weights_already_passed),
+                  W(F(i,j),3+weights_already_passed));
+                glVertexAttrib4d(
+                  pass_WI_index,
+                  WI(F(i,j),0+weights_already_passed),
+                  WI(F(i,j),1+weights_already_passed),
+                  WI(F(i,j),2+weights_already_passed),
+                  WI(F(i,j),3+weights_already_passed));
+                break;
+            }
+            weights_left -= pass_size;
+          }
+        }
+        if(tc != -1)
+        {
+          glTexCoord2d(TC(tc,0),TC(tc,1));
+        }
+        switch(cC)
         {
-          glNormal3d(N(i*3+j,0),N(i*3+j,1),N(i*3+j,2));
-        }else if(N.rows() == F.rows())
+          case 3:
+            glColor3dv(color.data());
+            break;
+          case 4:
+            glColor4dv(color.data());
+            break;
+          default:
+            break;
+        }
+        if(n != -1)
         {
-          glNormal3d(N(i,0),N(i,1),N(i,2));
+          glNormal3d(N(n,0),N(n,1),N(n,2));
         }
+        glVertex3d(V(F(i,j),0),V(F(i,j),1),V(F(i,j),2));
       }
-      glVertex3d(V(F(i,j),0),V(F(i,j),1),V(F(i,j),2));
-          //printf("Vertex: %d %g %g %g\n",F(i,j), V(F(i,j),0),V(F(i,j),1),V(F(i,j),2));
     }
-    //printf("\n");
   }
   glEnd();
 }

+ 38 - 0
include/igl/path_to_executable.cpp

@@ -0,0 +1,38 @@
+#include "path_to_executable.h"
+#ifdef __APPLE__
+#  include <mach-o/dyld.h>
+#endif
+std::string igl::path_to_executable()
+{
+  // http://pastebin.com/ffzzxPzi
+  using namespace std;
+  std::string path;
+  char buffer[1024];
+  uint32_t size = sizeof(buffer);
+#if defined (WIN32) || defined (WIN64)
+  GetModuleFileName(buffer, &size);
+  path = buffer;
+#elif defined (__APPLE__)
+  if(_NSGetExecutablePath(buffer, &size) == 0)
+  {
+    path = buffer;
+  }
+#elif defined(UNIX)
+  if (readlink("/proc/self/exe", buffer, sizeof(buffer)) == -1)
+  {
+    path = buffer;
+  }
+#elif defined(__FreeBSD__)
+  int mib[4];
+  mib[0] = CTL_KERN;
+  mib[1] = KERN_PROC;
+  mib[2] = KERN_PROC_PATHNAME;
+  mib[3] = -1;
+  sysctl(mib, 4, buffer, sizeof(buffer), NULL, 0);
+  path = buffer;
+#elif defined(SUNOS)
+  path = getexecname();
+#endif
+  return path;
+}
+

+ 21 - 0
include/igl/path_to_executable.h

@@ -0,0 +1,21 @@
+// 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_PATH_TO_EXECUTABLE_H
+#define IGL_PATH_TO_EXECUTABLE_H
+#include "igl_inline.h"
+#include <string>
+namespace igl
+{
+  // Return the path of the current executable.
+  // Note: Tested for Mac OS X
+  std::string path_to_executable();
+}
+#ifdef IGL_HEADER_ONLY
+#  include "path_to_executable.cpp"
+#endif
+#endif 

+ 1 - 0
include/igl/readDMAT.cpp

@@ -203,4 +203,5 @@ template bool igl::readDMAT<Eigen::Matrix<double, -1, -1, 0, -1, -1> >(std::basi
 template bool igl::readDMAT<double>(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >&);
 template bool igl::readDMAT<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template bool igl::readDMAT<Eigen::Matrix<double, 4, 1, 0, 4, 1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, 4, 1, 0, 4, 1> >&);
+template bool igl::readDMAT<Eigen::Matrix<double, -1, 1, 0, -1, 1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 #endif

+ 3 - 0
include/igl/repmat.h

@@ -15,6 +15,9 @@
 
 namespace igl
 {
+  // At least for Dense matrices this is replaced by `replicate` e.g., dst = src.replicate(n,m);
+  // http://forum.kde.org/viewtopic.php?f=74&t=90876#p173517
+
   // Ideally this is a super overloaded function that behaves just like
   // matlab's repmat