Browse Source

explicit templates matlab workspace and last commit before hunting bug in alec's skinning

Former-commit-id: fd074032e762ace3333801b0fb8488fdb9cec8e1
jalec 13 years ago
parent
commit
778c042ccf

+ 2 - 1
Makefile

@@ -16,9 +16,10 @@ OBJ_FILES=$(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))
 # include igl headers
 INC+=-Iinclude/
 
+CFLAGS += -Wall -arch i386 -arch x86_64
 # optimized default settings
 all: LFLAGS +=
-all: CFLAGS += -O3 -DNDEBUG -Wall
+all: CFLAGS += -O3 -DNDEBUG -j 
 debug: CFLAGS += -g -Wall -Werror
 
 # Eigen dependency

+ 27 - 0
examples/MatlabWorkspace/Makefile

@@ -0,0 +1,27 @@
+.PHONY: all
+
+IGL=../../
+IGL_LIB=-L$(IGL)/lib -ligl
+IGL_INC=-I$(IGL)/include
+
+EIGEN3_INC=-I/usr/local/include/eigen3 -I/usr/local/include/eigen3/unsupported
+
+MATLAB_INC=-I$(MATLAB)/extern/include/
+MATLAB_LIB=-L$(MATLAB)/bin/maci64 -lmx -lmat
+
+LIB+=$(IGL_LIB) $(MATLAB_LIB)
+INC+=$(IGL_INC) $(EIGEN3_INC) $(MATLAB_INC)
+
+all: example 
+
+CFLAGS += -g
+
+example: example.o
+	g++ -o example example.o $(LIB)
+
+example.o: example.cpp
+	g++ $(CFLAGS) -o $@ -c $< $(INC)
+
+clean:
+	rm -f example.o
+	rm -f example

+ 13 - 0
examples/MatlabWorkspace/README

@@ -0,0 +1,13 @@
+This is a simple example program that shows how to use the MatlabWorkspace
+class of the igl library
+
+
+To Build:
+  make
+
+To Run:
+  ./example [input path] [output path]
+
+Example Run #1:
+  Issuing:
+    ./example example.dmat output.mat

+ 32 - 0
examples/MatlabWorkspace/example.cpp

@@ -0,0 +1,32 @@
+#include <Eigen/Core>
+
+#include <igl/readDMAT.h>
+#include <cstdio>
+
+#ifndef IGL_HEADER_ONLY
+#  define IGL_HEADER_ONLY
+#  define IGL_HEADER_ONLY_WAS_NOT_DEFINED
+#endif
+#include <igl/MatlabWorkspace.h>
+#include <igl/on_boundary.h>
+#ifdef IGL_HEADER_ONLY_WAS_NOT_DEFINED
+#  undef IGL_HEADER_ONLY
+#endif
+
+int main(int argc, char * argv[])
+{
+  using namespace igl;
+  using namespace Eigen;
+  if(argc <= 2)
+  {
+    printf("USAGE:\n  ./example [input path] [output path]\n");
+    return 1;
+  }
+  MatrixXd M;
+  readDMAT(argv[1],M);
+  MatlabWorkspace mat;
+  mat.save(M,"M");
+  mat.write(argv[2]);
+
+  return 0;
+}

+ 7 - 0
examples/MatlabWorkspace/example.dmat

@@ -0,0 +1,7 @@
+3 2
+1
+4
+2
+5
+3
+6

BIN
examples/MatlabWorkspace/example.mat


+ 136 - 0
include/igl/MatlabWorkspace.cpp

@@ -0,0 +1,136 @@
+// Don't let libigl.a compile anything here
+#ifdef IGL_HEADER_ONLY
+
+#include "MatlabWorkspace.h"
+
+// IGL
+#include "list_to_matrix.h"
+
+// MATLAB
+#include "mat.h"
+
+// STL
+#include <iostream>
+#include <algorithm>
+
+IGL_INLINE igl::MatlabWorkspace::MatlabWorkspace()
+{
+}
+
+IGL_INLINE igl::MatlabWorkspace::~MatlabWorkspace()
+{
+  // clean up data
+  clear();
+}
+
+IGL_INLINE void igl::MatlabWorkspace::clear()
+{
+  for_each(data.begin(),data.end(),&mxDestroyArray);
+}
+
+IGL_INLINE bool igl::MatlabWorkspace::write(const std::string & path) const
+{
+  using namespace std;
+  MATFile * mat_file = matOpen(path.c_str(), "w");
+  assert(names.size() == data.size());
+  // loop over names and data
+  for(int i = 0;i < names.size(); i++)
+  {
+    // Put variable as LOCAL variable
+    int status = matPutVariable(mat_file,names[i].c_str(), data[i]);
+    if(status != 0) 
+    {
+      cerr<<"^MatlabWorkspace::save Error: matPutVariable ("<<names[i]<<
+        ") failed"<<endl;
+      return false;
+    } 
+  }
+  if(matClose(mat_file) != 0)
+  {
+    fprintf(stderr,"Error closing file %s\n",path.c_str());
+    return false;
+  }
+  return true;
+}
+
+// Treat everything as a double
+template <typename DerivedM>
+IGL_INLINE igl::MatlabWorkspace::MatlabWorkspace& igl::MatlabWorkspace::save(
+  const Eigen::PlainObjectBase<DerivedM>& M,
+  const std::string & name)
+{
+  using namespace std;
+  const int m = M.rows();
+  const int n = M.cols();
+
+  mxArray * mx_data = mxCreateDoubleMatrix(m,n,mxREAL);
+  data.push_back(mx_data);
+  names.push_back(name);
+  // Copy data immediately
+  copy(M.data(),M.data()+M.size(),mxGetPr(mx_data));
+  return *this;
+}
+
+template <typename ScalarM>
+IGL_INLINE igl::MatlabWorkspace::MatlabWorkspace& igl::MatlabWorkspace::save(
+  const std::vector<std::vector<ScalarM> > & vM,
+  const std::string & name)
+{
+  Eigen::MatrixXd M;
+  list_to_matrix(vM,M);
+  return this->save(M,name);
+}
+
+template <typename ScalarV>
+IGL_INLINE igl::MatlabWorkspace::MatlabWorkspace& igl::MatlabWorkspace::save(
+  const std::vector<ScalarV> & vV,
+  const std::string & name)
+{
+  Eigen::MatrixXd V;
+  list_to_matrix(vV,V);
+  return this->save(V,name);
+}
+
+template <typename DerivedM>
+IGL_INLINE igl::MatlabWorkspace::MatlabWorkspace& 
+  igl::MatlabWorkspace::save_index(
+    const Eigen::PlainObjectBase<DerivedM>& M,
+    const std::string & name)
+{
+  DerivedM Mp1 = M;
+  Mp1.array() += 1;
+  return this->save(Mp1,name);
+}
+
+template <typename ScalarM>
+IGL_INLINE igl::MatlabWorkspace::MatlabWorkspace& igl::MatlabWorkspace::save_index(
+  const std::vector<std::vector<ScalarM> > & vM,
+  const std::string & name)
+{
+  Eigen::MatrixXd M;
+  list_to_matrix(vM,M);
+  return this->save_index(M,name);
+}
+
+template <typename ScalarV>
+IGL_INLINE igl::MatlabWorkspace::MatlabWorkspace& igl::MatlabWorkspace::save_index(
+  const std::vector<ScalarV> & vV,
+  const std::string & name)
+{
+  Eigen::MatrixXd V;
+  list_to_matrix(vV,V);
+  return this->save_index(V,name);
+}
+
+
+//template <typename Data>
+//bool igl::MatlabWorkspace::save(const Data & M, const std::string & name)
+//{
+//  using namespace std;
+//  // If I don't know the type then I can't save it
+//  cerr<<"^MatlabWorkspace::save Error: Unknown data type. "<<
+//    name<<" not saved."<<endl;
+//  return false;
+//}
+
+#endif

+ 90 - 0
include/igl/MatlabWorkspace.h

@@ -0,0 +1,90 @@
+#ifndef IGL_WRITE_MATLAB_WORKSPACE
+#define IGL_WRITE_MATLAB_WORKSPACE
+#include "igl_inline.h"
+
+#include <string>
+#include <vector>
+#include <Eigen/Dense>
+
+#include "mat.h"
+
+namespace igl
+{
+  // Class which contains data of a matlab workspace which can be written to a
+  // .mat file and loaded from matlab
+  // 
+  // This depends on matlab at compile time (though it shouldn't necessarily
+  // have to) but it does not depend on running the matlab engine at run-time.
+  //
+  // Known bugs: Treats all matrices as doubles (this may actually be desired
+  // for some "index" matrices since matlab's sparse command takes doubles
+  // rather than int class matrices). It is of course not desired when dealing
+  // with logicals or uint's for images.
+  class MatlabWorkspace
+  {
+    private:
+      // List of names
+      std::vector<std::string> names;
+      // List of data pointers
+      std::vector<mxArray*> data;
+    public:
+      MatlabWorkspace();
+      ~MatlabWorkspace();
+      // Clear names and data of variables in workspace
+      IGL_INLINE void clear();
+      // Save current list of variables
+      //
+      // Inputs:
+      //   path  path to .mat file
+      // Returns true on success, false on failure
+      IGL_INLINE bool write(const std::string & path) const;
+      // Assign data to a variable name in the workspace
+      //
+      // Template: 
+      //   DerivedM  eigen matrix (e.g. MatrixXd)
+      // Inputs:
+      //   M  data (usually a matrix)
+      //   name  variable name to save into work space
+      // Returns true on success, false on failure
+      //
+      // Known Bugs: Assumes Eigen is using column major ordering
+      template <typename DerivedM>
+      IGL_INLINE MatlabWorkspace& save(
+        const Eigen::PlainObjectBase<DerivedM>& M,
+        const std::string & name);
+      // Templates:
+      //   ScalarM  scalar type, e.g. double
+      template <typename ScalarM>
+      IGL_INLINE MatlabWorkspace& save(
+        const std::vector<std::vector<ScalarM> > & vM,
+        const std::string & name);
+      // Templates:
+      //   ScalarV  scalar type, e.g. double
+      template <typename ScalarV>
+      IGL_INLINE MatlabWorkspace& save(
+        const std::vector<ScalarV> & vV,
+        const std::string & name);
+      // Same as save() but adds 1 to each element, useful for saving "index"
+      // matrices like lists of faces or elements
+      template <typename DerivedM>
+      IGL_INLINE MatlabWorkspace& save_index(
+        const Eigen::PlainObjectBase<DerivedM>& M,
+        const std::string & name);
+      template <typename ScalarM>
+      IGL_INLINE MatlabWorkspace& save_index(
+        const std::vector<std::vector<ScalarM> > & vM,
+        const std::string & name);
+      template <typename ScalarV>
+      IGL_INLINE MatlabWorkspace& save_index(
+        const std::vector<ScalarV> & vV,
+        const std::string & name);
+  };
+}
+
+// Be sure that this is not compiled into libigl.a
+#ifdef IGL_HEADER_ONLY
+#  include "MatlabWorkspace.cpp"
+#endif
+
+#endif
+

+ 2 - 2
include/igl/boundary_faces.h

@@ -13,8 +13,8 @@ namespace igl
   // BOUNDARY_FACES Determine boundary faces of tetrahedra stored in T
   //
   // Templates:
-  //   IntegerT  integer-value: i.e. int
-  //   IntegerF  integer-value: i.e. int
+  //   IntegerT  integer-value: e.g. int
+  //   IntegerF  integer-value: e.g. int
   // Input:
   //  T  tetrahedron index list, m by 4, where m is the number of tetrahedra
   // Output:

+ 3 - 0
include/igl/list_to_matrix.cpp

@@ -83,4 +83,7 @@ template bool igl::list_to_matrix<double, Eigen::Matrix<double, -1, -1, 0, -1, -
 template bool igl::list_to_matrix<double, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>&);
 template bool igl::list_to_matrix<bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > >(std::vector<bool, std::allocator<bool> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template bool igl::list_to_matrix<bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > >(std::vector<std::vector<bool, std::allocator<bool> >, std::allocator<std::vector<bool, std::allocator<bool> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template bool igl::list_to_matrix<int, Eigen::PlainObjectBase<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<int, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
+template bool igl::list_to_matrix<int, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(std::vector<int, std::allocator<int> > const&, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
 #endif

+ 0 - 1
include/igl/matlab_workspace.cpp

@@ -1 +0,0 @@
-#include "matlab_workspace.h"

+ 0 - 22
include/igl/matlab_workspace.h

@@ -1,22 +0,0 @@
-#ifndef IGL_WRITE_MATLAB_WORKSPACE
-#define IGL_WRITE_MATLAB_WORKSPACE
-#include "igl_inline.h"
-
-namespace igl
-{
-  // Class which contains data of a matlab workspace which can be written to a
-  // .mat file and loaded from matlab
-  // 
-  // This depends on matlab at compile time (though it shouldn't necessarily
-  // have to) but it does not depend on running the matlab engine at run-time.
-  class matlab_workspace
-  {
-  };
-}
-
-#ifdef IGL_HEADER_ONLY
-#  include "matlab_workspace.cpp"
-#endif
-
-#endif
-

+ 1 - 1
include/igl/on_boundary.cpp

@@ -48,8 +48,8 @@ IGL_INLINE void igl::on_boundary(
   {
     for(int j = 0;j<4;j++)
     {
+      assert(FC[i*4+j] == 2 || FC[i*4+j] == 1);
       C[i][j] = FC[i*4+j]==1;
-      assert(C[i][j] == 2 || C[i][j] == 1);
       // if any are on boundary set to true
       I[i] = I[i] || C[i][j];
     }

+ 1 - 0
include/igl/tt.cpp

@@ -84,4 +84,5 @@ IGL_INLINE void igl::tt(const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>&
 // Explicit template specialization
 // generated by autoexplicit.sh
 template void igl::tt<double>(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>&);
+template void igl::tt<double, int>(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>&, Eigen::Matrix<int, -1, -1, 0, -1, -1>&);
 #endif

+ 1 - 0
include/igl/upsample.cpp

@@ -89,4 +89,5 @@ IGL_INLINE void igl::upsample( MatV & V,MatF & F)
 
 #ifndef IGL_HEADER_ONLY
 // Explicit template specialization
+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>&);
 #endif

+ 2 - 2
include/igl/writeOFF.cpp

@@ -18,10 +18,10 @@ IGL_INLINE bool igl::writeOFF(
     
     fprintf (fp, "OFF\n%d %d 0\n",  (int) V.rows(), (int) F.rows());
     
-    for (unsigned i = 0; i < V.rows(); i++)
+    for (int i = 0; i < V.rows(); i++)
         fprintf (fp, "%f %f %f\n", V(i,0), V(i,1), V(i,2));
     
-    for (unsigned i = 0; i < F.rows(); i++)
+    for (int i = 0; i < F.rows(); i++)
         fprintf (fp, "3 %d %d %d\n", F(i,0), F(i,1), F(i,2));
     
     fclose (fp);

+ 14 - 49
matlab-to-eigen.html

@@ -1,53 +1,6 @@
 <html> <head>
     <title>MATLAB to Eigen</title>
-    <style type="text/css">
-table
-{
-  border-spacing: 0px;
-}
-tr.header th
-{
-  border-bottom: 1px solid; 
-  background-color: #ffb;
-  padding-left: 10px;
-  padding-right: 20px;
-}
-tr.d0 td 
-{
-  background-color: #EEE; 
-  color: black;
-  padding-left: 10px;
-  padding-right: 20px;
-  min-width: 200px;
-}
-tr.d1 td
-{
-  background-color: #bcf; 
-  color: black;
-  padding-left: 10px;
-  padding-right: 20px;
-  min-width: 200px;
-}
-
-tr.gotcha1 td
-{
-  background-color: #fcb;
-  color: black;
-  padding-left: 10px;
-  padding-right: 20px;
-  min-width: 200px;
-}
-
-tr.gotcha2 td
-{
-  background-color: #fed;
-  color: black;
-  padding-left: 10px;
-  padding-right: 20px;
-  min-width: 200px;
-}
-
-    </style>
+    <link href="./style.css" rel="stylesheet" type="text/css">
   </head>
   <body>
     <table>
@@ -245,7 +198,17 @@ tr.gotcha2 td
         <td><pre><code>B = fliplr(A)<br>B = flipud(A)</code></pre></td>
         <td><pre><code>B = A.rowwize().reverse().eval()<br>B =
 	A.colwise().reverse().eval()</code></pre></td>
-        <td>The <code>.eval()</code> is not neccessary is A != B</td>
+        <td>The <code>.eval()</code> is not necessary if A != B</td>
+      </tr>
+
+      <tr class=d0>
+        <td><pre><code>B = IM(A)</code></pre></td>
+        <td><pre><code>B = A.unaryExpr(bind1st(mem_fun( 
+  static_cast&lt;VectorXi::Scalar&amp;(VectorXi::*)(VectorXi::Index)&gt;
+  (&amp;VectorXi::operator())), &amp;IM)).eval();
+  </code></pre></td>
+        <td>Where IM is an "index map" column vector and A is an arbitrary
+        matrix. The <code>.eval()</code> is not necessary if A != B</td>
       </tr>
 
       <!-- Insert rows for each command pair -->
@@ -263,5 +226,7 @@ tr.gotcha2 td
     </table>
     <a href="http://eigen.tuxfamily.org/dox/AsciiQuickReference.txt">Eigen's
     "ASCII Quick Reference" with MATLAB translations</a>
+    <br>
+    <a href="./tutorial.html">IGL Lib Tutorial</a>
   </body>
 </html>

+ 4 - 68
tutorial.html

@@ -1,71 +1,7 @@
 <html>
   <head>
     <title>igl_lib tutorial</title>
-    <style>
-.note:before
-{
-  font-style: normal;
-  content: "Note: ";
-}
-.note
-{
-  background-color: #ddd;
-  border: 1px solid #bbb;
-  margin-top: 2px;
-  margin-bottom: 2px;
-  font-style: italic;
-  padding-left: 4px;
-  padding-right: 4px;
-  padding-top: 2px;
-  padding-bottom: 2px;
-}
-span.highlight
-{
-  background-color: #4F5;
-}
-a 
-{
-  text-decoration:none;
-  border:none;
-  outline:none;
-  color:#0645AD;
-}
-a:hover 
-{
-  color:#0645AD;
-  text-decoration: underline;
-}
-a:visited
-{
-  color:#0b0080;
-}
-span.todo:before
-{
-  font-style: normal;
-  content: "TODO: ";
-}
-span.todo
-{
-  color: #F54;
-  font-style: italic;
-}
-pre
-{
-  background-color: #c3e0f0;
-  overflow: auto;
-  padding-left: 8px;
-  padding-right: 8px;
-  padding-top: 4px;
-  padding-bottom: 4px;
-  border: 1px solid #999;
-}
-img.center
-{
-  display: block;
-  margin-left: auto;
-  margin-right: auto;
-}
-    </style>
+    <link href="./style.css" rel="stylesheet" type="text/css">
   </head>
   <body>
     <img src=http://igl.ethz.ch/includes/images/logo-igl.gif alt="igl logo"
@@ -114,16 +50,16 @@ img.center
       </p>
       <pre><code>
 ...
-#include &lt;some_other_igl_function.h&gt;
+#include &lt;igl/some_other_igl_function.h&gt;
 #ifndef IGL_HEADER_ONLY
 #  define IGL_HEADER_ONLY
 #  define IGL_HEADER_ONLY_WAS_NOT_DEFINED
 #endif
-#include &lt;igl_function_to_inline.h&gt;
+#include &lt;igl/igl_function_to_inline.h&gt;
 #ifdef IGL_HEADER_ONLY_WAS_NOT_DEFINED
 #  undef IGL_HEADER_ONLY
 #endif
-#include &lt;yet_another_igl_function.h&gt;
+#include &lt;igl/yet_another_igl_function.h&gt;
 ...
       </code></pre>
       <span class=todo>example <code>examples/XXX</code> also highlights this feature</span>