瀏覽代碼

Merge branch 'master' of github.com:libigl/libigl

Former-commit-id: d19496c92b5fa2cea0e61d01d8a972f5e9e33e8e
Alec Jacobson 9 年之前
父節點
當前提交
3121c477c1
共有 76 個文件被更改,包括 4750 次插入56 次删除
  1. 9 0
      .gitignore
  2. 3 2
      .gitmodules
  3. 4 4
      README.md
  4. 2 2
      include/igl/parula.cpp
  5. 65 20
      include/igl/serialize.h
  6. 9 10
      include/igl/unique.cpp
  7. 5 9
      include/igl/unique.h
  8. 21 5
      include/igl/viewer/Viewer.cpp
  9. 7 0
      include/igl/viewer/Viewer.h
  10. 5 2
      include/igl/viewer/ViewerCore.cpp
  11. 4 0
      include/igl/viewer/ViewerData.cpp
  12. 2 2
      index.html
  13. 48 0
      python/001_BasicTypes.py
  14. 14 0
      python/101_FileIO.py
  15. 11 0
      python/102_DrawMesh.py
  16. 24 0
      python/102_DrawMeshTCP.py
  17. 40 0
      python/103_Events.py
  18. 24 0
      python/104_Colors.py
  19. 67 0
      python/105_Overlays.py
  20. 48 0
      python/201_Normals.py
  21. 20 0
      python/202_GaussianCurvature.py
  22. 61 0
      python/203_CurvatureDirections.py
  23. 50 0
      python/204_Gradient.py
  24. 108 0
      python/205_Laplacian.py
  25. 34 0
      python/301_Slice.py
  26. 34 0
      python/302_Sort.py
  27. 73 0
      python/303_LaplaceEquation.py
  28. 96 0
      python/304_LinearEqualityConstraints.py
  29. 86 0
      python/305_QuadraticProgramming.py
  30. 56 0
      python/306_EigenDecomposition.py
  31. 154 0
      python/CMakeLists.txt
  32. 159 0
      python/README.md
  33. 51 0
      python/iglhelpers.py
  34. 59 0
      python/matlab/CurvatureDirections.m
  35. 12 0
      python/matlab/t102DrawMesh.m
  36. 409 0
      python/py_doc.cpp
  37. 409 0
      python/py_doc.h
  38. 69 0
      python/py_igl.cpp
  39. 6 0
      python/py_igl/py_SolverStatus.cpp
  40. 48 0
      python/py_igl/py_active_set.cpp
  41. 9 0
      python/py_igl/py_avg_edge_length.cpp
  42. 10 0
      python/py_igl/py_barycenter.cpp
  43. 30 0
      python/py_igl/py_boundary_facets.cpp
  44. 74 0
      python/py_igl/py_colon.cpp
  45. 10 0
      python/py_igl/py_cotmatrix.cpp
  46. 54 0
      python/py_igl/py_doublearea.cpp
  47. 22 0
      python/py_igl/py_eigs.cpp
  48. 9 0
      python/py_igl/py_floor.cpp
  49. 10 0
      python/py_igl/py_gaussian_curvature.cpp
  50. 10 0
      python/py_igl/py_grad.cpp
  51. 9 0
      python/py_igl/py_invert_diag.cpp
  52. 24 0
      python/py_igl/py_jet.cpp
  53. 19 0
      python/py_igl/py_massmatrix.cpp
  54. 73 0
      python/py_igl/py_min_quad_with_fixed.cpp
  55. 24 0
      python/py_igl/py_parula.cpp
  56. 38 0
      python/py_igl/py_per_corner_normals.cpp
  57. 34 0
      python/py_igl/py_per_face_normals.cpp
  58. 55 0
      python/py_igl/py_per_vertex_normals.cpp
  59. 15 0
      python/py_igl/py_principal_curvature.cpp
  60. 10 0
      python/py_igl/py_readDMAT.cpp
  61. 22 0
      python/py_igl/py_readOFF.cpp
  62. 36 0
      python/py_igl/py_read_triangle_mesh.cpp
  63. 11 0
      python/py_igl/py_setdiff.cpp
  64. 155 0
      python/py_igl/py_slice.cpp
  65. 107 0
      python/py_igl/py_slice_into.cpp
  66. 23 0
      python/py_igl/py_sortrows.cpp
  67. 116 0
      python/py_igl/py_unique.cpp
  68. 25 0
      python/py_igl/py_writeOBJ.cpp
  69. 371 0
      python/py_igl_viewer.cpp
  70. 623 0
      python/py_vector.cpp
  71. 19 0
      python/python.cpp
  72. 86 0
      python/python.h
  73. 68 0
      python/scripts/mk_py_doc.py
  74. 45 0
      python/tcpviewer.py
  75. 69 0
      python/tcpviewer_single.py
  76. 29 0
      scripts/update_gh-pages_nogit.sh

+ 9 - 0
.gitignore

@@ -78,5 +78,14 @@ tutorial/XXX_test/main.cpp
 python/py_igl/todo
 python/build
 python/.idea
+untitled
+Untitled.ipynb
+python/.ipynb_checkpoints
+python/py_igl/todo
+python/__pycache__
+iglhelpers.pyc
+python/build2
 tests/build
 tests/bin
+python/build3
+*.pyc

+ 3 - 2
.gitmodules

@@ -3,11 +3,12 @@
 url=https://github.com/libigl/nanogui.git
         fetchRecursiveSubmodules = true
         ignore = dirty
-
 [submodule "external/embree"]
 	path = external/embree
 	url = https://github.com/embree/embree.git
-
+[submodule "external/pybind11"]
+	path = external/pybind11
+	url = https://github.com/wjakob/pybind11.git
 [submodule "tests/googletest"]
 	path = tests/googletest
 	url = https://github.com/google/googletest.git

+ 4 - 4
README.md

@@ -23,7 +23,7 @@ just include igl headers (e.g. `#include <igl/cotmatrix.h>`) and run.  Each
 header file contains a single function (e.g. `igl/cotmatrix.h` contains
 `igl::cotmatrix()`). Most are tailored to operate on a generic triangle mesh
 stored in an n-by-3 matrix of vertex positions V and an m-by-3 matrix of
-triangle indices F. 
+triangle indices F.
 
 _Optionally_ the library may also be [pre-compiled](optional/) into a statically
 linked library, for faster compile times with your projects. This only effects
@@ -37,7 +37,7 @@ conversion table](matlab-to-eigen.html).
 ## Tutorial
 
 As of version 1.0, libigl includes an introductory
-[tutorial](tutorial/tutorial.html) that covers many functionalities.
+[tutorial](http://libigl.github.io/libigl/tutorial/tutorial.html) that covers many functionalities.
 
 ## Installation
 
@@ -135,7 +135,7 @@ We hope to fix this, or at least identify which functions are safe (many of
 them probably work just fine). This requires setting up unit testing, which is
 a major _todo_ for our development.
 
-## Git Submodules 
+## Git Submodules
 Libigl uses git submodules for its _optional_ dependencies,
 in particular, those needed by the OpenGL viewer to run the examples in the
 [tutorial](tutorial/tutorial.html). Git submodules allow use to treat clones of
@@ -192,7 +192,7 @@ few labs/companies/institutions using libigl:
  - ETH Zurich, [Interactive Geometry Lab](http://igl.ethz.ch/) and [Advanced Technologies Lab](http://ait.inf.ethz.ch/), Swizterland
  - George Mason University, [CraGL](http://cs.gmu.edu/~ygingold/), USA
  - [Hong Kong University of Science and Technology](http://www.ust.hk/), USA
- - [National Institute of Informatics](http://www.nii.ac.jp/en/), Japan 
+ - [National Institute of Informatics](http://www.nii.ac.jp/en/), Japan
  - New York University, [Media Research Lab](http://mrl.nyu.edu/), USA
  - NYUPoly, [Game Innovation Lab](http://game.engineering.nyu.edu/), USA
  - [Telecom ParisTech](http://www.telecom-paristech.fr/en/formation-et-innovation-dans-le-numerique.html), Paris, France

+ 2 - 2
include/igl/parula.cpp

@@ -21,8 +21,8 @@ IGL_INLINE void igl::parula(const T f, T & r, T & g, T & b)
   const float eff_f = (f>=1.?1.:(f<=0.?0.:f));
   // continuous index into array
   const float ff = eff_f*(PARULA_COLOR_MAP.rows()-1);
-  size_t s = floor(ff);
-  size_t d = ceil(ff);
+  size_t s = std::floor(ff);
+  size_t d = std::ceil(ff);
   const float t = (s==d ? 0. : (ff-s)/float(d-s));
 
   assert(t>=0 && t<=1);

+ 65 - 20
include/igl/serialize.h

@@ -21,7 +21,7 @@
 // -----------------------------------------------------------------------------
 
 // Known issues: This is not written in libigl-style so it isn't (easily)
-// "dualized" into the static library. 
+// "dualized" into the static library.
 //
 
 #include <type_traits>
@@ -45,16 +45,28 @@
 #define SERIALIZE_TYPE(Type,Params) \
 namespace igl { namespace serialization { \
   void _serialization(bool s,Type& obj,std::vector<char>& buffer) {Params} \
-  void serialize(const Type& obj,std::vector<char>& buffer) { \
+  template<> inline void serialize(const Type& obj,std::vector<char>& buffer) { \
     _serialization(true,const_cast<Type&>(obj),buffer); \
     } \
-  void deserialize(Type& obj,const std::vector<char>& buffer) { \
+  template<> inline void deserialize(Type& obj,const std::vector<char>& buffer) { \
     _serialization(false,obj,const_cast<std::vector<char>&>(buffer)); \
     } \
 }}
 
-#define SERIALIZE_MEMBER(Object) ::igl::serializer(s,obj.##Object,std::string(#Object),buffer);
-#define SERIALIZE_MEMBER_NAME(Object,Name) ::igl::serializer(s,obj.##Object,std::string(Name),buffer);
+#define SERIALIZE_TYPE_SOURCE(Type,Params) \
+namespace igl { namespace serialization { \
+  void _serialization(bool s,Type& obj,std::vector<char>& buffer) {Params} \
+  void _serialize(const Type& obj,std::vector<char>& buffer) { \
+    _serialization(true,const_cast<Type&>(obj),buffer); \
+    } \
+  void _deserialize(Type& obj,const std::vector<char>& buffer) { \
+    _serialization(false,obj,const_cast<std::vector<char>&>(buffer)); \
+    } \
+}}
+
+#define SERIALIZE_MEMBER(Object) igl::serializer(s,obj.Object,std::string(#Object),buffer);
+#define SERIALIZE_MEMBER_NAME(Object,Name) igl::serializer(s,obj.Object,std::string(Name),buffer);
+
 
 namespace igl
 {
@@ -101,21 +113,23 @@ namespace igl
   // Wrapper to expose both, the de- and serialization as one function
   //
   template <typename T>
-  inline bool serializer(bool serialize,T& obj,std::string& filename);
+  inline bool serializer(bool serialize,T& obj,const std::string& filename);
   template <typename T>
-  inline bool serializer(bool serialize,T& obj,std::string& objectName,const std::string& filename,bool overwrite = false);
+  inline bool serializer(bool serialize,T& obj,const std::string& objectName,const std::string& filename,bool overwrite = false);
   template <typename T>
-  inline bool serializer(bool serialize,T& obj,std::string& objectName,std::vector<char>& buffer);
+  inline bool serializer(bool serialize,T& obj,const std::string& objectName,std::vector<char>& buffer);
 
   // User defined types have to either overload the function igl::serialization::serialize()
   // and igl::serialization::deserialize() for their type (non-intrusive serialization):
   //
-  // namespace igl { namespace serialization 
+  // namespace igl { namespace serialization
   // {
+  //   template<>
   //   inline void serialize(const UserType& obj,std::vector<char>& buffer) {
   //     ::igl::serialize(obj.var,"var",buffer);
   //   }
-  //     
+  //
+  //   template<>
   //   inline void deserialize(UserType& obj,const std::vector<char>& buffer) {
   //     ::igl::deserialize(obj.var,"var",buffer);
   //   }
@@ -281,7 +295,7 @@ namespace igl
     template <typename T>
     inline typename std::enable_if<std::is_base_of<SerializableBase,T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
     template <typename T>
-    inline typename std::enable_if<std::is_base_of<SerializableBase,T>::value>::type deserialize(T& obj,std::vector<char>::const_iterator& iter);    
+    inline typename std::enable_if<std::is_base_of<SerializableBase,T>::value>::type deserialize(T& obj,std::vector<char>::const_iterator& iter);
 
     // stl containers
     // std::pair
@@ -333,6 +347,13 @@ namespace igl
     template<typename T,int P,typename I>
     inline void deserialize(Eigen::SparseMatrix<T,P,I>& obj,std::vector<char>::const_iterator& iter);
 
+    template<typename T,int P>
+    inline size_t getByteSize(const Eigen::Quaternion<T,P>& obj);
+    template<typename T,int P>
+    inline void serialize(const Eigen::Quaternion<T,P>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
+    template<typename T,int P>
+    inline void deserialize(Eigen::Quaternion<T,P>& obj,std::vector<char>::const_iterator& iter);
+
     // raw pointers
     template <typename T>
     inline typename std::enable_if<std::is_pointer<T>::value,size_t>::type getByteSize(const T& obj);
@@ -521,19 +542,19 @@ namespace igl
 
   // Wrapper function which combines both, de- and serialization
   template <typename T>
-  inline bool serializer(bool s,T& obj,std::string& filename)
+  inline bool serializer(bool s,T& obj,const std::string& filename)
   {
     return s ? serialize(obj,filename) : deserialize(obj,filename);
   }
 
   template <typename T>
-  inline bool serializer(bool s,T& obj,std::string& objectName,const std::string& filename,bool overwrite)
+  inline bool serializer(bool s,T& obj,const std::string& objectName,const std::string& filename,bool overwrite)
   {
     return s ? serialize(obj,objectName,filename,overwrite) : deserialize(obj,objectName,filename);
   }
 
   template <typename T>
-  inline bool serializer(bool s,T& obj,std::string& objectName,std::vector<char>& buffer)
+  inline bool serializer(bool s,T& obj,const std::string& objectName,std::vector<char>& buffer)
   {
     return s ? serialize(obj,objectName,buffer) : deserialize(obj,objectName,buffer);
   }
@@ -627,7 +648,7 @@ namespace igl
   }
 
   template <typename T>
-  inline void Serializable::Add(T& obj,std::string name,bool binary)
+  inline void Serializable::Add(T& obj,const std::string name,bool binary)
   {
     auto object = new SerializationObject<T>();
     object->Binary = binary;
@@ -650,7 +671,7 @@ namespace igl
     {
       // data
       std::vector<char> tmp;
-      serialize(obj,tmp);
+      serialize<>(obj,tmp);
 
       // size
       size_t size = buffer.size();
@@ -666,13 +687,13 @@ namespace igl
     inline typename std::enable_if<!is_serializable<T>::value>::type deserialize(T& obj,std::vector<char>::const_iterator& iter)
     {
       std::vector<char>::size_type size;
-      serialization::deserialize(size,iter);
+      serialization::deserialize<>(size,iter);
 
       std::vector<char> tmp;
       tmp.resize(size);
       std::copy(iter,iter+size,tmp.begin());
 
-      deserialize(obj,tmp);
+      deserialize<>(obj,tmp);
       iter += size;
     }
 
@@ -1010,6 +1031,30 @@ namespace igl
       obj.setFromTriplets(triplets.begin(),triplets.end());
     }
 
+    template<typename T,int P>
+    inline size_t getByteSize(const Eigen::Quaternion<T,P>& obj)
+    {
+      return sizeof(T)*4;
+    }
+
+    template<typename T,int P>
+    inline void serialize(const Eigen::Quaternion<T,P>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter)
+    {
+      serialization::serialize(obj.w(),buffer,iter);
+      serialization::serialize(obj.x(),buffer,iter);
+      serialization::serialize(obj.y(),buffer,iter);
+      serialization::serialize(obj.z(),buffer,iter);
+    }
+
+    template<typename T,int P>
+    inline void deserialize(Eigen::Quaternion<T,P>& obj,std::vector<char>::const_iterator& iter)
+    {
+      serialization::deserialize(obj.w(),iter);
+      serialization::deserialize(obj.x(),iter);
+      serialization::deserialize(obj.y(),iter);
+      serialization::deserialize(obj.z(),iter);
+    }
+
     // pointers
 
     template <typename T>
@@ -1115,13 +1160,13 @@ namespace igl
     template <typename T>
     inline void serialize(const T& obj,std::vector<char>& buffer)
     {
-      std::cerr << typeid(obj).name() << " is not serializable: derive from igl::Serializable or overload the function igl::serialization::serialize(const T& obj,std::vector<char>& buffer)" << std::endl;
+      std::cerr << typeid(obj).name() << " is not serializable: derive from igl::Serializable or spezialize the template function igl::serialization::serialize(const T& obj,std::vector<char>& buffer)" << std::endl;
     }
 
     template <typename T>
     inline void deserialize(T& obj,const std::vector<char>& buffer)
     {
-      std::cerr << typeid(obj).name() << " is not deserializable: derive from igl::Serializable or overload the function igl::serialization::deserialize(T& obj, const std::vector<char>& buffer)" << std::endl;
+      std::cerr << typeid(obj).name() << " is not deserializable: derive from igl::Serializable or spezialize the template function igl::serialization::deserialize(T& obj, const std::vector<char>& buffer)" << std::endl;
     }
 
     // helper functions

+ 9 - 10
include/igl/unique.cpp

@@ -1,9 +1,9 @@
 // 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 
+//
+// 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 "unique.h"
 #include "sort.h"
@@ -97,9 +97,8 @@ IGL_INLINE void igl::unique(
 
 template <
   typename DerivedA,
-  typename DerivedC,
-  typename DerivedIA,
-  typename DerivedIC>
+  typename DerivedC
+  >
 IGL_INLINE void igl::unique(
     const Eigen::PlainObjectBase<DerivedA> & A,
     Eigen::PlainObjectBase<DerivedC> & C)
@@ -123,7 +122,7 @@ IGL_INLINE void igl::unique(
 //   Eigen::PlainObjectBase<DerivedIC>& IC)
 // {
 //   using namespace std;
-// 
+//
 //   typedef Eigen::Matrix<typename DerivedA::Scalar, Eigen::Dynamic, 1> RowVector;
 //   vector<SortableRow<RowVector> > rows;
 //   rows.resize(A.rows());
@@ -134,12 +133,12 @@ IGL_INLINE void igl::unique(
 //     rows[i] = SortableRow<RowVector>(ri);
 //   }
 //   vector<SortableRow<RowVector> > vC;
-// 
+//
 //   // unique on rows
 //   vector<size_t> vIA;
 //   vector<size_t> vIC;
 //   unique(rows,vC,vIA,vIC);
-// 
+//
 //   // Convert to eigen
 //   C.resize(vC.size(),A.cols());
 //   IA.resize(vIA.size(),1);

+ 5 - 9
include/igl/unique.h

@@ -1,9 +1,9 @@
 // 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 
+//
+// 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_UNIQUE_H
 #define IGL_UNIQUE_H
@@ -45,9 +45,7 @@ namespace igl
       Eigen::PlainObjectBase<DerivedIC> & IC);
   template <
     typename DerivedA,
-    typename DerivedC,
-    typename DerivedIA,
-    typename DerivedIC>
+    typename DerivedC>
   IGL_INLINE void unique(
       const Eigen::PlainObjectBase<DerivedA> & A,
       Eigen::PlainObjectBase<DerivedC> & C);
@@ -76,5 +74,3 @@ namespace igl
 #endif
 
 #endif
-
-

+ 21 - 5
include/igl/viewer/Viewer.cpp

@@ -279,7 +279,6 @@ namespace viewer
     callback_mouse_scroll_data  = nullptr;
     callback_key_down_data      = nullptr;
     callback_key_up_data        = nullptr;
-
   }
 
   IGL_INLINE void Viewer::init_plugins()
@@ -726,10 +725,9 @@ namespace viewer
     this->save_mesh_to_file(fname.c_str());
   }
 
-  IGL_INLINE int Viewer::launch(bool resizable,bool fullscreen)
-  {
-    GLFWwindow* window;
 
+  IGL_INLINE int  Viewer::launch_init(bool resizable,bool fullscreen)
+  {
     glfwSetErrorCallback(glfw_error_callback);
     if (!glfwInit())
       return EXIT_FAILURE;
@@ -818,6 +816,11 @@ namespace viewer
 
     // Initialize IGL viewer
     init();
+  }
+
+  IGL_INLINE bool Viewer::launch_rendering(bool loop)
+  {
+    // glfwMakeContextCurrent(window);
 
     // Rendering loop
     while (!glfwWindowShouldClose(window))
@@ -841,8 +844,14 @@ namespace viewer
       {
         glfwWaitEvents();
       }
+
+      if (!loop)
+        return !glfwWindowShouldClose(window);
     }
+  }
 
+  IGL_INLINE void Viewer::launch_shut()
+  {
     opengl.free();
     core.shut();
 
@@ -850,7 +859,14 @@ namespace viewer
 
     glfwDestroyWindow(window);
     glfwTerminate();
-    return EXIT_SUCCESS;
+    return;
+  }
+
+  IGL_INLINE int Viewer::launch(bool resizable,bool fullscreen)
+  {
+    launch_init(resizable,fullscreen);
+    launch_rendering(true);
+    launch_shut();
   }
 } // end namespace
 }

+ 7 - 0
include/igl/viewer/Viewer.h

@@ -34,6 +34,8 @@
 
 namespace nanogui { class FormScreen; }
 
+class GLFWwindow;
+
 namespace igl
 {
 namespace viewer
@@ -42,8 +44,13 @@ namespace viewer
   class Viewer
   {
   public:
+    GLFWwindow* window;
 
     IGL_INLINE int launch(bool resizable = true,bool fullscreen = false);
+    IGL_INLINE int launch_init(bool resizable = true,bool fullscreen = false);
+    IGL_INLINE bool launch_rendering(bool loop = true);
+    IGL_INLINE void launch_shut();
+
     IGL_INLINE void init();
 
     // Stores all the viewing options

+ 5 - 2
include/igl/viewer/ViewerCore.cpp

@@ -32,6 +32,7 @@ namespace igl {
       SERIALIZE_MEMBER(lighting_factor);
 
       SERIALIZE_MEMBER(trackball_angle);
+      SERIALIZE_MEMBER(rotation_type);
 
       SERIALIZE_MEMBER(model_zoom);
       SERIALIZE_MEMBER(model_translation);
@@ -39,8 +40,6 @@ namespace igl {
       SERIALIZE_MEMBER(model_zoom_uv);
       SERIALIZE_MEMBER(model_translation_uv);
 
-      SERIALIZE_MEMBER(object_scale);
-
       SERIALIZE_MEMBER(camera_zoom);
       SERIALIZE_MEMBER(orthographic);
       SERIALIZE_MEMBER(camera_view_angle);
@@ -65,17 +64,21 @@ namespace igl {
       SERIALIZE_MEMBER(is_animating);
       SERIALIZE_MEMBER(animation_max_fps);
 
+      SERIALIZE_MEMBER(object_scale);
+
       SERIALIZE_MEMBER(viewport);
       SERIALIZE_MEMBER(view);
       SERIALIZE_MEMBER(model);
       SERIALIZE_MEMBER(proj);
     }
 
+    template<>
     IGL_INLINE void serialize(const igl::viewer::ViewerCore& obj,std::vector<char>& buffer)
     {
       serialization(true,const_cast<igl::viewer::ViewerCore&>(obj),buffer);
     }
 
+    template<>
     IGL_INLINE void deserialize(igl::viewer::ViewerCore& obj,const std::vector<char>& buffer)
     {
       serialization(false,obj,const_cast<std::vector<char>&>(buffer));

+ 4 - 0
include/igl/viewer/ViewerData.cpp

@@ -46,14 +46,18 @@ namespace igl {
       SERIALIZE_MEMBER(labels_positions);
       SERIALIZE_MEMBER(labels_strings);
 
+      SERIALIZE_MEMBER(dirty);
+
       SERIALIZE_MEMBER(face_based);
     }
 
+    template<>
     IGL_INLINE void serialize(const igl::viewer::ViewerData& obj,std::vector<char>& buffer)
     {
       serialization(true,const_cast<igl::viewer::ViewerData&>(obj),buffer);
     }
 
+    template<>
     IGL_INLINE void deserialize(igl::viewer::ViewerData& obj,const std::vector<char>& buffer)
     {
       serialization(false,obj,const_cast<std::vector<char>&>(buffer));

+ 2 - 2
index.html

@@ -40,7 +40,7 @@ just include igl headers (e.g. <code>#include &lt;igl/cotmatrix.h&gt;</code>) an
 header file contains a single function (e.g. <code>igl/cotmatrix.h</code> contains
 <code>igl::cotmatrix()</code>). Most are tailored to operate on a generic triangle mesh
 stored in an n-by&#8211;3 matrix of vertex positions V and an m-by&#8211;3 matrix of
-triangle indices F. </p>
+triangle indices F.</p>
 
 <p><em>Optionally</em> the library may also be <a href="optional/">pre-compiled</a> into a statically
 linked library, for faster compile times with your projects. This only effects
@@ -54,7 +54,7 @@ conversion table</a>.</p>
 <h2 id="tutorial">Tutorial</h2>
 
 <p>As of version 1.0, libigl includes an introductory
-<a href="tutorial/tutorial.html">tutorial</a> that covers many functionalities.</p>
+<a href="http://libigl.github.io/libigl/tutorial/tutorial.html">tutorial</a> that covers many functionalities.</p>
 
 <h2 id="installation">Installation</h2>
 

+ 48 - 0
python/001_BasicTypes.py

@@ -0,0 +1,48 @@
+from iglhelpers import *
+
+############# Dense Matrix Types #############
+
+# Create a numpy dense array
+# 2 types are supported by the wrappers: float64 and int64
+dense_matrix = np.array( [ (1,2,3), (4,5,6) , (7,8,9) ], dtype='float64')
+
+# libigl wrappers uses Eigen as a matrix type, you can easily convert between numpy and Eigen using
+# the helper function p2e. This operation duplicates the data.
+dense_matrix_eigen = p2e(dense_matrix)
+
+# The Eigen wrappers allows you to do operations directly on this matrix,
+# without having to convert back to numpy
+dense_matrix_eigen_2 = dense_matrix_eigen * dense_matrix_eigen
+
+# You can also inspect the data without converting it ...
+print("Eigen Matrix: \n", dense_matrix_eigen_2, "\n", sep='')
+
+# and access single elements
+print("Eigen Matrix(0,0): ", dense_matrix_eigen_2[0,0], "\n")
+
+# To convert it back to a numpy array, use the helper function e2p
+dense_matrix_2 = e2p(dense_matrix_eigen_2)
+print("Numpy Array: \n", dense_matrix_2, "\n", sep='')
+
+############# Sparse Matrix Types #############
+
+# Sparse matrices are handled in a very similar way
+# 2 types are supported by the wrappers: float64 and int64
+sparse_matrix = sparse.rand(10, 10, 0.1)
+
+# To convert to the eigen forma use p2e
+sparse_matrix_eigen = p2e(sparse_matrix)
+
+# They can directly be used plotted or used in computations
+print("Sparse matrix Eigen: ", sparse_matrix_eigen, sep='')
+
+# And converted back with e2p
+sparse_matrix_2 = e2p(sparse_matrix_eigen)
+print("Sparse matrix Numpy: ", sparse_matrix_2.todense(), sep='')
+
+
+
+
+
+
+

+ 14 - 0
python/101_FileIO.py

@@ -0,0 +1,14 @@
+from __future__ import print_function
+import igl
+
+# Load a mesh in OFF format
+V = igl.eigen.MatrixXd()
+F = igl.eigen.MatrixXi()
+igl.readOFF("../tutorial/shared/cube.off", V, F)
+
+# Print the vertices and faces matrices
+print("Vertices: \n", V, sep='')
+print("Faces: \n", F, sep='')
+
+# Save the mesh in OBJ format
+igl.writeOBJ("cube.obj",V,F)

+ 11 - 0
python/102_DrawMesh.py

@@ -0,0 +1,11 @@
+import igl
+
+# Load a mesh in OFF format
+V = igl.eigen.MatrixXd()
+F = igl.eigen.MatrixXi()
+igl.readOFF("../tutorial/shared/beetle.off", V, F)
+
+# Plot the mesh
+viewer = igl.viewer.Viewer();
+viewer.data.set_mesh(V, F);
+viewer.launch();

+ 24 - 0
python/102_DrawMeshTCP.py

@@ -0,0 +1,24 @@
+import igl
+import tcpviewer
+import time
+
+# Load a mesh in OFF format
+V = igl.eigen.MatrixXd()
+F = igl.eigen.MatrixXi()
+time1 = time.time()
+# igl.read_triangle_mesh("../tutorial/shared/armadillo.obj", V, F)
+igl.readOFF("../tutorial/shared/beetle.off", V, F)
+time2 = time.time()
+
+
+print('Loading mesh (%d vertices) %0.3f ms' % (V.rows(),(time2-time1)*1000.0))
+
+
+# Plot the mesh
+viewer = tcpviewer.TCPViewer()
+viewer.data.set_mesh(V, F)
+viewer.core.align_camera_center(V,F)
+viewer.launch()
+time3 = time.time()
+
+print('Sending to TCP viewer took %0.3f ms' % ((time3-time2)*1000.0))

+ 40 - 0
python/103_Events.py

@@ -0,0 +1,40 @@
+import igl
+
+V1 = igl.eigen.MatrixXd()
+F1 = igl.eigen.MatrixXi()
+
+V2 = igl.eigen.MatrixXd()
+F2 = igl.eigen.MatrixXi()
+
+def key_pressed(viewer, key, modifier):
+    print("Key: ", chr(key))
+
+    if key == ord('1'):
+        # # Clear should be called before drawing the mesh
+        viewer.data.clear();
+        # # Draw_mesh creates or updates the vertices and faces of the displayed mesh.
+        # # If a mesh is already displayed, draw_mesh returns an error if the given V and
+        # # F have size different than the current ones
+        viewer.data.set_mesh(V1, F1);
+        viewer.core.align_camera_center(V1,F1);
+    elif key == ord('2'):
+        viewer.data.clear();
+        viewer.data.set_mesh(V2, F2);
+        viewer.core.align_camera_center(V2,F2);
+    return False
+
+
+#  Load two meshes
+igl.readOFF("../tutorial/shared/bumpy.off", V1, F1);
+igl.readOFF("../tutorial/shared/fertility.off", V2, F2);
+
+print("1 Switch to bump mesh")
+print("2 Switch to fertility mesh")
+
+viewer = igl.viewer.Viewer()
+
+# Register a keyboard callback that allows to switch between
+# the two loaded meshes
+viewer.callback_key_pressed = key_pressed
+viewer.data.set_mesh(V1, F1)
+viewer.launch()

+ 24 - 0
python/104_Colors.py

@@ -0,0 +1,24 @@
+import igl
+
+V = igl.eigen.MatrixXd()
+F = igl.eigen.MatrixXi()
+C = igl.eigen.MatrixXd()
+
+# Load a mesh in OFF format
+igl.readOFF("../tutorial/shared/screwdriver.off", V, F)
+
+# Plot the mesh
+viewer = igl.viewer.Viewer()
+viewer.data.set_mesh(V, F)
+
+# Use the z coordinate as a scalar field over the surface
+Z = V.col(2);
+
+# Compute per-vertex colors
+igl.jet(Z,True,C)
+
+# Add per-vertex colors
+viewer.data.set_colors(C)
+
+# Launch the viewer
+viewer.launch()

+ 67 - 0
python/105_Overlays.py

@@ -0,0 +1,67 @@
+import igl
+
+V = igl.eigen.MatrixXd()
+F = igl.eigen.MatrixXi()
+
+# Load a mesh in OFF format
+igl.readOFF("../tutorial/shared/bunny.off", V, F)
+
+# Find the bounding box
+m = V.colwiseMinCoeff()
+M = V.colwiseMaxCoeff()
+
+
+# Corners of the bounding box
+V_box = igl.eigen.MatrixXd(
+[
+[m[0,0], m[0,1], m[0,2]],
+[M[0,0], m[0,1], m[0,2]],
+[M[0,0], M[0,1], m[0,2]],
+[m[0,0], M[0,1], m[0,2]],
+[m[0,0], m[0,1], M[0,2]],
+[M[0,0], m[0,1], M[0,2]],
+[M[0,0], M[0,1], M[0,2]],
+[m[0,0], M[0,1], M[0,2]]
+]
+)
+
+E_box = igl.eigen.MatrixXi(
+[
+[0, 1],
+[1, 2],
+[2, 3],
+[3, 0],
+[4, 5],
+[5, 6],
+[6, 7],
+[7, 4],
+[0, 4],
+[1, 5],
+[2, 6],
+[7 ,3]
+]
+)
+
+# Plot the mesh
+viewer = igl.viewer.Viewer()
+viewer.data.set_mesh(V, F)
+
+# Plot the corners of the bounding box as points
+viewer.data.add_points(V_box,igl.eigen.MatrixXd([[1,0,0]]))
+
+# Plot the edges of the bounding box
+for i in range(0,E_box.rows()):
+    viewer.data.add_edges(
+        V_box.row(E_box[i,0]),
+        V_box.row(E_box[i,1]),
+        igl.eigen.MatrixXd([[1,0,0]]))
+
+# Plot labels with the coordinates of bounding box vertices
+l1 = 'x: ' + str(m[0,0]) + ' y: ' + str(m[0,1]) + ' z: ' + str(m[0,2])
+viewer.data.add_label(m.transpose(),l1)
+
+l2 = 'x: ' + str(M[0,0]) + ' y: ' + str(M[0,1]) + ' z: ' + str(M[0,2])
+viewer.data.add_label(M.transpose(),l2);
+
+# Launch the viewer
+viewer.launch();

+ 48 - 0
python/201_Normals.py

@@ -0,0 +1,48 @@
+import igl
+
+
+V = igl.eigen.MatrixXd()
+F = igl.eigen.MatrixXi()
+
+N_vertices = igl.eigen.MatrixXd()
+N_faces = igl.eigen.MatrixXd()
+N_corners = igl.eigen.MatrixXd()
+
+# This function is called every time a keyboard button is pressed
+def key_pressed(viewer, key, modifier):
+    if key == ord('1'):
+      viewer.data.set_normals(N_faces)
+      return True
+    elif key == ord('2'):
+      viewer.data.set_normals(N_vertices)
+      return True
+    elif key == ord('3'):
+      viewer.data.set_normals(N_corners)
+      return True
+    return False
+
+# Load a mesh in OFF format
+igl.readOFF("../tutorial/shared/fandisk.off", V, F);
+
+# Compute per-face normals
+N_faces = igl.eigen.MatrixXd()
+igl.per_face_normals(V,F,N_faces)
+
+# Compute per-vertex normals
+N_vertices = igl.eigen.MatrixXd()
+igl.per_vertex_normals(V,F,igl.PER_VERTEX_NORMALS_WEIGHTING_TYPE_AREA,N_vertices)
+
+# Compute per-corner normals, |dihedral angle| > 20 degrees --> crease
+N_corners = igl.eigen.MatrixXd()
+igl.per_corner_normals(V,F,20,N_corners)
+
+# Plot the mesh
+viewer = igl.viewer.Viewer()
+viewer.callback_key_pressed = key_pressed
+viewer.core.show_lines = False
+viewer.data.set_mesh(V, F)
+viewer.data.set_normals(N_faces)
+print("Press '1' for per-face normals.")
+print("Press '2' for per-vertex normals.")
+print("Press '3' for per-corner normals.")
+viewer.launch()

+ 20 - 0
python/202_GaussianCurvature.py

@@ -0,0 +1,20 @@
+import igl
+
+# Load mesh
+V = igl.eigen.MatrixXd()
+F = igl.eigen.MatrixXi()
+igl.readOFF("../tutorial/shared/bumpy.off",V,F);
+
+# Compute Gaussian curvature
+K = igl.eigen.MatrixXd();
+igl.gaussian_curvature(V,F,K);
+
+# Compute pseudocolor
+C = igl.eigen.MatrixXd();
+igl.jet(K,True,C);
+
+# Plot the mesh with pseudocolors
+viewer = igl.viewer.Viewer()
+viewer.data.set_mesh(V, F)
+viewer.data.set_colors(C)
+viewer.launch()

+ 61 - 0
python/203_CurvatureDirections.py

@@ -0,0 +1,61 @@
+import igl
+
+V = igl.eigen.MatrixXd();
+F = igl.eigen.MatrixXi();
+igl.read_triangle_mesh("../tutorial/shared/fertility.off", V, F);
+
+# Alternative discrete mean curvature
+HN = igl.eigen.MatrixXd()
+L = igl.eigen.SparseMatrixd()
+M = igl.eigen.SparseMatrixd()
+Minv = igl.eigen.SparseMatrixd()
+
+
+igl.cotmatrix(V,F,L)
+igl.massmatrix(V,F,igl.MASSMATRIX_TYPE_VORONOI,M)
+
+igl.invert_diag(M,Minv)
+
+# Laplace-Beltrami of position
+HN = -Minv*(L*V)
+
+# Extract magnitude as mean curvature
+H = HN.rowwiseNorm()
+
+# Compute curvature directions via quadric fitting
+PD1 = igl.eigen.MatrixXd()
+PD2 = igl.eigen.MatrixXd()
+
+PV1 = igl.eigen.MatrixXd()
+PV2 = igl.eigen.MatrixXd()
+
+igl.principal_curvature(V,F,PD1,PD2,PV1,PV2)
+
+# Mean curvature
+H = 0.5*(PV1+PV2)
+
+viewer = igl.viewer.Viewer()
+viewer.data.set_mesh(V, F)
+
+# Compute pseudocolor
+C = igl.eigen.MatrixXd()
+igl.parula(H,True,C)
+
+viewer.data.set_colors(C)
+
+# Average edge length for sizing
+avg = igl.avg_edge_length(V,F)
+
+# Draw a blue segment parallel to the minimal curvature direction
+red = igl.eigen.MatrixXd([[0.8,0.2,0.2]])
+blue = igl.eigen.MatrixXd([[0.2,0.2,0.8]])
+
+viewer.data.add_edges(V + PD1*avg, V - PD1*avg, blue)
+
+# Draw a red segment parallel to the maximal curvature direction
+viewer.data.add_edges(V + PD2*avg, V - PD2*avg, red)
+
+# Hide wireframe
+viewer.core.show_lines = False
+
+viewer.launch();

+ 50 - 0
python/204_Gradient.py

@@ -0,0 +1,50 @@
+import igl
+
+V = igl.eigen.MatrixXd()
+F = igl.eigen.MatrixXi()
+
+# Load a mesh in OFF format
+igl.readOFF("../tutorial/shared/cheburashka.off", V, F)
+
+# Read scalar function values from a file, U: #V by 1
+U = igl.eigen.MatrixXd()
+igl.readDMAT("../tutorial/shared/cheburashka-scalar.dmat",U)
+U = U.col(0)
+
+# Compute gradient operator: #F*3 by #V
+G = igl.eigen.SparseMatrixd()
+igl.grad(V,F,G)
+
+# Compute gradient of U
+GU = (G*U).MapMatrix(F.rows(),3)
+
+# Compute gradient magnitude
+GU_mag = GU.rowwiseNorm()
+
+viewer = igl.viewer.Viewer()
+viewer.data.set_mesh(V, F)
+
+# Compute pseudocolor for original function
+C = igl.eigen.MatrixXd()
+
+igl.jet(U,True,C)
+
+# Or for gradient magnitude
+# igl.jet(GU_mag,True,C)
+
+viewer.data.set_colors(C);
+
+# Average edge length divided by average gradient (for scaling)
+max_size = igl.avg_edge_length(V,F) / GU_mag.mean()
+
+# Draw a black segment in direction of gradient at face barycenters
+BC = igl.eigen.MatrixXd()
+igl.barycenter(V,F,BC)
+
+black = igl.eigen.MatrixXd([[0.0,0.0,0.0]])
+viewer.data.add_edges(BC,BC+max_size*GU, black)
+
+# Hide wireframe
+viewer.core.show_lines = False
+
+viewer.launch()

+ 108 - 0
python/205_Laplacian.py

@@ -0,0 +1,108 @@
+from __future__ import print_function
+import igl
+import math
+
+global V
+global U
+global F
+global L
+
+V = igl.eigen.MatrixXd()
+U = igl.eigen.MatrixXd()
+F = igl.eigen.MatrixXi()
+
+L = igl.eigen.SparseMatrixd()
+viewer = igl.viewer.Viewer()
+
+# Load a mesh in OFF format
+igl.readOFF("../tutorial/shared/cow.off", V, F)
+
+# Compute Laplace-Beltrami operator: #V by #V
+igl.cotmatrix(V,F,L)
+
+# Alternative construction of same Laplacian
+G = igl.eigen.SparseMatrixd()
+K = igl.eigen.SparseMatrixd()
+
+# Gradient/Divergence
+igl.grad(V,F,G);
+
+# Diagonal per-triangle "mass matrix"
+dblA = igl.eigen.MatrixXd()
+igl.doublearea(V,F,dblA)
+
+# Place areas along diagonal #dim times
+
+T = (dblA.replicate(3,1)*0.5).asDiagonal() * 1
+
+# Laplacian K built as discrete divergence of gradient or equivalently
+# discrete Dirichelet energy Hessian
+
+temp = -G.transpose()
+K = -G.transpose() * T * G
+print("|K-L|: ",(K-L).norm())
+
+def key_pressed(viewer, key, modifier):
+    global V
+    global U
+    global F
+    global L
+
+    if key == ord('r') or key == ord('R'):
+        U = V;
+    elif key == ord(' '):
+
+        # Recompute just mass matrix on each step
+        M = igl.eigen.SparseMatrixd()
+
+        igl.massmatrix(U,F,igl.MASSMATRIX_TYPE_BARYCENTRIC,M);
+
+        # Solve (M-delta*L) U = M*U
+        S = (M - 0.001*L)
+
+        solver = igl.eigen.SimplicialLLTsparse(S)
+
+        U = solver.solve(M*U)
+
+        # Compute centroid and subtract (also important for numerics)
+        dblA = igl.eigen.MatrixXd()
+        igl.doublearea(U,F,dblA)
+
+        print(dblA.sum())
+
+        area = 0.5*dblA.sum()
+        BC = igl.eigen.MatrixXd()
+        igl.barycenter(U,F,BC)
+        centroid = igl.eigen.MatrixXd([[0.0,0.0,0.0]])
+
+        for i in range(0,BC.rows()):
+            centroid += 0.5*dblA[i,0]/area*BC.row(i)
+
+        U -= centroid.replicate(U.rows(),1)
+
+        # Normalize to unit surface area (important for numerics)
+        U = U / math.sqrt(area)
+    else:
+        return False
+
+    # Send new positions, update normals, recenter
+    viewer.data.set_vertices(U)
+    viewer.data.compute_normals()
+    viewer.core.align_camera_center(U,F)
+    return True
+
+# Use original normals as pseudo-colors
+N = igl.eigen.MatrixXd()
+igl.per_vertex_normals(V,F,N)
+C = N.rowwiseNormalized()*0.5+0.5;
+
+# Initialize smoothing with base mesh
+U = V
+viewer.data.set_mesh(U, F)
+viewer.data.set_colors(C)
+viewer.callback_key_pressed = key_pressed
+
+print("Press [space] to smooth.")
+print("Press [r] to reset.")
+
+viewer.launch()

+ 34 - 0
python/301_Slice.py

@@ -0,0 +1,34 @@
+from __future__ import print_function
+import igl
+
+V = igl.eigen.MatrixXd()
+F = igl.eigen.MatrixXi()
+
+igl.readOFF("../tutorial/shared/decimated-knight.off",V,F)
+
+# 100 random indicies into rows of F
+I = igl.eigen.MatrixXi()
+igl.floor((0.5*(igl.eigen.MatrixXd.Random(100,1)+1.)*F.rows()),I);
+
+# 50 random indicies into rows of I
+J = igl.eigen.MatrixXi()
+igl.floor((0.5*(igl.eigen.MatrixXd.Random(50,1)+1.)*I.rows()),J)
+
+# K = I(J);
+K = igl.eigen.MatrixXi()
+igl.slice(I,J,K)
+
+# default green for all faces
+#C = p2e(np.array([[0.4,0.8,0.3]])).replicate(F.rows(),1)
+C = igl.eigen.MatrixXd([[0.4,0.8,0.3]]).replicate(F.rows(),1)
+
+# Red for each in K
+R = igl.eigen.MatrixXd([[1.0,0.3,0.3]]).replicate(K.rows(),1)
+# C(K,:) = R
+igl.slice_into(R,K,1,C)
+
+# Plot the mesh with pseudocolors
+viewer = igl.viewer.Viewer()
+viewer.data.set_mesh(V, F)
+viewer.data.set_colors(C)
+viewer.launch()

+ 34 - 0
python/302_Sort.py

@@ -0,0 +1,34 @@
+import igl
+
+V = igl.eigen.MatrixXd()
+F = igl.eigen.MatrixXi()
+
+igl.readOFF("../tutorial/shared/decimated-knight.off",V,F)
+
+# Sort barycenters lexicographically
+BC = igl.eigen.MatrixXd()
+sorted_BC = igl.eigen.MatrixXd()
+
+igl.barycenter(V,F,BC);
+
+I = igl.eigen.MatrixXi()
+J = igl.eigen.MatrixXi()
+
+# sorted_BC = BC(I,:)
+igl.sortrows(BC,True,sorted_BC,I)
+
+# Get sorted "place" from sorted indices
+J.resize(I.rows(),1)
+# J(I) = 1:numel(I)
+
+igl.slice_into(igl.coloni(0,I.size()-1),I,J)
+
+# Pseudo-color based on sorted place
+C = igl.eigen.MatrixXd()
+igl.jet(J.castdouble(),True,C)
+
+# Plot the mesh with pseudocolors
+viewer = igl.viewer.Viewer()
+viewer.data.set_mesh(V, F)
+viewer.data.set_colors(C)
+viewer.launch()

+ 73 - 0
python/303_LaplaceEquation.py

@@ -0,0 +1,73 @@
+import igl
+
+V = igl.eigen.MatrixXd()
+F = igl.eigen.MatrixXi()
+
+igl.readOFF("../tutorial/shared/camelhead.off",V,F)
+
+# Find boundary edges
+E = igl.eigen.MatrixXi()
+igl.boundary_facets(F,E);
+
+# Find boundary vertices
+b  = igl.eigen.MatrixXi()
+IA = igl.eigen.MatrixXi()
+IC = igl.eigen.MatrixXi()
+
+igl.unique(E,b,IA,IC);
+
+# List of all vertex indices
+vall  = igl.eigen.MatrixXi()
+vin   = igl.eigen.MatrixXi()
+
+igl.coloni(0,V.rows()-1,vall)
+
+# List of interior indices
+igl.setdiff(vall,b,vin,IA)
+
+# Construct and slice up Laplacian
+L = igl.eigen.SparseMatrixd()
+L_in_in = igl.eigen.SparseMatrixd()
+L_in_b = igl.eigen.SparseMatrixd()
+
+igl.cotmatrix(V,F,L)
+igl.slice(L,vin,vin,L_in_in)
+igl.slice(L,vin,b,L_in_b)
+
+# Dirichlet boundary conditions from z-coordinate
+bc = igl.eigen.MatrixXd()
+Z = V.col(2)
+igl.slice(Z,b,bc)
+
+# Solve PDE
+solver = igl.eigen.SimplicialLLTsparse(-L_in_in)
+Z_in = solver.solve(L_in_b*bc)
+
+# slice into solution
+igl.slice_into(Z_in,vin,Z)
+
+# Alternative, short hand
+mqwf = igl.min_quad_with_fixed_data()
+
+# Linear term is 0
+B = igl.eigen.MatrixXd()
+B.setZero(V.rows(),1);
+
+# Empty constraints
+Beq = igl.eigen.MatrixXd()
+Aeq = igl.eigen.SparseMatrixd()
+
+# Our cotmatrix is _negative_ definite, so flip sign
+igl.min_quad_with_fixed_precompute(-L,b,Aeq,True,mqwf)
+igl.min_quad_with_fixed_solve(mqwf,B,bc,Beq,Z)
+
+# Pseudo-color based on solution
+C = igl.eigen.MatrixXd()
+igl.jet(Z,True,C)
+
+# Plot the mesh with pseudocolors
+viewer = igl.viewer.Viewer()
+viewer.data.set_mesh(V, F)
+viewer.core.show_lines = False
+viewer.data.set_colors(C)
+viewer.launch()

+ 96 - 0
python/304_LinearEqualityConstraints.py

@@ -0,0 +1,96 @@
+import igl
+
+V = igl.eigen.MatrixXd()
+F = igl.eigen.MatrixXi()
+
+igl.readOFF("../tutorial/shared/cheburashka.off",V,F)
+
+# Two fixed points
+# Left hand, left foot
+b = igl.eigen.MatrixXi([[4331],[5957]])
+bc = igl.eigen.MatrixXd([[1],[-1]])
+
+# Construct Laplacian and mass matrix
+L = igl.eigen.SparseMatrixd()
+M = igl.eigen.SparseMatrixd()
+Minv = igl.eigen.SparseMatrixd()
+Q = igl.eigen.SparseMatrixd()
+
+igl.cotmatrix(V,F,L)
+igl.massmatrix(V,F,igl.MASSMATRIX_TYPE_VORONOI,M)
+igl.invert_diag(M,Minv)
+
+# Bi-Laplacian
+Q = L * (Minv * L);
+
+# Zero linear term
+B = igl.eigen.MatrixXd.Zero(V.rows(),1);
+
+Z       = igl.eigen.MatrixXd()
+Z_const = igl.eigen.MatrixXd()
+
+# Alternative, short hand
+mqwf = igl.min_quad_with_fixed_data()
+
+# Empty constraints
+Beq = igl.eigen.MatrixXd()
+Aeq = igl.eigen.SparseMatrixd()
+
+igl.min_quad_with_fixed_precompute(Q,b,Aeq,True,mqwf)
+igl.min_quad_with_fixed_solve(mqwf,B,bc,Beq,Z)
+
+# Constraint forcing difference of two points to be 0
+Aeq = igl.eigen.SparseMatrixd(1,V.rows())
+
+# Right hand, right foot
+Aeq.insert(0,6074,1)
+Aeq.insert(0,6523,-1)
+Aeq.makeCompressed()
+
+Beq = igl.eigen.MatrixXd([[0]])
+igl.min_quad_with_fixed_precompute(Q,b,Aeq,True,mqwf)
+igl.min_quad_with_fixed_solve(mqwf,B,bc,Beq,Z_const)
+
+# Pseudo-color based on solution
+global C
+C = igl.eigen.MatrixXd()
+
+global C_const
+C_const = igl.eigen.MatrixXd()
+
+global toggle
+toggle = True
+
+# Use same color axes
+min_z = min(Z.minCoeff(),Z_const.minCoeff())
+max_z = max(Z.maxCoeff(),Z_const.maxCoeff())
+
+igl.jet(      Z,min_z,max_z,C);
+igl.jet(Z_const,min_z,max_z,C_const);
+
+# Plot the mesh with pseudocolors
+viewer = igl.viewer.Viewer()
+viewer.data.set_mesh(V, F)
+viewer.core.show_lines = False
+viewer.data.set_colors(C)
+
+def key_down(viewer,key,mode):
+    if key == ord(' '):
+        global toggle
+        global C
+        global C_const
+
+        if toggle:
+            viewer.data.set_colors(C)
+        else:
+            viewer.data.set_colors(C_const)
+
+        toggle = not toggle;
+        return True
+
+    return False
+
+viewer.callback_key_down = key_down
+
+print("Press [space] to toggle between unconstrained and constrained.")
+viewer.launch()

+ 86 - 0
python/305_QuadraticProgramming.py

@@ -0,0 +1,86 @@
+import igl
+
+b = igl.eigen.MatrixXi()
+B = igl.eigen.MatrixXd()
+bc = igl.eigen.MatrixXd()
+lx = igl.eigen.MatrixXd()
+ux = igl.eigen.MatrixXd()
+Beq = igl.eigen.MatrixXd()
+Bieq = igl.eigen.MatrixXd()
+Z = igl.eigen.MatrixXd()
+
+Q = igl.eigen.SparseMatrixd()
+Aeq = igl.eigen.SparseMatrixd()
+Aieq = igl.eigen.SparseMatrixd()
+
+def solve(viewer):
+    global Q,B,b,bc,Aeq,Beq,Aieq,Bieq,lx,ux,Z
+    params = igl.active_set_params()
+    params.max_iter = 8
+
+    igl.active_set(Q,B,b,bc,Aeq,Beq,Aieq,Bieq,lx,ux,params,Z)
+
+    C = igl.eigen.MatrixXd()
+    igl.jet(Z,0,1,C)
+    viewer.data.set_colors(C)
+
+def key_down(viewer, key, mod):
+    global Beq,solve
+    if key == ord('.'):
+         Beq[0,0] = Beq[0,0] * 2.0
+         solve(viewer)
+         return True
+    elif key == ord(','):
+         Beq[0,0] = Beq[0,0] / 2.0
+         solve(viewer)
+         return True
+    elif key == ord(' '):
+         solve(viewer)
+         return True
+    return False;
+
+
+V = igl.eigen.MatrixXd()
+F = igl.eigen.MatrixXi()
+
+igl.readOFF("../tutorial/shared/cheburashka.off",V,F)
+
+# Plot the mesh
+viewer = igl.viewer.Viewer()
+viewer.data.set_mesh(V, F)
+viewer.core.show_lines = False
+viewer.callback_key_down = key_down
+
+# One fixed point on belly
+b  = igl.eigen.MatrixXi([[2556]])
+bc = igl.eigen.MatrixXd([[1]])
+
+# Construct Laplacian and mass matrix
+L = igl.eigen.SparseMatrixd()
+M = igl.eigen.SparseMatrixd()
+Minv = igl.eigen.SparseMatrixd()
+
+igl.cotmatrix(V,F,L)
+igl.massmatrix(V,F,igl.MASSMATRIX_TYPE_VORONOI,M);
+igl.invert_diag(M,Minv)
+
+# Bi-Laplacian
+Q = L.transpose() * (Minv * L)
+
+# Zero linear term
+B = igl.eigen.MatrixXd.Zero(V.rows(),1)
+
+# Lower and upper bound
+lx = igl.eigen.MatrixXd.Zero(V.rows(),1)
+ux = igl.eigen.MatrixXd.Ones(V.rows(),1)
+
+# Equality constraint constrain solution to sum to 1
+Beq = igl.eigen.MatrixXd([[0.08]])
+Aeq = M.diagonal().transpose().sparseView()
+
+# (Empty inequality constraints)
+solve(viewer)
+print("Press '.' to increase scale and resolve.")
+print("Press ',' to decrease scale and resolve.")
+
+viewer.launch()

+ 56 - 0
python/306_EigenDecomposition.py

@@ -0,0 +1,56 @@
+import igl
+
+V = igl.eigen.MatrixXd()
+U = igl.eigen.MatrixXd()
+F = igl.eigen.MatrixXi()
+
+c = 0
+bbd = 1.0
+twod = False
+
+if not igl.read_triangle_mesh("../tutorial/shared/beetle.off",V,F):
+    print("failed to load mesh")
+
+twod = V.col(2).minCoeff() == V.col(2).maxCoeff()
+bbd = (V.colwiseMaxCoeff() - V.colwiseMinCoeff()).norm()
+
+L = igl.eigen.SparseMatrixd()
+M = igl.eigen.SparseMatrixd()
+
+igl.cotmatrix(V,F,L)
+L = -L
+igl.massmatrix(V,F,igl.MASSMATRIX_TYPE_DEFAULT,M)
+k = 5
+
+D = igl.eigen.MatrixXd()
+if not igl.eigs(L,M,k+1,igl.EIGS_TYPE_SM,U,D):
+    print("Eigs failed.")
+
+U = (U-U.minCoeff())/(U.maxCoeff()-U.minCoeff());
+
+viewer = igl.viewer.Viewer()
+
+def key_down(viewer,key,mod):
+    global U, c
+    
+    if key == ord(' '):
+        U = U.rightCols(k)
+
+        # Rescale eigen vectors for visualization
+        Z = bbd*0.5*U.col(c)
+        C = igl.eigen.MatrixXd()
+        igl.parula(U.col(c),False,C)
+        c = (c+1)%U.cols()
+
+        if twod:
+            V.setcol(2,Z)
+
+        viewer.data.set_mesh(V,F)
+        viewer.data.compute_normals()
+        viewer.data.set_colors(C)
+        return True
+
+viewer.callback_key_down = key_down
+viewer.callback_key_down(viewer,ord(' '),0);
+viewer.core.show_lines = False
+viewer.launch()

+ 154 - 0
python/CMakeLists.txt

@@ -0,0 +1,154 @@
+cmake_minimum_required(VERSION 2.8)
+
+project(pybind)
+
+IF(MSVC)
+### Enable parallel compilation for Visual Studio
+  add_definitions(-DEIGEN_DONT_ALIGN)
+  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
+  SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/../ )
+  SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/../ )
+ENDIF(MSVC)
+
+SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../tutorial/cmake)
+
+if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+  message(STATUS "Setting build type to 'MinSizeRel' as none was specified.")
+  set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING "Choose the type of build." FORCE)
+  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
+    "MinSizeRel" "RelWithDebInfo")
+endif()
+
+find_package(OPENGL REQUIRED)
+
+# Force a specific python version
+# SET(PYTHON_LIBRARIES "D:/Python34/libs/python34.lib")
+# SET(PYTHON_INCLUDE_DIR "D:/Python34/include")
+
+# Force a specific python version
+# SET(PYTHON_LIBRARIES "/usr/local/Cellar/python3/3.5.0/Frameworks/Python.framework/Versions/3.5/lib/libpython3.5m.dylib")
+# SET(PYTHON_INCLUDE_DIR "/usr/local/Cellar/python3/3.5.0/Frameworks/Python.framework/Versions/3.5/include/python3.5m")
+
+set(Python_ADDITIONAL_VERSIONS 3.4.3 3.5 3.6)
+find_package(PythonLibs REQUIRED)
+find_package(PythonInterp REQUIRED)
+
+string(TOUPPER "${CMAKE_BUILD_TYPE}" U_CMAKE_BUILD_TYPE)
+if (UNIX)
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+  if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG)
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -flto")
+  endif()
+endif()
+
+# Compile with compiler warnings turned on
+if(MSVC)
+  if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
+    string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+  else()
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
+  endif()
+else()
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
+endif()
+
+include_directories(${PYTHON_INCLUDE_DIR} include)
+
+## include pybing
+include_directories(${PROJECT_SOURCE_DIR}/../external/pybind11/include)
+
+## include eigen
+include_directories(${PROJECT_SOURCE_DIR}/../external/nanogui/ext/eigen)
+
+## include libigl
+include_directories(${PROJECT_SOURCE_DIR}/../include)
+
+## include glew
+if(NOT APPLE)
+  find_package(GLEW REQUIRED)
+  include_directories( ${GLEW_INCLUDE_DIR} )
+	set(SHARED_SOURCES ${SHARED_SOURCES} ${GLEW_SOURCES})
+endif(NOT APPLE)
+
+
+# include nanogui and dependencies
+add_subdirectory("../external/nanogui/" "nanogui")
+include_directories("../external/nanogui/include")
+include_directories("../external/nanogui/ext/glfw/include")
+include_directories("../external/nanogui/ext/nanovg/src")
+list(APPEND SHARED_LIBRARIES "nanogui" "glfw" ${OPENGL_LIBRARIES})
+
+
+add_library(igl SHARED
+  python.cpp
+  py_vector.cpp
+  py_igl.cpp
+  py_doc.cpp
+  py_igl_viewer.cpp
+  ${SHARED_SOURCES}
+)
+
+# if(NOT APPLE)
+# 	find_package(GLEW REQUIRED)
+# endif(NOT APPLE)
+
+if(APPLE)
+	set(CMAKE_SHARED_LINKER_FLAGS "-framework OpenGL -framework Cocoa")
+endif (APPLE) #APPLE
+#
+# if(UNIX AND NOT APPLE)
+#   set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} -lGL -lGLU -lrt -lX11 -lXxf86vm -lXrandr -lpthread -lXi  -lXcursor -lXinerama ")
+#   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx")
+# endif(UNIX AND NOT APPLE)
+
+
+set_target_properties(igl PROPERTIES PREFIX "")
+set_target_properties(igl PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR})
+
+target_link_libraries(igl ${SHARED_LIBRARIES})
+
+if (WIN32)
+  if (MSVC)
+    # Enforce size-based optimization and link time code generation on MSVC (~30% smaller binaries in experiments)
+    set_target_properties(igl PROPERTIES COMPILE_FLAGS "/Os /GL")
+    set_target_properties(igl PROPERTIES LINK_FLAGS "/LTCG")
+  endif()
+
+  # .PYD file extension on Windows
+  set_target_properties(igl PROPERTIES SUFFIX ".pyd")
+
+  # Link against the Python shared library
+  # message(FATAL_ERROR ${PYTHON_LIBRARY})
+  # target_link_libraries(igl ${PYTHON_LIBRARY})
+  target_link_libraries(igl ${PYTHON_LIBRARIES})
+
+
+elseif (UNIX)
+  # It's quite common to have multiple copies of the same Python version
+  # installed on one's system. E.g.: one copy from the OS and another copy
+  # that's statically linked into an application like Blender or Maya.
+  # If we link our plugin library against the OS Python here and import it
+  # into Blender or Maya later on, this will cause segfaults when multiple
+  # conflicting Python instances are active at the same time.
+
+  # Windows does not seem to be affected by this issue. The solution for Linux
+  # and Mac OS is simple: we just don't link against the Python library. The
+  # resulting shared library will have missing symbols, but that's perfectly
+  # fine -- they will be resolved at import time.
+
+  # .SO file extension on Linux/Mac OS
+  set_target_properties(igl PROPERTIES SUFFIX ".so")
+
+  # Strip unnecessary sections of the binary on Linux/Mac OS
+  if(APPLE)
+    set_target_properties(igl PROPERTIES MACOSX_RPATH ".")
+    set_target_properties(igl PROPERTIES LINK_FLAGS "-undefined dynamic_lookup -dead_strip")
+    if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG)
+      add_custom_command(TARGET igl POST_BUILD COMMAND strip -u -r ${CMAKE_CURRENT_BINARY_DIR}/../igl.so)
+    endif()
+  else()
+    if (NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG)
+      add_custom_command(TARGET igl POST_BUILD COMMAND strip ${CMAKE_CURRENT_BINARY_DIR}/../igl.so)
+    endif()
+  endif()
+endif()

+ 159 - 0
python/README.md

@@ -0,0 +1,159 @@
+# Python wrappers for libigl
+
+
+## Work in progress
+<span style="color:#F62217">
+Everything in this folder is currently being developed and it is likely to be
+changed radically in the next couple of months, breaking compatibility between
+different version. We plan to stabilize the python API by the end of 2015.
+</span>
+
+## Introduction
+
+libigl functions can be called natively from python by compiling the wrappers
+in this folder. The wrappers supports both python 2.7 and python 3.5 and are
+generated using [pybind11](https://github.com/wjakob/pybind11).
+
+The generated library will statically link against all dependencies producing a single,
+self-contained binary.
+
+## Installation
+
+The python bindings can be compiled with the following instructions, assuming
+that your terminal is pointing to the root of libigl:
+
+```bash
+cd python
+mkdir build
+cd build; make; cd ..
+```
+
+The cmake script will complain if it is not able to find python. In that case
+you can specify the location of the interpreter by specifying the following
+cmake variables.
+
+MacOSX/Linux:
+
+```cmake
+SET(PYTHON_LIBRARIES "/usr/local/Cellar/python3/3.5.0/Frameworks/Python.framework/Versions/3.5/lib/libpython3.5m.dylib")
+SET(PYTHON_INCLUDE_DIR "/usr/local/Cellar/python3/3.5.0/Frameworks/Python.framework/Versions/3.5/include/python3.5m")
+```
+
+Windows:
+
+```cmake
+SET(PYTHON_LIBRARIES "C:/Python35/libs/python35.lib")
+SET(PYTHON_INCLUDE_DIR "C:/Python35/include")
+```
+
+## Tutorial
+
+All libigl tutorials will be ported to python and will use the same naming
+scheme. You can find the tutorials in the folder python/tutorials and you can
+launch them with the following commands:
+
+```bash
+cd python
+python 102_DrawMesh.py
+```
+
+## Matrix Representation
+
+TODO: describe in detail the wrapped eigen classes and how to convert them to
+numpy.
+
+## Viewer and callbacks
+
+The igl viewer provides a convenient and efficient way of visualizing 3D
+surfaces in python. It behaves in the same way as the C++ viewer and supports
+native python functions as callbacks. This is a simple example that loads
+two meshes and switches between the two when a key is pressed:
+
+```python
+import igl
+
+V1 = igl.eigen.MatrixXd()
+F1 = igl.eigen.MatrixXi()
+
+V2 = igl.eigen.MatrixXd()
+F2 = igl.eigen.MatrixXi()
+
+def key_pressed(viewer, key, modifier):
+    print("Key: ", chr(key))
+
+    if key == ord('1'):
+        # # Clear should be called before drawing the mesh
+        viewer.data.clear();
+        # # Draw_mesh creates or updates the vertices and faces of the displayed mesh.
+        # # If a mesh is already displayed, draw_mesh returns an error if the given V and
+        # # F have size different than the current ones
+        viewer.data.set_mesh(V1, F1);
+        viewer.core.align_camera_center(V1,F1);
+    elif key == ord('2'):
+        viewer.data.clear();
+        viewer.data.set_mesh(V2, F2);
+        viewer.core.align_camera_center(V2,F2);
+    return False
+
+
+#  Load two meshes
+igl.readOFF("../tutorial/shared/bumpy.off", V1, F1);
+igl.readOFF("../tutorial/shared/fertility.off", V2, F2);
+
+print("1 Switch to bump mesh")
+print("2 Switch to fertility mesh")
+
+viewer = igl.viewer.Viewer()
+
+# Register a keyboard callback that allows to switch between
+# the two loaded meshes
+viewer.callback_key_pressed = key_pressed
+viewer.data.set_mesh(V1, F1)
+viewer.launch()
+```
+
+### Remote viewer
+
+Whe using the viewer from an interactive python shell (iPython), it is
+inconvenient to let the viewer take control of the main thread for rendering
+purposes. We provide a simple wrapper for the viewer that allows to launch
+a remote process and send meshes to it via a TCP/IP socket. For more
+informations on how to use it see the documentation in [tcpviewer.py](tcpviewer.py)
+
+## Matlab
+
+The python wrappers can be natively being used from MATLAB.
+We provide a few examples in the folder python/matlab.
+
+## Documentation
+
+The python functions have exactly the same prototypes as their C++ counterpart.
+To get help for a certain function, please check the documentation in the
+corresponding .h file in libigl/include. We will add a proper docstring
+documentation in the future.
+
+## Known Issues
+
+## Contact
+
+Libigl is a group endeavor led by [Alec
+Jacobson](http://www.cs.columbia.edu/~jacobson/) and [Daniele
+Panozzo](http://www.inf.ethz.ch/personal/dpanozzo/). Please [contact
+us](mailto:alecjacobson@gmail.com,daniele.panozzo@gmail.com) if you have
+questions or comments. For troubleshooting, please post an
+[issue](https://github.com/libigl/libigl/issues) on github.
+
+If you're using libigl in your projects, quickly [drop us a
+note](mailto:alecjacobson@gmail.com,daniele.panozzo@gmail.com). Tell us who you
+are and what you're using it for. This helps us apply for funding and justify
+spending time maintaining this.
+
+If you find bugs or have problems please use our [github issue tracking
+page](https://github.com/libigl/libigl/issues).
+
+## Copyright
+2015 Alec Jacobson, Daniele Panozzo, Christian Schüller, Olga Diamanti, Qingnan
+Zhou, Nico Pietroni, Stefan Brugger, Kenshi Takayama, Wenzel Jakob, Nikolas De
+Giorgis, Luigi Rocca, Leonardo Sacht, Olga Sorkine-Hornung, and others.
+
+Please see individual files for appropriate copyright notices.

+ 51 - 0
python/iglhelpers.py

@@ -0,0 +1,51 @@
+import numpy as np
+import scipy.sparse as sparse
+import igl
+
+def p2e(m):
+    if isinstance(m, np.ndarray):
+        if m.dtype.type == np.int32:
+            return igl.eigen.MatrixXi(m)
+        elif m.dtype.type == np.float64:
+            return igl.eigen.MatrixXd(m)
+        raise TypeError("p2e only support dtype float64 or int32")
+    if sparse.issparse(m):
+        # convert in a dense matrix with triples
+        coo = m.tocoo()
+        triplets = np.vstack((coo.row, coo.col, coo.data)).T
+
+        triples_eigen_wrapper = igl.eigen.MatrixXd(triplets)
+
+        if m.dtype.type == np.int32:
+            t = igl.eigen.SparseMatrixi()
+            t.fromcoo(triples_eigen_wrapper)
+            return t
+        elif m.dtype.type == np.float64:
+            t = igl.eigen.SparseMatrixd()
+            t.fromCOO(triples_eigen_wrapper)
+            return t
+
+
+    raise TypeError("p2e only support numpy.array or scipy.sparse")
+
+
+def e2p(m):
+    if isinstance(m, igl.eigen.MatrixXd):
+        return np.array(m, dtype='float64')
+    elif isinstance(m, igl.eigen.MatrixXi):
+        return np.array(m, dtype='int32')
+    elif isinstance(m, igl.eigen.SparseMatrixd):
+        coo = np.array(m.toCOO())
+        I = coo[:, 0]
+        J = coo[:, 1]
+        V = coo[:, 2]
+        return sparse.coo_matrix((V,(I,J)), shape=(m.rows(),m.cols()), dtype='float64')
+    elif isinstance(m, igl.eigen.SparseMatrixi):
+        coo = np.array(m.toCOO())
+        I = coo[:, 0]
+        J = coo[:, 1]
+        V = coo[:, 2]
+        return sparse.coo_matrix((V,(I,J)), shape=(m.rows(),m.cols()), dtype='int32')
+
+def printMatrixSizes(x,xn):
+    print(xn + " (" + str(x.rows()) + "," + str(x.cols()) + ")")

+ 59 - 0
python/matlab/CurvatureDirections.m

@@ -0,0 +1,59 @@
+V = py.igl.eigen.MatrixXd();
+F = py.igl.eigen.MatrixXi();
+py.igl.read_triangle_mesh('../tutorial/shared/fertility.off', V, F);
+
+% Alternative discrete mean curvature
+HN = py.igl.eigen.MatrixXd();
+L = py.igl.eigen.SparseMatrixd();
+M = py.igl.eigen.SparseMatrixd();
+Minv = py.igl.eigen.SparseMatrixd();
+
+
+py.igl.cotmatrix(V,F,L)
+py.igl.massmatrix(V,F,py.igl.MASSMATRIX_TYPE_VORONOI,M)
+
+py.igl.invert_diag(M,Minv)
+
+% Laplace-Beltrami of position
+HN = -Minv*(L*V)
+
+% Extract magnitude as mean curvature
+H = HN.rowwiseNorm()
+
+% Compute curvature directions via quadric fitting
+PD1 = py.igl.eigen.MatrixXd()
+PD2 = py.igl.eigen.MatrixXd()
+
+PV1 = py.igl.eigen.MatrixXd()
+PV2 = py.igl.eigen.MatrixXd()
+
+py.igl.principal_curvature(V,F,PD1,PD2,PV1,PV2)
+
+% Mean curvature
+H = 0.5*(PV1+PV2)
+
+viewer = py.igl.viewer.Viewer()
+viewer.data.set_mesh(V, F)
+
+% Compute pseudocolor
+C = py.igl.eigen.MatrixXd()
+py.igl.parula(H,true,C)
+
+viewer.data.set_colors(C)
+
+% Average edge length for sizing
+avg = py.igl.avg_edge_length(V,F)
+
+% Draw a blue segment parallel to the minimal curvature direction
+red = py.iglhelpers.p2e(py.numpy.array([[0.8,0.2,0.2]]))
+blue = py.iglhelpers.p2e(py.numpy.array([[0.2,0.2,0.8]]))
+
+viewer.data.add_edges(V + PD1*avg, V - PD1*avg, blue)
+
+% Draw a red segment parallel to the maximal curvature direction
+viewer.data.add_edges(V + PD2*avg, V - PD2*avg, red)
+
+% Hide wireframe
+viewer.core.show_lines = false
+
+viewer.launch()

+ 12 - 0
python/matlab/t102DrawMesh.m

@@ -0,0 +1,12 @@
+% Load a mesh in OFF format
+V = py.igl.eigen.MatrixXd();
+F = py.igl.eigen.MatrixXi();
+py.igl.readOFF('../tutorial/shared/beetle.off', V, F);
+
+V
+
+% Plot the mesh
+viewer = py.tcpviewer.TCPViewer()
+viewer.data.set_mesh(V, F)
+viewer.launch()
+

+ 409 - 0
python/py_doc.cpp

@@ -0,0 +1,409 @@
+const char *__doc_igl_AABB = R"igl_Qu8mg5v7(See igl\AABB.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_active_set = R"igl_Qu8mg5v7(See igl\active_set.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_adjacency_list = R"igl_Qu8mg5v7(See igl\adjacency_list.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_adjacency_matrix = R"igl_Qu8mg5v7(See igl\adjacency_matrix.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_all_edges = R"igl_Qu8mg5v7(See igl\all_edges.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_all_pairs_distances = R"igl_Qu8mg5v7(See igl\all_pairs_distances.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_angle_bound_frame_fields = R"igl_Qu8mg5v7(See igl\angle_bound_frame_fields.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_angular_distance = R"igl_Qu8mg5v7(See igl\angular_distance.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_any_of = R"igl_Qu8mg5v7(See igl\any_of.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_arap = R"igl_Qu8mg5v7(See igl\arap.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_ARAPEnergyType = R"igl_Qu8mg5v7(See igl\ARAPEnergyType.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_arap_dof = R"igl_Qu8mg5v7(See igl\arap_dof.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_arap_linear_block = R"igl_Qu8mg5v7(See igl\arap_linear_block.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_arap_rhs = R"igl_Qu8mg5v7(See igl\arap_rhs.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_average_onto_faces = R"igl_Qu8mg5v7(See igl\average_onto_faces.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_average_onto_vertices = R"igl_Qu8mg5v7(See igl\average_onto_vertices.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_avg_edge_length = R"igl_Qu8mg5v7(See igl\avg_edge_length.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_axis_angle_to_quat = R"igl_Qu8mg5v7(See igl\axis_angle_to_quat.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_barycenter = R"igl_Qu8mg5v7(See igl\barycenter.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_barycentric_coordinates = R"igl_Qu8mg5v7(See igl\barycentric_coordinates.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_barycentric_to_global = R"igl_Qu8mg5v7(See igl\barycentric_to_global.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_basename = R"igl_Qu8mg5v7(See igl\basename.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_bfs_orient = R"igl_Qu8mg5v7(See igl\bfs_orient.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_biharmonic_coordinates = R"igl_Qu8mg5v7(See igl\biharmonic_coordinates.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_bone_parents = R"igl_Qu8mg5v7(See igl\bone_parents.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_boundary_conditions = R"igl_Qu8mg5v7(See igl\boundary_conditions.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_boundary_facets = R"igl_Qu8mg5v7(See igl\boundary_facets.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_boundary_loop = R"igl_Qu8mg5v7(See igl\boundary_loop.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_bounding_box = R"igl_Qu8mg5v7(See igl\bounding_box.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_bounding_box_diagonal = R"igl_Qu8mg5v7(See igl\bounding_box_diagonal.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_Camera = R"igl_Qu8mg5v7(See igl\Camera.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_canonical_quaternions = R"igl_Qu8mg5v7(See igl\canonical_quaternions.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_cat = R"igl_Qu8mg5v7(See igl\cat.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_ceil = R"igl_Qu8mg5v7(See igl\ceil.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_centroid = R"igl_Qu8mg5v7(See igl\centroid.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_circulation = R"igl_Qu8mg5v7(See igl\circulation.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_collapse_edge = R"igl_Qu8mg5v7(See igl\collapse_edge.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_collapse_small_triangles = R"igl_Qu8mg5v7(See igl\collapse_small_triangles.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_colon = R"igl_Qu8mg5v7(See igl\colon.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_columnize = R"igl_Qu8mg5v7(See igl\columnize.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_column_to_quats = R"igl_Qu8mg5v7(See igl\column_to_quats.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_comb_cross_field = R"igl_Qu8mg5v7(See igl\comb_cross_field.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_comb_frame_field = R"igl_Qu8mg5v7(See igl\comb_frame_field.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_comb_line_field = R"igl_Qu8mg5v7(See igl\comb_line_field.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_components = R"igl_Qu8mg5v7(See igl\components.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_compute_frame_field_bisectors = R"igl_Qu8mg5v7(See igl\compute_frame_field_bisectors.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_ConjugateFFSolverData = R"igl_Qu8mg5v7(See igl\ConjugateFFSolverData.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_conjugate_frame_fields = R"igl_Qu8mg5v7(See igl\conjugate_frame_fields.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_cotmatrix = R"igl_Qu8mg5v7(See igl\cotmatrix.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_cotmatrix_entries = R"igl_Qu8mg5v7(See igl\cotmatrix_entries.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_covariance_scatter_matrix = R"igl_Qu8mg5v7(See igl\covariance_scatter_matrix.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_cross = R"igl_Qu8mg5v7(See igl\cross.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_cross_field_missmatch = R"igl_Qu8mg5v7(See igl\cross_field_missmatch.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_crouzeix_raviart_massmatrix = R"igl_Qu8mg5v7(See igl\crouzeix_raviart_massmatrix.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_cumsum = R"igl_Qu8mg5v7(See igl\cumsum.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_cut_mesh = R"igl_Qu8mg5v7(See igl\cut_mesh.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_cut_mesh_from_singularities = R"igl_Qu8mg5v7(See igl\cut_mesh_from_singularities.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_C_STR = R"igl_Qu8mg5v7(See igl\C_STR.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_dated_copy = R"igl_Qu8mg5v7(See igl\dated_copy.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_decimate = R"igl_Qu8mg5v7(See igl\decimate.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_deform_skeleton = R"igl_Qu8mg5v7(See igl\deform_skeleton.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_deprecated = R"igl_Qu8mg5v7(See igl\deprecated.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_diag = R"igl_Qu8mg5v7(See igl\diag.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_dihedral_angles = R"igl_Qu8mg5v7(See igl\dihedral_angles.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_dijkstra = R"igl_Qu8mg5v7(See igl\dijkstra.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_directed_edge_orientations = R"igl_Qu8mg5v7(See igl\directed_edge_orientations.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_directed_edge_parents = R"igl_Qu8mg5v7(See igl\directed_edge_parents.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_dirname = R"igl_Qu8mg5v7(See igl\dirname.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_dot = R"igl_Qu8mg5v7(See igl\dot.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_dot_row = R"igl_Qu8mg5v7(See igl\dot_row.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_doublearea = R"igl_Qu8mg5v7(See igl\doublearea.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_dqs = R"igl_Qu8mg5v7(See igl\dqs.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_edges = R"igl_Qu8mg5v7(See igl\edges.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_edge_collapse_is_valid = R"igl_Qu8mg5v7(See igl\edge_collapse_is_valid.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_edge_flaps = R"igl_Qu8mg5v7(See igl\edge_flaps.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_edge_lengths = R"igl_Qu8mg5v7(See igl\edge_lengths.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_edge_topology = R"igl_Qu8mg5v7(See igl\edge_topology.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_eigs = R"igl_Qu8mg5v7(See igl\eigs.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_EPS = R"igl_Qu8mg5v7(See igl\EPS.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_example_fun = R"igl_Qu8mg5v7(See igl\example_fun.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_exterior_edges = R"igl_Qu8mg5v7(See igl\exterior_edges.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_faces_first = R"igl_Qu8mg5v7(See igl\faces_first.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_facet_components = R"igl_Qu8mg5v7(See igl\facet_components.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_face_areas = R"igl_Qu8mg5v7(See igl\face_areas.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_face_occurrences = R"igl_Qu8mg5v7(See igl\face_occurrences.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_false_barycentric_subdivision = R"igl_Qu8mg5v7(See igl\false_barycentric_subdivision.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_field_local_global_conversions = R"igl_Qu8mg5v7(See igl\field_local_global_conversions.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_file_contents_as_string = R"igl_Qu8mg5v7(See igl\file_contents_as_string.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_file_dialog_open = R"igl_Qu8mg5v7(See igl\file_dialog_open.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_file_dialog_save = R"igl_Qu8mg5v7(See igl\file_dialog_save.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_file_exists = R"igl_Qu8mg5v7(See igl\file_exists.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_find = R"igl_Qu8mg5v7(See igl\find.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_find_cross_field_singularities = R"igl_Qu8mg5v7(See igl\find_cross_field_singularities.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_fit_plane = R"igl_Qu8mg5v7(See igl\fit_plane.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_fit_rigid = R"igl_Qu8mg5v7(See igl\fit_rigid.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_fit_rotations = R"igl_Qu8mg5v7(See igl\fit_rotations.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_floor = R"igl_Qu8mg5v7(See igl\floor.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_forward_kinematics = R"igl_Qu8mg5v7(See igl\forward_kinematics.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_frame_field_deformer = R"igl_Qu8mg5v7(See igl\frame_field_deformer.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_frame_to_cross_field = R"igl_Qu8mg5v7(See igl\frame_to_cross_field.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_frustum = R"igl_Qu8mg5v7(See igl\frustum.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_full = R"igl_Qu8mg5v7(See igl\full.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_gaussian_curvature = R"igl_Qu8mg5v7(See igl\gaussian_curvature.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_get_seconds = R"igl_Qu8mg5v7(See igl\get_seconds.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_get_seconds_hires = R"igl_Qu8mg5v7(See igl\get_seconds_hires.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_grad = R"igl_Qu8mg5v7(See igl\grad.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_group_sum_matrix = R"igl_Qu8mg5v7(See igl\group_sum_matrix.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_HalfEdgeIterator = R"igl_Qu8mg5v7(See igl\HalfEdgeIterator.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_harmonic = R"igl_Qu8mg5v7(See igl\harmonic.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_harwell_boeing = R"igl_Qu8mg5v7(See igl\harwell_boeing.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_histc = R"igl_Qu8mg5v7(See igl\histc.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_hsv_to_rgb = R"igl_Qu8mg5v7(See igl\hsv_to_rgb.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_igl_inline = R"igl_Qu8mg5v7(See igl\igl_inline.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_IndexComparison = R"igl_Qu8mg5v7(See igl\IndexComparison.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_integrable_polyvector_fields = R"igl_Qu8mg5v7(See igl\integrable_polyvector_fields.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_internal_angles = R"igl_Qu8mg5v7(See igl\internal_angles.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_intersect = R"igl_Qu8mg5v7(See igl\intersect.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_invert_diag = R"igl_Qu8mg5v7(See igl\invert_diag.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_in_element = R"igl_Qu8mg5v7(See igl\in_element.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_is_border_vertex = R"igl_Qu8mg5v7(See igl\is_border_vertex.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_is_boundary_edge = R"igl_Qu8mg5v7(See igl\is_boundary_edge.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_is_dir = R"igl_Qu8mg5v7(See igl\is_dir.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_is_edge_manifold = R"igl_Qu8mg5v7(See igl\is_edge_manifold.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_is_file = R"igl_Qu8mg5v7(See igl\is_file.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_is_irregular_vertex = R"igl_Qu8mg5v7(See igl\is_irregular_vertex.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_is_planar = R"igl_Qu8mg5v7(See igl\is_planar.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_is_readable = R"igl_Qu8mg5v7(See igl\is_readable.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_is_sparse = R"igl_Qu8mg5v7(See igl\is_sparse.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_is_symmetric = R"igl_Qu8mg5v7(See igl\is_symmetric.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_is_vertex_manifold = R"igl_Qu8mg5v7(See igl\is_vertex_manifold.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_is_writable = R"igl_Qu8mg5v7(See igl\is_writable.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_jet = R"igl_Qu8mg5v7(See igl\jet.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_launch_medit = R"igl_Qu8mg5v7(See igl\launch_medit.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_lbs_matrix = R"igl_Qu8mg5v7(See igl\lbs_matrix.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_limit_faces = R"igl_Qu8mg5v7(See igl\limit_faces.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_line_field_missmatch = R"igl_Qu8mg5v7(See igl\line_field_missmatch.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_line_segment_in_rectangle = R"igl_Qu8mg5v7(See igl\line_segment_in_rectangle.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_linprog = R"igl_Qu8mg5v7(See igl\linprog.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_list_to_matrix = R"igl_Qu8mg5v7(See igl\list_to_matrix.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_local_basis = R"igl_Qu8mg5v7(See igl\local_basis.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_look_at = R"igl_Qu8mg5v7(See igl\look_at.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_lscm = R"igl_Qu8mg5v7(See igl\lscm.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_lu_lagrange = R"igl_Qu8mg5v7(See igl\lu_lagrange.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_map_vertices_to_circle = R"igl_Qu8mg5v7(See igl\map_vertices_to_circle.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_marching_cubes = R"igl_Qu8mg5v7(See igl\marching_cubes.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_massmatrix = R"igl_Qu8mg5v7(See igl\massmatrix.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_material_colors = R"igl_Qu8mg5v7(See igl\material_colors.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_matlab_format = R"igl_Qu8mg5v7(See igl\matlab_format.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_matrix_to_list = R"igl_Qu8mg5v7(See igl\matrix_to_list.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_mat_max = R"igl_Qu8mg5v7(See igl\mat_max.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_mat_min = R"igl_Qu8mg5v7(See igl\mat_min.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_mat_to_quat = R"igl_Qu8mg5v7(See igl\mat_to_quat.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_max_size = R"igl_Qu8mg5v7(See igl\max_size.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_median = R"igl_Qu8mg5v7(See igl\median.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_min_quad_dense = R"igl_Qu8mg5v7(See igl\min_quad_dense.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_min_quad_with_fixed = R"igl_Qu8mg5v7(See igl\min_quad_with_fixed.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_min_size = R"igl_Qu8mg5v7(See igl\min_size.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_mod = R"igl_Qu8mg5v7(See igl\mod.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_mode = R"igl_Qu8mg5v7(See igl\mode.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_mvc = R"igl_Qu8mg5v7(See igl\mvc.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_nchoosek = R"igl_Qu8mg5v7(See igl\nchoosek.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_next_filename = R"igl_Qu8mg5v7(See igl\next_filename.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_normalize_quat = R"igl_Qu8mg5v7(See igl\normalize_quat.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_normalize_row_lengths = R"igl_Qu8mg5v7(See igl\normalize_row_lengths.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_normalize_row_sums = R"igl_Qu8mg5v7(See igl\normalize_row_sums.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_NormalType = R"igl_Qu8mg5v7(See igl\NormalType.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_normal_derivative = R"igl_Qu8mg5v7(See igl\normal_derivative.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_null = R"igl_Qu8mg5v7(See igl\null.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_n_polyvector = R"igl_Qu8mg5v7(See igl\n_polyvector.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_n_polyvector_general = R"igl_Qu8mg5v7(See igl\n_polyvector_general.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_ONE = R"igl_Qu8mg5v7(See igl\ONE.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_on_boundary = R"igl_Qu8mg5v7(See igl\on_boundary.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_orientable_patches = R"igl_Qu8mg5v7(See igl\orientable_patches.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_orient_outward = R"igl_Qu8mg5v7(See igl\orient_outward.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_orth = R"igl_Qu8mg5v7(See igl\orth.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_ortho = R"igl_Qu8mg5v7(See igl\ortho.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_outer_facet = R"igl_Qu8mg5v7(See igl\outer_facet.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_parallel_transport_angles = R"igl_Qu8mg5v7(See igl\parallel_transport_angles.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_partition = R"igl_Qu8mg5v7(See igl\partition.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_parula = R"igl_Qu8mg5v7(See igl\parula.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_pathinfo = R"igl_Qu8mg5v7(See igl\pathinfo.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_path_to_executable = R"igl_Qu8mg5v7(See igl\path_to_executable.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_per_corner_normals = R"igl_Qu8mg5v7(See igl\per_corner_normals.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_per_edge_normals = R"igl_Qu8mg5v7(See igl\per_edge_normals.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_per_face_normals = R"igl_Qu8mg5v7(See igl\per_face_normals.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_per_vertex_attribute_smoothing = R"igl_Qu8mg5v7(See igl\per_vertex_attribute_smoothing.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_per_vertex_normals = R"igl_Qu8mg5v7(See igl\per_vertex_normals.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_PI = R"igl_Qu8mg5v7(See igl\PI.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_planarize_quad_mesh = R"igl_Qu8mg5v7(See igl\planarize_quad_mesh.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_ply = R"igl_Qu8mg5v7(See igl\ply.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_point_in_circle = R"igl_Qu8mg5v7(See igl\point_in_circle.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_point_in_poly = R"igl_Qu8mg5v7(See igl\point_in_poly.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_point_mesh_squared_distance = R"igl_Qu8mg5v7(See igl\point_mesh_squared_distance.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_polar_dec = R"igl_Qu8mg5v7(See igl\polar_dec.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_polar_svd = R"igl_Qu8mg5v7(See igl\polar_svd.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_polar_svd3x3 = R"igl_Qu8mg5v7(See igl\polar_svd3x3.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_polygon_mesh_to_triangle_mesh = R"igl_Qu8mg5v7(See igl\polygon_mesh_to_triangle_mesh.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_polyroots = R"igl_Qu8mg5v7(See igl\polyroots.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_polyvector_field_comb_from_matchings_and_cuts = R"igl_Qu8mg5v7(See igl\polyvector_field_comb_from_matchings_and_cuts.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_polyvector_field_cut_mesh_with_singularities = R"igl_Qu8mg5v7(See igl\polyvector_field_cut_mesh_with_singularities.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_polyvector_field_matchings = R"igl_Qu8mg5v7(See igl\polyvector_field_matchings.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_polyvector_field_poisson_reconstruction = R"igl_Qu8mg5v7(See igl\polyvector_field_poisson_reconstruction.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_polyvector_field_singularities_from_matchings = R"igl_Qu8mg5v7(See igl\polyvector_field_singularities_from_matchings.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_principal_curvature = R"igl_Qu8mg5v7(See igl\principal_curvature.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_print_ijv = R"igl_Qu8mg5v7(See igl\print_ijv.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_print_vector = R"igl_Qu8mg5v7(See igl\print_vector.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_procrustes = R"igl_Qu8mg5v7(See igl\procrustes.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_project = R"igl_Qu8mg5v7(See igl\project.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_project_isometrically_to_plane = R"igl_Qu8mg5v7(See igl\project_isometrically_to_plane.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_project_to_line = R"igl_Qu8mg5v7(See igl\project_to_line.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_project_to_line_segment = R"igl_Qu8mg5v7(See igl\project_to_line_segment.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_pseudonormal_test = R"igl_Qu8mg5v7(See igl\pseudonormal_test.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_quad_planarity = R"igl_Qu8mg5v7(See igl\quad_planarity.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_quats_to_column = R"igl_Qu8mg5v7(See igl\quats_to_column.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_quat_conjugate = R"igl_Qu8mg5v7(See igl\quat_conjugate.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_quat_mult = R"igl_Qu8mg5v7(See igl\quat_mult.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_quat_to_axis_angle = R"igl_Qu8mg5v7(See igl\quat_to_axis_angle.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_quat_to_mat = R"igl_Qu8mg5v7(See igl\quat_to_mat.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_random_dir = R"igl_Qu8mg5v7(See igl\random_dir.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_random_points_on_mesh = R"igl_Qu8mg5v7(See igl\random_points_on_mesh.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_random_quaternion = R"igl_Qu8mg5v7(See igl\random_quaternion.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_randperm = R"igl_Qu8mg5v7(See igl\randperm.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_ray_sphere_intersect = R"igl_Qu8mg5v7(See igl\ray_sphere_intersect.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_readCSV = R"igl_Qu8mg5v7(See igl\readCSV.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_readDMAT = R"igl_Qu8mg5v7(See igl\readDMAT.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_readMESH = R"igl_Qu8mg5v7(See igl\readMESH.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_readNODE = R"igl_Qu8mg5v7(See igl\readNODE.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_readOBJ = R"igl_Qu8mg5v7(See igl\readOBJ.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_readOFF = R"igl_Qu8mg5v7(See igl\readOFF.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_readPLY = R"igl_Qu8mg5v7(See igl\readPLY.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_readSTL = R"igl_Qu8mg5v7(See igl\readSTL.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_readTGF = R"igl_Qu8mg5v7(See igl\readTGF.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_readWRL = R"igl_Qu8mg5v7(See igl\readWRL.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_read_triangle_mesh = R"igl_Qu8mg5v7(See igl\read_triangle_mesh.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_REDRUM = R"igl_Qu8mg5v7(See igl\REDRUM.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_remove_duplicates = R"igl_Qu8mg5v7(See igl\remove_duplicates.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_remove_duplicate_vertices = R"igl_Qu8mg5v7(See igl\remove_duplicate_vertices.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_remove_unreferenced = R"igl_Qu8mg5v7(See igl\remove_unreferenced.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_reorder = R"igl_Qu8mg5v7(See igl\reorder.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_repdiag = R"igl_Qu8mg5v7(See igl\repdiag.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_repmat = R"igl_Qu8mg5v7(See igl\repmat.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_rgb_to_hsv = R"igl_Qu8mg5v7(See igl\rgb_to_hsv.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_rotate_by_quat = R"igl_Qu8mg5v7(See igl\rotate_by_quat.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_rotate_vectors = R"igl_Qu8mg5v7(See igl\rotate_vectors.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_rotation_matrix_from_directions = R"igl_Qu8mg5v7(See igl\rotation_matrix_from_directions.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_round = R"igl_Qu8mg5v7(See igl\round.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_rows_to_matrix = R"igl_Qu8mg5v7(See igl\rows_to_matrix.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_sample_edges = R"igl_Qu8mg5v7(See igl\sample_edges.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_serialize = R"igl_Qu8mg5v7(See igl\serialize.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_setdiff = R"igl_Qu8mg5v7(See igl\setdiff.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_signed_distance = R"igl_Qu8mg5v7(See igl\signed_distance.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_slice = R"igl_Qu8mg5v7(See igl\slice.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_slice_into = R"igl_Qu8mg5v7(See igl\slice_into.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_slice_mask = R"igl_Qu8mg5v7(See igl\slice_mask.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_slice_tets = R"igl_Qu8mg5v7(See igl\slice_tets.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_snap_points = R"igl_Qu8mg5v7(See igl\snap_points.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_snap_to_canonical_view_quat = R"igl_Qu8mg5v7(See igl\snap_to_canonical_view_quat.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_snap_to_fixed_up = R"igl_Qu8mg5v7(See igl\snap_to_fixed_up.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_SolverStatus = R"igl_Qu8mg5v7(See igl\SolverStatus.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_sort = R"igl_Qu8mg5v7(See igl\sort.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_SortableRow = R"igl_Qu8mg5v7(See igl\SortableRow.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_sortrows = R"igl_Qu8mg5v7(See igl\sortrows.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_sort_angles = R"igl_Qu8mg5v7(See igl\sort_angles.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_sort_triangles = R"igl_Qu8mg5v7(See igl\sort_triangles.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_sort_vectors_ccw = R"igl_Qu8mg5v7(See igl\sort_vectors_ccw.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_sparse = R"igl_Qu8mg5v7(See igl\sparse.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_speye = R"igl_Qu8mg5v7(See igl\speye.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_stdin_to_temp = R"igl_Qu8mg5v7(See igl\stdin_to_temp.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_STR = R"igl_Qu8mg5v7(See igl\STR.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_sum = R"igl_Qu8mg5v7(See igl\sum.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_svd3x3 = R"igl_Qu8mg5v7(See igl\svd3x3.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_svd3x3_avx = R"igl_Qu8mg5v7(See igl\svd3x3_avx.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_svd3x3_sse = R"igl_Qu8mg5v7(See igl\svd3x3_sse.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_Timer = R"igl_Qu8mg5v7(See igl\Timer.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_trackball = R"igl_Qu8mg5v7(See igl\trackball.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_transpose_blocks = R"igl_Qu8mg5v7(See igl\transpose_blocks.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_triangles_from_strip = R"igl_Qu8mg5v7(See igl\triangles_from_strip.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_triangle_fan = R"igl_Qu8mg5v7(See igl\triangle_fan.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_triangle_triangle_adjacency = R"igl_Qu8mg5v7(See igl\triangle_triangle_adjacency.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_two_axis_valuator_fixed_up = R"igl_Qu8mg5v7(See igl\two_axis_valuator_fixed_up.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_uniformly_sample_two_manifold = R"igl_Qu8mg5v7(See igl\uniformly_sample_two_manifold.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_unique = R"igl_Qu8mg5v7(See igl\unique.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_unique_edge_map = R"igl_Qu8mg5v7(See igl\unique_edge_map.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_unique_simplices = R"igl_Qu8mg5v7(See igl\unique_simplices.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_unproject = R"igl_Qu8mg5v7(See igl\unproject.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_upsample = R"igl_Qu8mg5v7(See igl\upsample.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_vector_area_matrix = R"igl_Qu8mg5v7(See igl\vector_area_matrix.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_verbose = R"igl_Qu8mg5v7(See igl\verbose.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_vertex_triangle_adjacency = R"igl_Qu8mg5v7(See igl\vertex_triangle_adjacency.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_Viewport = R"igl_Qu8mg5v7(See igl\Viewport.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_volume = R"igl_Qu8mg5v7(See igl\volume.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_WindingNumberAABB = R"igl_Qu8mg5v7(See igl\WindingNumberAABB.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_WindingNumberMethod = R"igl_Qu8mg5v7(See igl\WindingNumberMethod.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_WindingNumberTree = R"igl_Qu8mg5v7(See igl\WindingNumberTree.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_winding_number = R"igl_Qu8mg5v7(See igl\winding_number.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_writeDMAT = R"igl_Qu8mg5v7(See igl\writeDMAT.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_writeMESH = R"igl_Qu8mg5v7(See igl\writeMESH.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_writeOBJ = R"igl_Qu8mg5v7(See igl\writeOBJ.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_writeOFF = R"igl_Qu8mg5v7(See igl\writeOFF.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_writePLY = R"igl_Qu8mg5v7(See igl\writePLY.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_writeSTL = R"igl_Qu8mg5v7(See igl\writeSTL.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_writeTGF = R"igl_Qu8mg5v7(See igl\writeTGF.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_writeWRL = R"igl_Qu8mg5v7(See igl\writeWRL.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_write_triangle_mesh = R"igl_Qu8mg5v7(See igl\write_triangle_mesh.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_ZERO = R"igl_Qu8mg5v7(See igl\ZERO.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_anttweakbar_cocoa_key_to_anttweakbar_key = R"igl_Qu8mg5v7(See igl\anttweakbar\cocoa_key_to_anttweakbar_key.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_anttweakbar_ReAntTweakBar = R"igl_Qu8mg5v7(See igl\anttweakbar\ReAntTweakBar.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_bbw_bbw = R"igl_Qu8mg5v7(See igl\bbw\bbw.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_boolean_from_cork_mesh = R"igl_Qu8mg5v7(See igl\boolean\from_cork_mesh.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_boolean_MeshBooleanType = R"igl_Qu8mg5v7(See igl\boolean\MeshBooleanType.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_boolean_mesh_boolean = R"igl_Qu8mg5v7(See igl\boolean\mesh_boolean.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_boolean_mesh_boolean_cork = R"igl_Qu8mg5v7(See igl\boolean\mesh_boolean_cork.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_boolean_to_cork_mesh = R"igl_Qu8mg5v7(See igl\boolean\to_cork_mesh.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_cgal_complex_to_mesh = R"igl_Qu8mg5v7(See igl\cgal\complex_to_mesh.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_cgal_intersect_other = R"igl_Qu8mg5v7(See igl\cgal\intersect_other.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_cgal_mesh_to_cgal_triangle_list = R"igl_Qu8mg5v7(See igl\cgal\mesh_to_cgal_triangle_list.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_cgal_mesh_to_polyhedron = R"igl_Qu8mg5v7(See igl\cgal\mesh_to_polyhedron.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_cgal_order_facets_around_edges = R"igl_Qu8mg5v7(See igl\cgal\order_facets_around_edges.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_cgal_outer_hull = R"igl_Qu8mg5v7(See igl\cgal\outer_hull.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_cgal_peel_outer_hull_layers = R"igl_Qu8mg5v7(See igl\cgal\peel_outer_hull_layers.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_cgal_point_mesh_squared_distance = R"igl_Qu8mg5v7(See igl\cgal\point_mesh_squared_distance.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_cgal_polyhedron_to_mesh = R"igl_Qu8mg5v7(See igl\cgal\polyhedron_to_mesh.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_cgal_RemeshSelfIntersectionsParam = R"igl_Qu8mg5v7(See igl\cgal\RemeshSelfIntersectionsParam.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_cgal_remesh_self_intersections = R"igl_Qu8mg5v7(See igl\cgal\remesh_self_intersections.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_cgal_SelfIntersectMesh = R"igl_Qu8mg5v7(See igl\cgal\SelfIntersectMesh.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_cgal_signed_distance_isosurface = R"igl_Qu8mg5v7(See igl\cgal\signed_distance_isosurface.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_comiso_frame_field = R"igl_Qu8mg5v7(See igl\comiso\frame_field.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_comiso_miq = R"igl_Qu8mg5v7(See igl\comiso\miq.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_comiso_nrosy = R"igl_Qu8mg5v7(See igl\comiso\nrosy.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_embree_ambient_occlusion = R"igl_Qu8mg5v7(See igl\embree\ambient_occlusion.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_embree_bone_heat = R"igl_Qu8mg5v7(See igl\embree\bone_heat.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_embree_bone_visible = R"igl_Qu8mg5v7(See igl\embree\bone_visible.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_embree_EmbreeIntersector = R"igl_Qu8mg5v7(See igl\embree\EmbreeIntersector.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_embree_Embree_convenience = R"igl_Qu8mg5v7(See igl\embree\Embree_convenience.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_embree_Hit = R"igl_Qu8mg5v7(See igl\embree\Hit.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_embree_line_mesh_intersection = R"igl_Qu8mg5v7(See igl\embree\line_mesh_intersection.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_embree_reorient_facets_raycast = R"igl_Qu8mg5v7(See igl\embree\reorient_facets_raycast.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_embree_unproject_in_mesh = R"igl_Qu8mg5v7(See igl\embree\unproject_in_mesh.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_embree_unproject_onto_mesh = R"igl_Qu8mg5v7(See igl\embree\unproject_onto_mesh.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_lim_lim = R"igl_Qu8mg5v7(See igl\lim\lim.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_matlab_matlabinterface = R"igl_Qu8mg5v7(See igl\matlab\matlabinterface.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_matlab_MatlabWorkspace = R"igl_Qu8mg5v7(See igl\matlab\MatlabWorkspace.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_matlab_mexErrMsgTxt = R"igl_Qu8mg5v7(See igl\matlab\mexErrMsgTxt.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_matlab_MexStream = R"igl_Qu8mg5v7(See igl\matlab\MexStream.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_matlab_parse_rhs = R"igl_Qu8mg5v7(See igl\matlab\parse_rhs.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_matlab_prepare_lhs = R"igl_Qu8mg5v7(See igl\matlab\prepare_lhs.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_mosek_mosek_guarded = R"igl_Qu8mg5v7(See igl\mosek\mosek_guarded.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_mosek_mosek_linprog = R"igl_Qu8mg5v7(See igl\mosek\mosek_linprog.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_mosek_mosek_quadprog = R"igl_Qu8mg5v7(See igl\mosek\mosek_quadprog.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl_compile_and_link_program = R"igl_Qu8mg5v7(See igl\opengl\compile_and_link_program.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl_compile_shader = R"igl_Qu8mg5v7(See igl\opengl\compile_shader.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl_create_index_vbo = R"igl_Qu8mg5v7(See igl\opengl\create_index_vbo.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl_create_mesh_vbo = R"igl_Qu8mg5v7(See igl\opengl\create_mesh_vbo.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl_create_shader_program = R"igl_Qu8mg5v7(See igl\opengl\create_shader_program.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl_create_vector_vbo = R"igl_Qu8mg5v7(See igl\opengl\create_vector_vbo.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl_destroy_shader_program = R"igl_Qu8mg5v7(See igl\opengl\destroy_shader_program.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl_gl_type_size = R"igl_Qu8mg5v7(See igl\opengl\gl_type_size.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl_init_render_to_texture = R"igl_Qu8mg5v7(See igl\opengl\init_render_to_texture.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl_load_shader = R"igl_Qu8mg5v7(See igl\opengl\load_shader.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl_OpenGL_convenience = R"igl_Qu8mg5v7(See igl\opengl\OpenGL_convenience.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl_print_program_info_log = R"igl_Qu8mg5v7(See igl\opengl\print_program_info_log.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl_print_shader_info_log = R"igl_Qu8mg5v7(See igl\opengl\print_shader_info_log.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl_render_to_tga = R"igl_Qu8mg5v7(See igl\opengl\render_to_tga.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl_report_gl_error = R"igl_Qu8mg5v7(See igl\opengl\report_gl_error.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl_texture_from_tga = R"igl_Qu8mg5v7(See igl\opengl\texture_from_tga.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl_tga = R"igl_Qu8mg5v7(See igl\opengl\tga.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl_uniform_type_to_string = R"igl_Qu8mg5v7(See igl\opengl\uniform_type_to_string.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl2_draw_beach_ball = R"igl_Qu8mg5v7(See igl\opengl2\draw_beach_ball.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl2_draw_floor = R"igl_Qu8mg5v7(See igl\opengl2\draw_floor.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl2_draw_mesh = R"igl_Qu8mg5v7(See igl\opengl2\draw_mesh.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl2_draw_point = R"igl_Qu8mg5v7(See igl\opengl2\draw_point.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl2_draw_rectangular_marquee = R"igl_Qu8mg5v7(See igl\opengl2\draw_rectangular_marquee.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl2_draw_skeleton_3d = R"igl_Qu8mg5v7(See igl\opengl2\draw_skeleton_3d.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl2_draw_skeleton_vector_graphics = R"igl_Qu8mg5v7(See igl\opengl2\draw_skeleton_vector_graphics.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl2_flare_textures = R"igl_Qu8mg5v7(See igl\opengl2\flare_textures.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl2_lens_flare = R"igl_Qu8mg5v7(See igl\opengl2\lens_flare.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl2_model_proj_viewport = R"igl_Qu8mg5v7(See igl\opengl2\model_proj_viewport.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl2_MouseController = R"igl_Qu8mg5v7(See igl\opengl2\MouseController.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl2_print_gl_get = R"igl_Qu8mg5v7(See igl\opengl2\print_gl_get.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl2_project = R"igl_Qu8mg5v7(See igl\opengl2\project.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl2_right_axis = R"igl_Qu8mg5v7(See igl\opengl2\right_axis.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl2_RotateWidget = R"igl_Qu8mg5v7(See igl\opengl2\RotateWidget.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl2_shine_textures = R"igl_Qu8mg5v7(See igl\opengl2\shine_textures.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl2_sort_triangles = R"igl_Qu8mg5v7(See igl\opengl2\sort_triangles.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl2_unproject = R"igl_Qu8mg5v7(See igl\opengl2\unproject.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl2_unproject_to_zero_plane = R"igl_Qu8mg5v7(See igl\opengl2\unproject_to_zero_plane.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl2_up_axis = R"igl_Qu8mg5v7(See igl\opengl2\up_axis.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_opengl2_view_axis = R"igl_Qu8mg5v7(See igl\opengl2\view_axis.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_png_render_to_png = R"igl_Qu8mg5v7(See igl\png\render_to_png.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_png_render_to_png_async = R"igl_Qu8mg5v7(See igl\png\render_to_png_async.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_png_texture_from_file = R"igl_Qu8mg5v7(See igl\png\texture_from_file.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_png_texture_from_png = R"igl_Qu8mg5v7(See igl\png\texture_from_png.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_tetgen_cdt = R"igl_Qu8mg5v7(See igl\tetgen\cdt.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_tetgen_mesh_to_tetgenio = R"igl_Qu8mg5v7(See igl\tetgen\mesh_to_tetgenio.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_tetgen_mesh_with_skeleton = R"igl_Qu8mg5v7(See igl\tetgen\mesh_with_skeleton.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_tetgen_read_into_tetgenio = R"igl_Qu8mg5v7(See igl\tetgen\read_into_tetgenio.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_tetgen_tetgenio_to_tetmesh = R"igl_Qu8mg5v7(See igl\tetgen\tetgenio_to_tetmesh.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_tetgen_tetrahedralize = R"igl_Qu8mg5v7(See igl\tetgen\tetrahedralize.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_triangle_triangulate = R"igl_Qu8mg5v7(See igl\triangle\triangulate.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_viewer_OpenGL_shader = R"igl_Qu8mg5v7(See igl\viewer\OpenGL_shader.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_viewer_OpenGL_state = R"igl_Qu8mg5v7(See igl\viewer\OpenGL_state.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_viewer_TextRenderer = R"igl_Qu8mg5v7(See igl\viewer\TextRenderer.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_viewer_TextRenderer_fonts = R"igl_Qu8mg5v7(See igl\viewer\TextRenderer_fonts.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_viewer_Viewer = R"igl_Qu8mg5v7(See igl\viewer\Viewer.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_viewer_ViewerCore = R"igl_Qu8mg5v7(See igl\viewer\ViewerCore.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_viewer_ViewerData = R"igl_Qu8mg5v7(See igl\viewer\ViewerData.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_viewer_ViewerPlugin = R"igl_Qu8mg5v7(See igl\viewer\ViewerPlugin.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_xml_ReAntTweakBarXMLSerialization = R"igl_Qu8mg5v7(See igl\xml\ReAntTweakBarXMLSerialization.h for the documentation.)igl_Qu8mg5v7";
+const char *__doc_igl_xml_serialize_xml = R"igl_Qu8mg5v7(See igl\xml\serialize_xml.h for the documentation.)igl_Qu8mg5v7";

+ 409 - 0
python/py_doc.h

@@ -0,0 +1,409 @@
+extern const char *__doc_igl_AABB;
+extern const char *__doc_igl_active_set;
+extern const char *__doc_igl_adjacency_list;
+extern const char *__doc_igl_adjacency_matrix;
+extern const char *__doc_igl_all_edges;
+extern const char *__doc_igl_all_pairs_distances;
+extern const char *__doc_igl_angle_bound_frame_fields;
+extern const char *__doc_igl_angular_distance;
+extern const char *__doc_igl_any_of;
+extern const char *__doc_igl_arap;
+extern const char *__doc_igl_ARAPEnergyType;
+extern const char *__doc_igl_arap_dof;
+extern const char *__doc_igl_arap_linear_block;
+extern const char *__doc_igl_arap_rhs;
+extern const char *__doc_igl_average_onto_faces;
+extern const char *__doc_igl_average_onto_vertices;
+extern const char *__doc_igl_avg_edge_length;
+extern const char *__doc_igl_axis_angle_to_quat;
+extern const char *__doc_igl_barycenter;
+extern const char *__doc_igl_barycentric_coordinates;
+extern const char *__doc_igl_barycentric_to_global;
+extern const char *__doc_igl_basename;
+extern const char *__doc_igl_bfs_orient;
+extern const char *__doc_igl_biharmonic_coordinates;
+extern const char *__doc_igl_bone_parents;
+extern const char *__doc_igl_boundary_conditions;
+extern const char *__doc_igl_boundary_facets;
+extern const char *__doc_igl_boundary_loop;
+extern const char *__doc_igl_bounding_box;
+extern const char *__doc_igl_bounding_box_diagonal;
+extern const char *__doc_igl_Camera;
+extern const char *__doc_igl_canonical_quaternions;
+extern const char *__doc_igl_cat;
+extern const char *__doc_igl_ceil;
+extern const char *__doc_igl_centroid;
+extern const char *__doc_igl_circulation;
+extern const char *__doc_igl_collapse_edge;
+extern const char *__doc_igl_collapse_small_triangles;
+extern const char *__doc_igl_colon;
+extern const char *__doc_igl_columnize;
+extern const char *__doc_igl_column_to_quats;
+extern const char *__doc_igl_comb_cross_field;
+extern const char *__doc_igl_comb_frame_field;
+extern const char *__doc_igl_comb_line_field;
+extern const char *__doc_igl_components;
+extern const char *__doc_igl_compute_frame_field_bisectors;
+extern const char *__doc_igl_ConjugateFFSolverData;
+extern const char *__doc_igl_conjugate_frame_fields;
+extern const char *__doc_igl_cotmatrix;
+extern const char *__doc_igl_cotmatrix_entries;
+extern const char *__doc_igl_covariance_scatter_matrix;
+extern const char *__doc_igl_cross;
+extern const char *__doc_igl_cross_field_missmatch;
+extern const char *__doc_igl_crouzeix_raviart_massmatrix;
+extern const char *__doc_igl_cumsum;
+extern const char *__doc_igl_cut_mesh;
+extern const char *__doc_igl_cut_mesh_from_singularities;
+extern const char *__doc_igl_C_STR;
+extern const char *__doc_igl_dated_copy;
+extern const char *__doc_igl_decimate;
+extern const char *__doc_igl_deform_skeleton;
+extern const char *__doc_igl_deprecated;
+extern const char *__doc_igl_diag;
+extern const char *__doc_igl_dihedral_angles;
+extern const char *__doc_igl_dijkstra;
+extern const char *__doc_igl_directed_edge_orientations;
+extern const char *__doc_igl_directed_edge_parents;
+extern const char *__doc_igl_dirname;
+extern const char *__doc_igl_dot;
+extern const char *__doc_igl_dot_row;
+extern const char *__doc_igl_doublearea;
+extern const char *__doc_igl_dqs;
+extern const char *__doc_igl_edges;
+extern const char *__doc_igl_edge_collapse_is_valid;
+extern const char *__doc_igl_edge_flaps;
+extern const char *__doc_igl_edge_lengths;
+extern const char *__doc_igl_edge_topology;
+extern const char *__doc_igl_eigs;
+extern const char *__doc_igl_EPS;
+extern const char *__doc_igl_example_fun;
+extern const char *__doc_igl_exterior_edges;
+extern const char *__doc_igl_faces_first;
+extern const char *__doc_igl_facet_components;
+extern const char *__doc_igl_face_areas;
+extern const char *__doc_igl_face_occurrences;
+extern const char *__doc_igl_false_barycentric_subdivision;
+extern const char *__doc_igl_field_local_global_conversions;
+extern const char *__doc_igl_file_contents_as_string;
+extern const char *__doc_igl_file_dialog_open;
+extern const char *__doc_igl_file_dialog_save;
+extern const char *__doc_igl_file_exists;
+extern const char *__doc_igl_find;
+extern const char *__doc_igl_find_cross_field_singularities;
+extern const char *__doc_igl_fit_plane;
+extern const char *__doc_igl_fit_rigid;
+extern const char *__doc_igl_fit_rotations;
+extern const char *__doc_igl_floor;
+extern const char *__doc_igl_forward_kinematics;
+extern const char *__doc_igl_frame_field_deformer;
+extern const char *__doc_igl_frame_to_cross_field;
+extern const char *__doc_igl_frustum;
+extern const char *__doc_igl_full;
+extern const char *__doc_igl_gaussian_curvature;
+extern const char *__doc_igl_get_seconds;
+extern const char *__doc_igl_get_seconds_hires;
+extern const char *__doc_igl_grad;
+extern const char *__doc_igl_group_sum_matrix;
+extern const char *__doc_igl_HalfEdgeIterator;
+extern const char *__doc_igl_harmonic;
+extern const char *__doc_igl_harwell_boeing;
+extern const char *__doc_igl_histc;
+extern const char *__doc_igl_hsv_to_rgb;
+extern const char *__doc_igl_igl_inline;
+extern const char *__doc_igl_IndexComparison;
+extern const char *__doc_igl_integrable_polyvector_fields;
+extern const char *__doc_igl_internal_angles;
+extern const char *__doc_igl_intersect;
+extern const char *__doc_igl_invert_diag;
+extern const char *__doc_igl_in_element;
+extern const char *__doc_igl_is_border_vertex;
+extern const char *__doc_igl_is_boundary_edge;
+extern const char *__doc_igl_is_dir;
+extern const char *__doc_igl_is_edge_manifold;
+extern const char *__doc_igl_is_file;
+extern const char *__doc_igl_is_irregular_vertex;
+extern const char *__doc_igl_is_planar;
+extern const char *__doc_igl_is_readable;
+extern const char *__doc_igl_is_sparse;
+extern const char *__doc_igl_is_symmetric;
+extern const char *__doc_igl_is_vertex_manifold;
+extern const char *__doc_igl_is_writable;
+extern const char *__doc_igl_jet;
+extern const char *__doc_igl_launch_medit;
+extern const char *__doc_igl_lbs_matrix;
+extern const char *__doc_igl_limit_faces;
+extern const char *__doc_igl_line_field_missmatch;
+extern const char *__doc_igl_line_segment_in_rectangle;
+extern const char *__doc_igl_linprog;
+extern const char *__doc_igl_list_to_matrix;
+extern const char *__doc_igl_local_basis;
+extern const char *__doc_igl_look_at;
+extern const char *__doc_igl_lscm;
+extern const char *__doc_igl_lu_lagrange;
+extern const char *__doc_igl_map_vertices_to_circle;
+extern const char *__doc_igl_marching_cubes;
+extern const char *__doc_igl_massmatrix;
+extern const char *__doc_igl_material_colors;
+extern const char *__doc_igl_matlab_format;
+extern const char *__doc_igl_matrix_to_list;
+extern const char *__doc_igl_mat_max;
+extern const char *__doc_igl_mat_min;
+extern const char *__doc_igl_mat_to_quat;
+extern const char *__doc_igl_max_size;
+extern const char *__doc_igl_median;
+extern const char *__doc_igl_min_quad_dense;
+extern const char *__doc_igl_min_quad_with_fixed;
+extern const char *__doc_igl_min_size;
+extern const char *__doc_igl_mod;
+extern const char *__doc_igl_mode;
+extern const char *__doc_igl_mvc;
+extern const char *__doc_igl_nchoosek;
+extern const char *__doc_igl_next_filename;
+extern const char *__doc_igl_normalize_quat;
+extern const char *__doc_igl_normalize_row_lengths;
+extern const char *__doc_igl_normalize_row_sums;
+extern const char *__doc_igl_NormalType;
+extern const char *__doc_igl_normal_derivative;
+extern const char *__doc_igl_null;
+extern const char *__doc_igl_n_polyvector;
+extern const char *__doc_igl_n_polyvector_general;
+extern const char *__doc_igl_ONE;
+extern const char *__doc_igl_on_boundary;
+extern const char *__doc_igl_orientable_patches;
+extern const char *__doc_igl_orient_outward;
+extern const char *__doc_igl_orth;
+extern const char *__doc_igl_ortho;
+extern const char *__doc_igl_outer_facet;
+extern const char *__doc_igl_parallel_transport_angles;
+extern const char *__doc_igl_partition;
+extern const char *__doc_igl_parula;
+extern const char *__doc_igl_pathinfo;
+extern const char *__doc_igl_path_to_executable;
+extern const char *__doc_igl_per_corner_normals;
+extern const char *__doc_igl_per_edge_normals;
+extern const char *__doc_igl_per_face_normals;
+extern const char *__doc_igl_per_vertex_attribute_smoothing;
+extern const char *__doc_igl_per_vertex_normals;
+extern const char *__doc_igl_PI;
+extern const char *__doc_igl_planarize_quad_mesh;
+extern const char *__doc_igl_ply;
+extern const char *__doc_igl_point_in_circle;
+extern const char *__doc_igl_point_in_poly;
+extern const char *__doc_igl_point_mesh_squared_distance;
+extern const char *__doc_igl_polar_dec;
+extern const char *__doc_igl_polar_svd;
+extern const char *__doc_igl_polar_svd3x3;
+extern const char *__doc_igl_polygon_mesh_to_triangle_mesh;
+extern const char *__doc_igl_polyroots;
+extern const char *__doc_igl_polyvector_field_comb_from_matchings_and_cuts;
+extern const char *__doc_igl_polyvector_field_cut_mesh_with_singularities;
+extern const char *__doc_igl_polyvector_field_matchings;
+extern const char *__doc_igl_polyvector_field_poisson_reconstruction;
+extern const char *__doc_igl_polyvector_field_singularities_from_matchings;
+extern const char *__doc_igl_principal_curvature;
+extern const char *__doc_igl_print_ijv;
+extern const char *__doc_igl_print_vector;
+extern const char *__doc_igl_procrustes;
+extern const char *__doc_igl_project;
+extern const char *__doc_igl_project_isometrically_to_plane;
+extern const char *__doc_igl_project_to_line;
+extern const char *__doc_igl_project_to_line_segment;
+extern const char *__doc_igl_pseudonormal_test;
+extern const char *__doc_igl_quad_planarity;
+extern const char *__doc_igl_quats_to_column;
+extern const char *__doc_igl_quat_conjugate;
+extern const char *__doc_igl_quat_mult;
+extern const char *__doc_igl_quat_to_axis_angle;
+extern const char *__doc_igl_quat_to_mat;
+extern const char *__doc_igl_random_dir;
+extern const char *__doc_igl_random_points_on_mesh;
+extern const char *__doc_igl_random_quaternion;
+extern const char *__doc_igl_randperm;
+extern const char *__doc_igl_ray_sphere_intersect;
+extern const char *__doc_igl_readCSV;
+extern const char *__doc_igl_readDMAT;
+extern const char *__doc_igl_readMESH;
+extern const char *__doc_igl_readNODE;
+extern const char *__doc_igl_readOBJ;
+extern const char *__doc_igl_readOFF;
+extern const char *__doc_igl_readPLY;
+extern const char *__doc_igl_readSTL;
+extern const char *__doc_igl_readTGF;
+extern const char *__doc_igl_readWRL;
+extern const char *__doc_igl_read_triangle_mesh;
+extern const char *__doc_igl_REDRUM;
+extern const char *__doc_igl_remove_duplicates;
+extern const char *__doc_igl_remove_duplicate_vertices;
+extern const char *__doc_igl_remove_unreferenced;
+extern const char *__doc_igl_reorder;
+extern const char *__doc_igl_repdiag;
+extern const char *__doc_igl_repmat;
+extern const char *__doc_igl_rgb_to_hsv;
+extern const char *__doc_igl_rotate_by_quat;
+extern const char *__doc_igl_rotate_vectors;
+extern const char *__doc_igl_rotation_matrix_from_directions;
+extern const char *__doc_igl_round;
+extern const char *__doc_igl_rows_to_matrix;
+extern const char *__doc_igl_sample_edges;
+extern const char *__doc_igl_serialize;
+extern const char *__doc_igl_setdiff;
+extern const char *__doc_igl_signed_distance;
+extern const char *__doc_igl_slice;
+extern const char *__doc_igl_slice_into;
+extern const char *__doc_igl_slice_mask;
+extern const char *__doc_igl_slice_tets;
+extern const char *__doc_igl_snap_points;
+extern const char *__doc_igl_snap_to_canonical_view_quat;
+extern const char *__doc_igl_snap_to_fixed_up;
+extern const char *__doc_igl_SolverStatus;
+extern const char *__doc_igl_sort;
+extern const char *__doc_igl_SortableRow;
+extern const char *__doc_igl_sortrows;
+extern const char *__doc_igl_sort_angles;
+extern const char *__doc_igl_sort_triangles;
+extern const char *__doc_igl_sort_vectors_ccw;
+extern const char *__doc_igl_sparse;
+extern const char *__doc_igl_speye;
+extern const char *__doc_igl_stdin_to_temp;
+extern const char *__doc_igl_STR;
+extern const char *__doc_igl_sum;
+extern const char *__doc_igl_svd3x3;
+extern const char *__doc_igl_svd3x3_avx;
+extern const char *__doc_igl_svd3x3_sse;
+extern const char *__doc_igl_Timer;
+extern const char *__doc_igl_trackball;
+extern const char *__doc_igl_transpose_blocks;
+extern const char *__doc_igl_triangles_from_strip;
+extern const char *__doc_igl_triangle_fan;
+extern const char *__doc_igl_triangle_triangle_adjacency;
+extern const char *__doc_igl_two_axis_valuator_fixed_up;
+extern const char *__doc_igl_uniformly_sample_two_manifold;
+extern const char *__doc_igl_unique;
+extern const char *__doc_igl_unique_edge_map;
+extern const char *__doc_igl_unique_simplices;
+extern const char *__doc_igl_unproject;
+extern const char *__doc_igl_upsample;
+extern const char *__doc_igl_vector_area_matrix;
+extern const char *__doc_igl_verbose;
+extern const char *__doc_igl_vertex_triangle_adjacency;
+extern const char *__doc_igl_Viewport;
+extern const char *__doc_igl_volume;
+extern const char *__doc_igl_WindingNumberAABB;
+extern const char *__doc_igl_WindingNumberMethod;
+extern const char *__doc_igl_WindingNumberTree;
+extern const char *__doc_igl_winding_number;
+extern const char *__doc_igl_writeDMAT;
+extern const char *__doc_igl_writeMESH;
+extern const char *__doc_igl_writeOBJ;
+extern const char *__doc_igl_writeOFF;
+extern const char *__doc_igl_writePLY;
+extern const char *__doc_igl_writeSTL;
+extern const char *__doc_igl_writeTGF;
+extern const char *__doc_igl_writeWRL;
+extern const char *__doc_igl_write_triangle_mesh;
+extern const char *__doc_igl_ZERO;
+extern const char *__doc_igl_anttweakbar_cocoa_key_to_anttweakbar_key;
+extern const char *__doc_igl_anttweakbar_ReAntTweakBar;
+extern const char *__doc_igl_bbw_bbw;
+extern const char *__doc_igl_boolean_from_cork_mesh;
+extern const char *__doc_igl_boolean_MeshBooleanType;
+extern const char *__doc_igl_boolean_mesh_boolean;
+extern const char *__doc_igl_boolean_mesh_boolean_cork;
+extern const char *__doc_igl_boolean_to_cork_mesh;
+extern const char *__doc_igl_cgal_complex_to_mesh;
+extern const char *__doc_igl_cgal_intersect_other;
+extern const char *__doc_igl_cgal_mesh_to_cgal_triangle_list;
+extern const char *__doc_igl_cgal_mesh_to_polyhedron;
+extern const char *__doc_igl_cgal_order_facets_around_edges;
+extern const char *__doc_igl_cgal_outer_hull;
+extern const char *__doc_igl_cgal_peel_outer_hull_layers;
+extern const char *__doc_igl_cgal_point_mesh_squared_distance;
+extern const char *__doc_igl_cgal_polyhedron_to_mesh;
+extern const char *__doc_igl_cgal_RemeshSelfIntersectionsParam;
+extern const char *__doc_igl_cgal_remesh_self_intersections;
+extern const char *__doc_igl_cgal_SelfIntersectMesh;
+extern const char *__doc_igl_cgal_signed_distance_isosurface;
+extern const char *__doc_igl_comiso_frame_field;
+extern const char *__doc_igl_comiso_miq;
+extern const char *__doc_igl_comiso_nrosy;
+extern const char *__doc_igl_embree_ambient_occlusion;
+extern const char *__doc_igl_embree_bone_heat;
+extern const char *__doc_igl_embree_bone_visible;
+extern const char *__doc_igl_embree_EmbreeIntersector;
+extern const char *__doc_igl_embree_Embree_convenience;
+extern const char *__doc_igl_embree_Hit;
+extern const char *__doc_igl_embree_line_mesh_intersection;
+extern const char *__doc_igl_embree_reorient_facets_raycast;
+extern const char *__doc_igl_embree_unproject_in_mesh;
+extern const char *__doc_igl_embree_unproject_onto_mesh;
+extern const char *__doc_igl_lim_lim;
+extern const char *__doc_igl_matlab_matlabinterface;
+extern const char *__doc_igl_matlab_MatlabWorkspace;
+extern const char *__doc_igl_matlab_mexErrMsgTxt;
+extern const char *__doc_igl_matlab_MexStream;
+extern const char *__doc_igl_matlab_parse_rhs;
+extern const char *__doc_igl_matlab_prepare_lhs;
+extern const char *__doc_igl_mosek_mosek_guarded;
+extern const char *__doc_igl_mosek_mosek_linprog;
+extern const char *__doc_igl_mosek_mosek_quadprog;
+extern const char *__doc_igl_opengl_compile_and_link_program;
+extern const char *__doc_igl_opengl_compile_shader;
+extern const char *__doc_igl_opengl_create_index_vbo;
+extern const char *__doc_igl_opengl_create_mesh_vbo;
+extern const char *__doc_igl_opengl_create_shader_program;
+extern const char *__doc_igl_opengl_create_vector_vbo;
+extern const char *__doc_igl_opengl_destroy_shader_program;
+extern const char *__doc_igl_opengl_gl_type_size;
+extern const char *__doc_igl_opengl_init_render_to_texture;
+extern const char *__doc_igl_opengl_load_shader;
+extern const char *__doc_igl_opengl_OpenGL_convenience;
+extern const char *__doc_igl_opengl_print_program_info_log;
+extern const char *__doc_igl_opengl_print_shader_info_log;
+extern const char *__doc_igl_opengl_render_to_tga;
+extern const char *__doc_igl_opengl_report_gl_error;
+extern const char *__doc_igl_opengl_texture_from_tga;
+extern const char *__doc_igl_opengl_tga;
+extern const char *__doc_igl_opengl_uniform_type_to_string;
+extern const char *__doc_igl_opengl2_draw_beach_ball;
+extern const char *__doc_igl_opengl2_draw_floor;
+extern const char *__doc_igl_opengl2_draw_mesh;
+extern const char *__doc_igl_opengl2_draw_point;
+extern const char *__doc_igl_opengl2_draw_rectangular_marquee;
+extern const char *__doc_igl_opengl2_draw_skeleton_3d;
+extern const char *__doc_igl_opengl2_draw_skeleton_vector_graphics;
+extern const char *__doc_igl_opengl2_flare_textures;
+extern const char *__doc_igl_opengl2_lens_flare;
+extern const char *__doc_igl_opengl2_model_proj_viewport;
+extern const char *__doc_igl_opengl2_MouseController;
+extern const char *__doc_igl_opengl2_print_gl_get;
+extern const char *__doc_igl_opengl2_project;
+extern const char *__doc_igl_opengl2_right_axis;
+extern const char *__doc_igl_opengl2_RotateWidget;
+extern const char *__doc_igl_opengl2_shine_textures;
+extern const char *__doc_igl_opengl2_sort_triangles;
+extern const char *__doc_igl_opengl2_unproject;
+extern const char *__doc_igl_opengl2_unproject_to_zero_plane;
+extern const char *__doc_igl_opengl2_up_axis;
+extern const char *__doc_igl_opengl2_view_axis;
+extern const char *__doc_igl_png_render_to_png;
+extern const char *__doc_igl_png_render_to_png_async;
+extern const char *__doc_igl_png_texture_from_file;
+extern const char *__doc_igl_png_texture_from_png;
+extern const char *__doc_igl_tetgen_cdt;
+extern const char *__doc_igl_tetgen_mesh_to_tetgenio;
+extern const char *__doc_igl_tetgen_mesh_with_skeleton;
+extern const char *__doc_igl_tetgen_read_into_tetgenio;
+extern const char *__doc_igl_tetgen_tetgenio_to_tetmesh;
+extern const char *__doc_igl_tetgen_tetrahedralize;
+extern const char *__doc_igl_triangle_triangulate;
+extern const char *__doc_igl_viewer_OpenGL_shader;
+extern const char *__doc_igl_viewer_OpenGL_state;
+extern const char *__doc_igl_viewer_TextRenderer;
+extern const char *__doc_igl_viewer_TextRenderer_fonts;
+extern const char *__doc_igl_viewer_Viewer;
+extern const char *__doc_igl_viewer_ViewerCore;
+extern const char *__doc_igl_viewer_ViewerData;
+extern const char *__doc_igl_viewer_ViewerPlugin;
+extern const char *__doc_igl_xml_ReAntTweakBarXMLSerialization;
+extern const char *__doc_igl_xml_serialize_xml;

+ 69 - 0
python/py_igl.cpp

@@ -0,0 +1,69 @@
+#include <Eigen/Dense>
+
+#include "python.h"
+
+#include <igl/readOFF.h>
+#include <igl/writeOBJ.h>
+#include <igl/per_face_normals.h>
+#include <igl/per_corner_normals.h>
+#include <igl/per_vertex_normals.h>
+#include <igl/gaussian_curvature.h>
+#include <igl/jet.h>
+#include <igl/read_triangle_mesh.h>
+#include <igl/cotmatrix.h>
+#include <igl/massmatrix.h>
+#include <igl/invert_diag.h>
+#include <igl/principal_curvature.h>
+#include <igl/parula.h>
+#include <igl/readDMAT.h>
+#include <igl/grad.h>
+#include <igl/avg_edge_length.h>
+#include <igl/barycenter.h>
+#include <igl/doublearea.h>
+#include <igl/floor.h>
+#include <igl/slice.h>
+#include <igl/slice_into.h>
+#include <igl/sortrows.h>
+#include <igl/colon.h>
+#include <igl/boundary_facets.h>
+#include <igl/unique.h>
+#include <igl/setdiff.h>
+#include <igl/min_quad_with_fixed.h>
+#include <igl/SolverStatus.h>
+#include <igl/active_set.h>
+#include <igl/eigs.h>
+
+void python_export_igl(py::module &m)
+{
+#include "py_igl/py_readOFF.cpp"
+#include "py_igl/py_writeOBJ.cpp"
+#include "py_igl/py_per_face_normals.cpp"
+#include "py_igl/py_per_corner_normals.cpp"
+#include "py_igl/py_per_vertex_normals.cpp"
+#include "py_igl/py_gaussian_curvature.cpp"
+#include "py_igl/py_jet.cpp"
+#include "py_igl/py_read_triangle_mesh.cpp"
+#include "py_igl/py_cotmatrix.cpp"
+#include "py_igl/py_massmatrix.cpp"
+#include "py_igl/py_invert_diag.cpp"
+#include "py_igl/py_principal_curvature.cpp"
+#include "py_igl/py_parula.cpp"
+#include "py_igl/py_readDMAT.cpp"
+#include "py_igl/py_grad.cpp"
+#include "py_igl/py_avg_edge_length.cpp"
+#include "py_igl/py_barycenter.cpp"
+#include "py_igl/py_doublearea.cpp"
+#include "py_igl/py_floor.cpp"
+#include "py_igl/py_slice.cpp"
+#include "py_igl/py_slice_into.cpp"
+#include "py_igl/py_sortrows.cpp"
+#include "py_igl/py_colon.cpp"
+#include "py_igl/py_boundary_facets.cpp"
+#include "py_igl/py_unique.cpp"
+#include "py_igl/py_setdiff.cpp"
+#include "py_igl/py_min_quad_with_fixed.cpp"
+#include "py_igl/py_SolverStatus.cpp"
+#include "py_igl/py_active_set.cpp"
+#include "py_igl/py_eigs.cpp"
+
+}

+ 6 - 0
python/py_igl/py_SolverStatus.cpp

@@ -0,0 +1,6 @@
+py::enum_<igl::SolverStatus>(m, "SolverStatus")
+    .value("SOLVER_STATUS_CONVERGED", igl::SOLVER_STATUS_CONVERGED)
+    .value("SOLVER_STATUS_MAX_ITER", igl::SOLVER_STATUS_MAX_ITER)
+    .value("SOLVER_STATUS_ERROR", igl::SOLVER_STATUS_ERROR)
+    .value("NUM_SOLVER_STATUSES", igl::NUM_SOLVER_STATUSES)
+    .export_values();

+ 48 - 0
python/py_igl/py_active_set.cpp

@@ -0,0 +1,48 @@
+// Wrap the params struct
+py::class_<igl::active_set_params > active_set_params(m, "active_set_params");
+
+active_set_params
+.def("__init__", [](igl::active_set_params &m)
+{
+    new (&m) igl::active_set_params();
+    m.Auu_pd = false;
+    m.max_iter = 100;
+    m.inactive_threshold = igl::DOUBLE_EPS;
+    m.constraint_threshold = igl::DOUBLE_EPS;
+    m.solution_diff_threshold = igl::DOUBLE_EPS;
+})
+.def_readwrite("Auu_pd", &igl::active_set_params::Auu_pd)
+.def_readwrite("max_iter", &igl::active_set_params::max_iter)
+.def_readwrite("inactive_threshold", &igl::active_set_params::inactive_threshold)
+.def_readwrite("constraint_threshold", &igl::active_set_params::constraint_threshold)
+.def_readwrite("solution_diff_threshold", &igl::active_set_params::solution_diff_threshold)
+.def_readwrite("Auu_pd", &igl::active_set_params::Auu_pd)
+;
+
+m.def("active_set", []
+(
+  const Eigen::SparseMatrix<double>& A,
+  const Eigen::MatrixXd& B,
+  const Eigen::MatrixXi& known,
+  const Eigen::MatrixXd& Y,
+  const Eigen::SparseMatrix<double>& Aeq,
+  const Eigen::MatrixXd& Beq,
+  const Eigen::SparseMatrix<double>& Aieq,
+  const Eigen::MatrixXd& Bieq,
+  const Eigen::MatrixXd& lx,
+  const Eigen::MatrixXd& ux,
+  const igl::active_set_params& params,
+  Eigen::MatrixXd& Z
+)
+{
+  assert_is_VectorX("B",B);
+  assert_is_VectorX("known",known);
+  assert_is_VectorX("Y",Y);
+  assert_is_VectorX("Beq",Beq);
+  assert_is_VectorX("Bieq",Bieq);
+  assert_is_VectorX("Z",Z);
+
+  return igl::active_set(A,B,known,Y,Aeq,Eigen::VectorXd(Beq),Aieq,Bieq,lx,ux,params,Z);
+}, __doc_igl_active_set,
+py::arg("A"), py::arg("B"), py::arg("known"), py::arg("Y"), py::arg("Aeq"), py::arg("Beq")
+, py::arg("Aieq"), py::arg("Bieq"), py::arg("lx"), py::arg("ux"), py::arg("params"), py::arg("Z"));

+ 9 - 0
python/py_igl/py_avg_edge_length.cpp

@@ -0,0 +1,9 @@
+m.def("avg_edge_length", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F
+)
+{
+  return igl::avg_edge_length(V,F);
+}, __doc_igl_avg_edge_length,
+py::arg("V"), py::arg("F"));

+ 10 - 0
python/py_igl/py_barycenter.cpp

@@ -0,0 +1,10 @@
+m.def("barycenter", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F,
+  Eigen::MatrixXd& BC
+)
+{
+  return igl::barycenter(V,F,BC);
+}, __doc_igl_barycenter,
+py::arg("V"), py::arg("F"), py::arg("BC"));

+ 30 - 0
python/py_igl/py_boundary_facets.cpp

@@ -0,0 +1,30 @@
+m.def("boundary_facets", []
+(
+  const std::vector<std::vector<int> > & T,
+  std::vector<std::vector<int> > & F
+)
+{
+  return igl::boundary_facets(T,F);
+}, __doc_igl_boundary_facets,
+py::arg("T"), py::arg("F"));
+
+m.def("boundary_facets", []
+(
+  const Eigen::MatrixXi& T,
+  Eigen::MatrixXi& F
+)
+{
+  return igl::boundary_facets(T,F);
+}, __doc_igl_boundary_facets,
+py::arg("T"), py::arg("F"));
+
+m.def("boundary_facets", []
+(
+  const Eigen::MatrixXi& T
+)
+{
+  Eigen::MatrixXi F;
+  igl::boundary_facets(T,F);
+  return F;
+}, __doc_igl_boundary_facets,
+py::arg("T"));

+ 74 - 0
python/py_igl/py_colon.cpp

@@ -0,0 +1,74 @@
+m.def("colon", []
+(
+  const double low,
+  const double step,
+  const double high,
+  Eigen::MatrixXd& I
+)
+{
+  Eigen::Matrix<double,Eigen::Dynamic,1> temp;
+  igl::colon<double>(low,step,high,temp);
+  I = temp;
+}, __doc_igl_colon,
+py::arg("low"), py::arg("step"), py::arg("high"), py::arg("I"));
+
+m.def("colon", []
+(
+  const double low,
+  const double high,
+  Eigen::MatrixXd& I
+)
+{
+  Eigen::Matrix<double,Eigen::Dynamic,1> temp;
+  igl::colon<double>(low,high,temp);
+  I = temp;
+}, __doc_igl_colon,
+py::arg("low"), py::arg("high"), py::arg("I"));
+
+m.def("colon", []
+(
+  const double& low,
+  const double& high
+)
+{
+  return Eigen::MatrixXd(igl::colon<double>(low,high));
+}, __doc_igl_colon,
+py::arg("low"), py::arg("high"));
+
+
+m.def("coloni", []
+(
+  const int low,
+  const int step,
+  const int high,
+  Eigen::MatrixXi& I
+)
+{
+  Eigen::Matrix<int,Eigen::Dynamic,1> temp;
+  igl::colon<int>(low,step,high,temp);
+  I = temp;
+}, __doc_igl_colon,
+py::arg("low"), py::arg("step"), py::arg("high"), py::arg("I"));
+
+m.def("coloni", []
+(
+  const int low,
+  const int high,
+  Eigen::MatrixXi& I
+)
+{
+  Eigen::Matrix<int,Eigen::Dynamic,1> temp;
+  igl::colon<int>(low,high,temp);
+  I = temp;
+}, __doc_igl_colon,
+py::arg("low"), py::arg("high"), py::arg("I"));
+
+m.def("coloni", []
+(
+  const int& low,
+  const int& high
+)
+{
+  return Eigen::MatrixXi(igl::colon<int>(low,high));
+}, __doc_igl_colon,
+py::arg("low"), py::arg("high"));

+ 10 - 0
python/py_igl/py_cotmatrix.cpp

@@ -0,0 +1,10 @@
+m.def("cotmatrix", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F,
+  Eigen::SparseMatrix<double>& L
+)
+{
+  return igl::cotmatrix(V,F,L);
+}, __doc_igl_cotmatrix,
+py::arg("V"), py::arg("F"), py::arg("L"));

+ 54 - 0
python/py_igl/py_doublearea.cpp

@@ -0,0 +1,54 @@
+m.def("doublearea", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F,
+  Eigen::MatrixXd& dblA
+)
+{
+  return igl::doublearea(V,F,dblA);
+}, __doc_igl_doublearea,
+py::arg("V"), py::arg("F"), py::arg("dblA"));
+
+m.def("doublearea", []
+(
+  const Eigen::MatrixXd& A,
+  const Eigen::MatrixXd& B,
+  const Eigen::MatrixXd& C,
+  Eigen::MatrixXd& D
+)
+{
+  return igl::doublearea(A,B,C,D);
+}, __doc_igl_doublearea,
+py::arg("A"), py::arg("B"), py::arg("C"), py::arg("D"));
+
+m.def("doublearea_single", []
+(
+  const Eigen::MatrixXd& A,
+  const Eigen::MatrixXd& B,
+  const Eigen::MatrixXd& C
+)
+{
+  return igl::doublearea_single(A,B,C);
+}, __doc_igl_doublearea,
+py::arg("A"), py::arg("B"), py::arg("C"));
+
+m.def("doublearea", []
+(
+  const Eigen::MatrixXd& l,
+  Eigen::MatrixXd& dblA
+)
+{
+  return igl::doublearea(l,dblA);
+}, __doc_igl_doublearea,
+py::arg("l"), py::arg("dblA"));
+
+m.def("doublearea_quad", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F,
+  Eigen::MatrixXd& dblA
+)
+{
+  return igl::doublearea_quad(V,F,dblA);
+}, __doc_igl_doublearea,
+py::arg("V"), py::arg("F"), py::arg("dblA"));

+ 22 - 0
python/py_igl/py_eigs.cpp

@@ -0,0 +1,22 @@
+py::enum_<igl::EigsType>(m, "EigsType")
+    .value("EIGS_TYPE_SM", igl::EIGS_TYPE_SM)
+    .value("EIGS_TYPE_LM", igl::EIGS_TYPE_LM)
+    .value("NUM_EIGS_TYPES", igl::NUM_EIGS_TYPES)
+    .export_values();
+
+m.def("eigs", []
+(
+  const Eigen::SparseMatrix<double>& A,
+  const Eigen::SparseMatrix<double>& B,
+  const size_t k,
+  const igl::EigsType type,
+  Eigen::MatrixXd& sU,
+  Eigen::MatrixXd& sS
+)
+{
+  Eigen::VectorXd sSt;
+  bool ret = igl::eigs(A,B,k,type,sU,sSt);
+  sS = sSt;
+  return ret;
+}, __doc_igl_eigs,
+py::arg("A"), py::arg("B"), py::arg("k"), py::arg("type"), py::arg("sU"), py::arg("sS"));

+ 9 - 0
python/py_igl/py_floor.cpp

@@ -0,0 +1,9 @@
+m.def("floor", []
+(
+  const Eigen::MatrixXd& X,
+  Eigen::MatrixXi& Y
+)
+{
+  return igl::floor(X,Y);
+}, __doc_igl_floor,
+py::arg("X"), py::arg("Y"));

+ 10 - 0
python/py_igl/py_gaussian_curvature.cpp

@@ -0,0 +1,10 @@
+m.def("gaussian_curvature", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F,
+  Eigen::MatrixXd& K
+)
+{
+  return igl::gaussian_curvature(V,F,K);
+}, __doc_igl_gaussian_curvature,
+py::arg("V"), py::arg("F"), py::arg("K"));

+ 10 - 0
python/py_igl/py_grad.cpp

@@ -0,0 +1,10 @@
+m.def("grad", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F,
+  Eigen::SparseMatrix<double>& G
+)
+{
+  return igl::grad(V,F,G);
+}, __doc_igl_grad,
+py::arg("V"), py::arg("F"), py::arg("G"));

+ 9 - 0
python/py_igl/py_invert_diag.cpp

@@ -0,0 +1,9 @@
+m.def("invert_diag", []
+(
+  const Eigen::SparseMatrix<double>& X,
+  Eigen::SparseMatrix<double>& Y
+)
+{
+  return igl::invert_diag(X,Y);
+}, __doc_igl_invert_diag,
+py::arg("X"), py::arg("Y"));

+ 24 - 0
python/py_igl/py_jet.cpp

@@ -0,0 +1,24 @@
+m.def("jet", []
+(
+  const Eigen::MatrixXd& Z,
+  const bool normalize,
+  Eigen::MatrixXd& C
+)
+{
+  assert_is_VectorX("Z",Z);
+  return igl::jet(Z,normalize,C);
+}, __doc_igl_jet,
+py::arg("Z"), py::arg("normalize"), py::arg("C"));
+
+m.def("jet", []
+(
+  const Eigen::MatrixXd& Z,
+  const double min_Z,
+  const double max_Z,
+  Eigen::MatrixXd& C
+)
+{
+  assert_is_VectorX("Z",Z);
+  return igl::jet(Z,min_Z,max_Z,C);
+}, __doc_igl_jet,
+py::arg("Z"), py::arg("min_Z"), py::arg("max_Z"), py::arg("C"));

+ 19 - 0
python/py_igl/py_massmatrix.cpp

@@ -0,0 +1,19 @@
+py::enum_<igl::MassMatrixType>(m, "MassMatrixType")
+    .value("MASSMATRIX_TYPE_BARYCENTRIC", igl::MASSMATRIX_TYPE_BARYCENTRIC)
+    .value("MASSMATRIX_TYPE_VORONOI", igl::MASSMATRIX_TYPE_VORONOI)
+    .value("MASSMATRIX_TYPE_FULL", igl::MASSMATRIX_TYPE_FULL)
+    .value("MASSMATRIX_TYPE_DEFAULT", igl::MASSMATRIX_TYPE_DEFAULT)
+    .value("NUM_MASSMATRIX_TYPE", igl::NUM_MASSMATRIX_TYPE)
+    .export_values();
+
+m.def("massmatrix", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F,
+  const igl::MassMatrixType type,
+  Eigen::SparseMatrix<double>& M
+)
+{
+  return igl::massmatrix(V,F,type,M);
+}, __doc_igl_massmatrix,
+py::arg("V"), py::arg("F"), py::arg("type"), py::arg("M"));

+ 73 - 0
python/py_igl/py_min_quad_with_fixed.cpp

@@ -0,0 +1,73 @@
+
+// Wrap the data class, no properties are exposed since it is not necessary
+py::class_<igl::min_quad_with_fixed_data<double> > min_quad_with_fixed_data(m, "min_quad_with_fixed_data");
+
+min_quad_with_fixed_data
+.def(py::init<>());
+
+m.def("min_quad_with_fixed_precompute", []
+(
+  const Eigen::SparseMatrix<double>& A,
+  const Eigen::MatrixXi& known,
+  const Eigen::SparseMatrix<double>& Aeq,
+  const bool pd,
+  igl::min_quad_with_fixed_data<double> & data
+)
+{
+  assert_is_VectorX("known",known);
+  return igl::min_quad_with_fixed_precompute(A,known,Aeq,pd,data);
+}, __doc_igl_min_quad_with_fixed,
+py::arg("A"), py::arg("known"), py::arg("Aeq"), py::arg("pd"), py::arg("data"));
+
+m.def("min_quad_with_fixed_solve", []
+(
+  const igl::min_quad_with_fixed_data<double> & data,
+  const Eigen::MatrixXd& B,
+  const Eigen::MatrixXd& Y,
+  const Eigen::MatrixXd & Beq,
+  Eigen::MatrixXd& Z,
+  Eigen::MatrixXd& sol
+)
+{
+  assert_is_VectorX("B",B);
+  assert_is_VectorX("Y",Y);
+  assert_is_VectorX("Beq",Beq);
+  return igl::min_quad_with_fixed_solve(data,B,Y,Beq,Z,sol);
+}, __doc_igl_min_quad_with_fixed,
+py::arg("data"), py::arg("B"), py::arg("Y"), py::arg("Beq"), py::arg("Z"), py::arg("sol"));
+
+m.def("min_quad_with_fixed_solve", []
+(
+  const igl::min_quad_with_fixed_data<double> & data,
+  const Eigen::MatrixXd& B,
+  const Eigen::MatrixXd& Y,
+  const Eigen::MatrixXd & Beq,
+  Eigen::MatrixXd& Z
+)
+{
+  assert_is_VectorX("B",B);
+  assert_is_VectorX("Y",Y);
+  assert_is_VectorX("Beq",Beq);
+  return igl::min_quad_with_fixed_solve(data,B,Y,Beq,Z);
+}, __doc_igl_min_quad_with_fixed,
+py::arg("data"), py::arg("B"), py::arg("Y"), py::arg("Beq"), py::arg("Z"));
+
+m.def("min_quad_with_fixed", []
+(
+  const Eigen::SparseMatrix<double>& A,
+  const Eigen::MatrixXd& B,
+  const Eigen::MatrixXi& known,
+  const Eigen::MatrixXd& Y,
+  const Eigen::SparseMatrix<double>& Aeq,
+  const Eigen::MatrixXd& Beq,
+  const bool pd,
+  Eigen::MatrixXd& Z
+)
+{
+  assert_is_VectorX("B",B);
+  assert_is_VectorX("known",known);
+  assert_is_VectorX("Y",Y);
+  assert_is_VectorX("Beq",Beq);
+  return igl::min_quad_with_fixed(A,B,known,Y,Aeq,Beq,pd,Z);
+}, __doc_igl_min_quad_with_fixed,
+py::arg("A"), py::arg("B"), py::arg("known"), py::arg("Y"), py::arg("Aeq"), py::arg("Beq"), py::arg("pd"), py::arg("Z"));

+ 24 - 0
python/py_igl/py_parula.cpp

@@ -0,0 +1,24 @@
+m.def("parula", []
+(
+  const Eigen::MatrixXd& Z,
+  const bool normalize,
+  Eigen::MatrixXd& C
+)
+{
+  assert_is_VectorX("Z",Z);
+  return igl::parula(Z,normalize,C);
+}, __doc_igl_parula,
+py::arg("Z"), py::arg("normalize"), py::arg("C"));
+
+m.def("parula", []
+(
+  const Eigen::MatrixXd& Z,
+  const double min_Z,
+  const double max_Z,
+  Eigen::MatrixXd& C
+)
+{
+  assert_is_VectorX("Z",Z);
+  return igl::parula(Z,min_Z,max_Z,C);
+}, __doc_igl_parula,
+py::arg("Z"), py::arg("min_Z"), py::arg("max_Z"), py::arg("C"));

+ 38 - 0
python/py_igl/py_per_corner_normals.cpp

@@ -0,0 +1,38 @@
+m.def("per_corner_normals", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F,
+  const double corner_threshold,
+  Eigen::MatrixXd& CN
+)
+{
+  return igl::per_corner_normals(V,F,corner_threshold,CN);
+}, __doc_igl_per_corner_normals,
+py::arg("V"), py::arg("F"), py::arg("corner_threshold"), py::arg("CN"));
+
+m.def("per_corner_normals", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F,
+  const Eigen::MatrixXd& FN,
+  const double corner_threshold,
+  Eigen::MatrixXd& CN
+)
+{
+  return igl::per_corner_normals(V,F,FN,corner_threshold,CN);
+}, __doc_igl_per_corner_normals,
+py::arg("V"), py::arg("F"), py::arg("FN"), py::arg("corner_threshold"), py::arg("CN"));
+
+m.def("per_corner_normals", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F,
+  const Eigen::MatrixXd& FN,
+  const double corner_threshold,
+  const std::vector<std::vector<int> >& VF,
+  Eigen::MatrixXd& CN
+)
+{
+  return igl::per_corner_normals(V,F,FN,VF,corner_threshold,CN);
+}, __doc_igl_per_corner_normals,
+py::arg("V"), py::arg("F"), py::arg("FN"), py::arg("corner_threshold"), py::arg("VF"), py::arg("CN"));

+ 34 - 0
python/py_igl/py_per_face_normals.cpp

@@ -0,0 +1,34 @@
+m.def("per_face_normals", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F,
+  const Eigen::MatrixXd& Z,
+  Eigen::MatrixXd& N
+)
+{
+  assert_is_VectorX("Z",Z);
+  return igl::per_face_normals(V,F,Z,N);
+}, __doc_igl_per_face_normals,
+py::arg("V"), py::arg("F"), py::arg("Z"), py::arg("N"));
+
+m.def("per_face_normals", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F,
+  Eigen::MatrixXd& N
+)
+{
+  return igl::per_face_normals(V,F,N);
+}, __doc_igl_per_face_normals,
+py::arg("V"), py::arg("F"), py::arg("N"));
+
+m.def("per_face_normals_stable", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F,
+  Eigen::MatrixXd& N
+)
+{
+  return igl::per_face_normals_stable(V,F,N);
+}, __doc_igl_per_face_normals,
+py::arg("V"), py::arg("F"), py::arg("N"));

+ 55 - 0
python/py_igl/py_per_vertex_normals.cpp

@@ -0,0 +1,55 @@
+py::enum_<igl::PerVertexNormalsWeightingType>(m, "PerVertexNormalsWeightingType")
+    .value("PER_VERTEX_NORMALS_WEIGHTING_TYPE_UNIFORM", igl::PER_VERTEX_NORMALS_WEIGHTING_TYPE_UNIFORM)
+    .value("PER_VERTEX_NORMALS_WEIGHTING_TYPE_AREA", igl::PER_VERTEX_NORMALS_WEIGHTING_TYPE_AREA)
+    .value("PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE", igl::PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE)
+    .value("PER_VERTEX_NORMALS_WEIGHTING_TYPE_DEFAULT", igl::PER_VERTEX_NORMALS_WEIGHTING_TYPE_DEFAULT)
+    .value("NUM_PER_VERTEX_NORMALS_WEIGHTING_TYPE", igl::NUM_PER_VERTEX_NORMALS_WEIGHTING_TYPE)
+    .export_values();
+
+m.def("per_vertex_normals", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F,
+  const igl::PerVertexNormalsWeightingType weighting,
+  Eigen::MatrixXd& N
+)
+{
+  return igl::per_vertex_normals(V,F,weighting,N);
+}, __doc_igl_per_vertex_normals,
+py::arg("V"), py::arg("F"), py::arg("weighting"), py::arg("N"));
+
+m.def("per_vertex_normals", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F,
+  Eigen::MatrixXd& N
+)
+{
+  return igl::per_vertex_normals(V,F,N);
+}, __doc_igl_per_vertex_normals,
+py::arg("V"), py::arg("F"), py::arg("N"));
+
+m.def("per_vertex_normals", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F,
+  const igl::PerVertexNormalsWeightingType weighting,
+  const Eigen::MatrixXd& FN,
+  Eigen::MatrixXd& N
+)
+{
+  return igl::per_vertex_normals(V,F,weighting,FN,N);
+}, __doc_igl_per_vertex_normals,
+py::arg("V"), py::arg("F"), py::arg("weighting"), py::arg("FN"), py::arg("N"));
+
+m.def("per_vertex_normals", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F,
+  const Eigen::MatrixXd& FN,
+  Eigen::MatrixXd& N
+)
+{
+  return igl::per_vertex_normals(V,F,FN,N);
+}, __doc_igl_per_vertex_normals,
+py::arg("V"), py::arg("F"), py::arg("FN"), py::arg("N"));

+ 15 - 0
python/py_igl/py_principal_curvature.cpp

@@ -0,0 +1,15 @@
+m.def("principal_curvature", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F,
+  Eigen::MatrixXd& PD1,
+  Eigen::MatrixXd& PD2,
+  Eigen::MatrixXd& PV1,
+  Eigen::MatrixXd& PV2,
+  unsigned radius,
+  bool useKring
+)
+{
+  return igl::principal_curvature(V,F,PD1,PD2,PV1,PV2,radius,useKring);
+}, __doc_igl_principal_curvature,
+py::arg("V"), py::arg("F"), py::arg("PD1"), py::arg("PD2"), py::arg("PV1"), py::arg("PV2"), py::arg("radius") = 5, py::arg("useKring") = true);

+ 10 - 0
python/py_igl/py_readDMAT.cpp

@@ -0,0 +1,10 @@
+
+m.def("readDMAT", []
+(
+  const std::string str,
+  Eigen::MatrixXd& W
+)
+{
+  return igl::readDMAT(str,W);
+}, __doc_igl_readDMAT,
+py::arg("str"), py::arg("W"));

+ 22 - 0
python/py_igl/py_readOFF.cpp

@@ -0,0 +1,22 @@
+m.def("readOFF", []
+(
+  const std::string str,
+  Eigen::MatrixXd& V,
+  Eigen::MatrixXi& F
+)
+{
+  return igl::readOFF(str,V,F);
+}, __doc_igl_readOFF,
+py::arg("str"), py::arg("V"), py::arg("F"));
+
+m.def("readOFF", []
+(
+  const std::string str,
+  Eigen::MatrixXd& V,
+  Eigen::MatrixXi& F,
+  Eigen::MatrixXd& N
+)
+{
+  return igl::readOFF(str,V,F,N);
+}, __doc_igl_readOFF,
+py::arg("str"), py::arg("V"), py::arg("F"), py::arg("N"));

+ 36 - 0
python/py_igl/py_read_triangle_mesh.cpp

@@ -0,0 +1,36 @@
+m.def("read_triangle_mesh", []
+(
+  const std::string str,
+  std::vector<std::vector<double> >& V,
+  std::vector<std::vector<int> >& F
+)
+{
+  return igl::read_triangle_mesh(str,V,F);
+}, __doc_igl_read_triangle_mesh,
+py::arg("str"), py::arg("V"), py::arg("F"));
+
+m.def("read_triangle_mesh", []
+(
+  const std::string str,
+  Eigen::MatrixXd& V,
+  Eigen::MatrixXi& F
+)
+{
+  return igl::read_triangle_mesh(str,V,F);
+}, __doc_igl_read_triangle_mesh,
+py::arg("str"), py::arg("V"), py::arg("F"));
+
+m.def("read_triangle_mesh", []
+(
+  const std::string str,
+  Eigen::MatrixXd& V,
+  Eigen::MatrixXi& F,
+  std::string & dir,
+  std::string & base,
+  std::string & ext,
+  std::string & name
+)
+{
+  return igl::read_triangle_mesh(str,V,F,dir,base,ext,name);
+}, __doc_igl_read_triangle_mesh,
+py::arg("str"), py::arg("V"), py::arg("F"), py::arg("dir"), py::arg("base"), py::arg("ext"), py::arg("name"));

+ 11 - 0
python/py_igl/py_setdiff.cpp

@@ -0,0 +1,11 @@
+m.def("setdiff", []
+(
+  const Eigen::MatrixXi& A,
+  const Eigen::MatrixXi& B,
+  Eigen::MatrixXi& C,
+  Eigen::MatrixXi& IA
+)
+{
+  return igl::setdiff(A,B,C,IA);
+}, __doc_igl_setdiff,
+py::arg("A"), py::arg("B"), py::arg("C"), py::arg("IA"));

+ 155 - 0
python/py_igl/py_slice.cpp

@@ -0,0 +1,155 @@
+// // Double
+//
+m.def("slice", []
+(
+  const Eigen::SparseMatrix<double>& X,
+  const Eigen::MatrixXi& R,
+  const Eigen::MatrixXi& C,
+  Eigen::SparseMatrix<double>& Y
+)
+{
+  assert_is_VectorX("R",R);
+  assert_is_VectorX("C",C);
+  return igl::slice(X,R,C,Y);
+}, __doc_igl_slice,
+py::arg("X"), py::arg("R"), py::arg("C"), py::arg("Y"));
+
+m.def("slice", []
+(
+  const Eigen::SparseMatrix<double>& X,
+  const Eigen::MatrixXi& R,
+  const int& dim,
+  Eigen::SparseMatrix<double>& Y
+)
+{
+  assert_is_VectorX("R",R);
+  return igl::slice(X,R,dim,Y);
+}, __doc_igl_slice,
+py::arg("X"), py::arg("R"), py::arg("dim"), py::arg("Y"));
+
+m.def("slice", []
+(
+  const Eigen::MatrixXd& X,
+  const Eigen::MatrixXi& R,
+  const Eigen::MatrixXi& C,
+  Eigen::MatrixXd& Y
+)
+{
+  assert_is_VectorX("R",R);
+  assert_is_VectorX("C",C);
+  return igl::slice(X,R,C,Y);
+}, __doc_igl_slice,
+py::arg("X"), py::arg("R"), py::arg("C"), py::arg("Y"));
+
+m.def("slice", []
+(
+  const Eigen::MatrixXd& X,
+  const Eigen::MatrixXi& R,
+  Eigen::MatrixXd& Y
+)
+{
+  assert_is_VectorX("R",R);
+  return igl::slice(X,R,Y);
+}, __doc_igl_slice,
+py::arg("X"), py::arg("R"), py::arg("Y"));
+
+m.def("slice", []
+(
+  const Eigen::MatrixXd& X,
+  const Eigen::MatrixXi& R
+)
+{
+  assert_is_VectorX("R",R);
+  return igl::slice(X,R);
+}, __doc_igl_slice,
+py::arg("X"), py::arg("A"));
+
+m.def("slice", []
+(
+  const Eigen::MatrixXd& X,
+  const Eigen::MatrixXi& R,
+  const int& dim
+)
+{
+  assert_is_VectorX("R",R);
+  return igl::slice(X,R,dim);
+}, __doc_igl_slice,
+py::arg("X"), py::arg("R"), py::arg("dim"));
+
+// int
+m.def("slice", []
+(
+  const Eigen::SparseMatrix<int>& X,
+  const Eigen::MatrixXi& R,
+  const Eigen::MatrixXi& C,
+  Eigen::SparseMatrix<int>& Y
+)
+{
+  assert_is_VectorX("R",R);
+  assert_is_VectorX("C",C);
+  return igl::slice(X,R,C,Y);
+}, __doc_igl_slice,
+py::arg("X"), py::arg("R"), py::arg("C"), py::arg("Y"));
+
+m.def("slice", []
+(
+  const Eigen::SparseMatrix<int>& X,
+  const Eigen::MatrixXi& R,
+  const int& dim,
+  Eigen::SparseMatrix<int>& Y
+)
+{
+  assert_is_VectorX("R",R);
+  return igl::slice(X,R,dim,Y);
+}, __doc_igl_slice,
+py::arg("X"), py::arg("R"), py::arg("dim"), py::arg("Y"));
+
+m.def("slice", []
+(
+  const Eigen::MatrixXi& X,
+  const Eigen::MatrixXi& R,
+  const Eigen::MatrixXi& C,
+  Eigen::MatrixXi& Y
+)
+{
+  assert_is_VectorX("R",R);
+  assert_is_VectorX("C",C);
+  return igl::slice(X,R,C,Y);
+}, __doc_igl_slice,
+py::arg("X"), py::arg("R"), py::arg("C"), py::arg("Y"));
+
+
+m.def("slice", []
+(
+  const Eigen::MatrixXi& X,
+  const Eigen::MatrixXi& R,
+  Eigen::MatrixXi& Y
+)
+{
+  assert_is_VectorX("R",R);
+  return igl::slice(X,R,Y);
+}, __doc_igl_slice,
+py::arg("X"), py::arg("R"), py::arg("Y"));
+
+m.def("slice", []
+(
+  const Eigen::MatrixXi& X,
+  const Eigen::MatrixXi& R
+)
+{
+  assert_is_VectorX("R",R);
+  return igl::slice(X,R);
+}, __doc_igl_slice,
+py::arg("X"), py::arg("R"));
+
+m.def("slice", []
+(
+  const Eigen::MatrixXi& X,
+  const Eigen::MatrixXi& R,
+  const int& dim
+)
+{
+  assert_is_VectorX("R",R);
+  return igl::slice(X,R,dim);
+}, __doc_igl_slice,
+py::arg("X"), py::arg("R"), py::arg("dim"));

+ 107 - 0
python/py_igl/py_slice_into.cpp

@@ -0,0 +1,107 @@
+m.def("slice_into", []
+(
+  const Eigen::SparseMatrix<double>& X,
+  const Eigen::MatrixXi& R,
+  const Eigen::MatrixXi& C,
+  Eigen::SparseMatrix<double>& Y
+)
+{
+  assert_is_VectorX("R",R);
+  assert_is_VectorX("C",C);
+  return igl::slice_into(X,R,C,Y);
+}, __doc_igl_slice_into,
+py::arg("X"), py::arg("R"), py::arg("C"), py::arg("Y"));
+
+m.def("slice_into", []
+(
+  const Eigen::MatrixXd& X,
+  const Eigen::MatrixXi& R,
+  const Eigen::MatrixXi& C,
+  Eigen::MatrixXd& Y
+)
+{
+  assert_is_VectorX("R",R);
+  assert_is_VectorX("C",C);
+  return igl::slice_into(X,R,C,Y);
+}, __doc_igl_slice_into,
+py::arg("X"), py::arg("R"), py::arg("C"), py::arg("Y"));
+
+m.def("slice_into", []
+(
+  const Eigen::MatrixXd& X,
+  const Eigen::MatrixXi& R,
+  const int& dim,
+  Eigen::MatrixXd& Y
+)
+{
+  assert_is_VectorX("R",R);
+  return igl::slice_into(X,R,dim,Y);
+}, __doc_igl_slice_into,
+py::arg("X"), py::arg("R"), py::arg("dim"), py::arg("Y"));
+
+m.def("slice_into", []
+(
+  const Eigen::MatrixXd& X,
+  const Eigen::MatrixXi& R,
+  Eigen::MatrixXd& Y
+)
+{
+  assert_is_VectorX("R",R);
+  return igl::slice_into(X,R,Y);
+}, __doc_igl_slice_into,
+py::arg("X"), py::arg("R"), py::arg("Y"));
+
+// int
+
+m.def("slice_into", []
+(
+  const Eigen::SparseMatrix<int>& X,
+  const Eigen::MatrixXi& R,
+  const Eigen::MatrixXi& C,
+  Eigen::SparseMatrix<int>& Y
+)
+{
+  assert_is_VectorX("R",R);
+  assert_is_VectorX("C",C);
+  return igl::slice_into(X,R,C,Y);
+}, __doc_igl_slice_into,
+py::arg("X"), py::arg("R"), py::arg("C"), py::arg("Y"));
+
+m.def("slice_into", []
+(
+  const Eigen::MatrixXi& X,
+  const Eigen::MatrixXi& R,
+  const Eigen::MatrixXi& C,
+  Eigen::MatrixXi& Y
+)
+{
+  assert_is_VectorX("R",R);
+  assert_is_VectorX("C",C);
+  return igl::slice_into(X,R,C,Y);
+}, __doc_igl_slice_into,
+py::arg("X"), py::arg("R"), py::arg("C"), py::arg("Y"));
+
+m.def("slice_into", []
+(
+  const Eigen::MatrixXi& X,
+  const Eigen::MatrixXi& R,
+  const int& dim,
+  Eigen::MatrixXi& Y
+)
+{
+  assert_is_VectorX("R",R);
+  return igl::slice_into(X,R,dim,Y);
+}, __doc_igl_slice_into,
+py::arg("X"), py::arg("R"), py::arg("dim"), py::arg("Y"));
+
+m.def("slice_into", []
+(
+  const Eigen::MatrixXi& X,
+  const Eigen::MatrixXi& R,
+  Eigen::MatrixXi& Y
+)
+{
+  assert_is_VectorX("R",R);
+  return igl::slice_into(X,R,Y);
+}, __doc_igl_slice_into,
+py::arg("X"), py::arg("R"), py::arg("Y"));

+ 23 - 0
python/py_igl/py_sortrows.cpp

@@ -0,0 +1,23 @@
+m.def("sortrows", []
+(
+  const Eigen::MatrixXd& X,
+  const bool ascending,
+  Eigen::MatrixXd& Y,
+  Eigen::MatrixXi& I
+)
+{
+  return igl::sortrows(X,ascending,Y,I);
+}, __doc_igl_sortrows,
+py::arg("X"), py::arg("ascending"), py::arg("Y"), py::arg("I"));
+
+m.def("sortrows", []
+(
+  const Eigen::MatrixXi& X,
+  const bool ascending,
+  Eigen::MatrixXi& Y,
+  Eigen::MatrixXi& I
+)
+{
+  return igl::sortrows(X,ascending,Y,I);
+}, __doc_igl_sortrows,
+py::arg("X"), py::arg("ascending"), py::arg("Y"), py::arg("I"));

+ 116 - 0
python/py_igl/py_unique.cpp

@@ -0,0 +1,116 @@
+m.def("unique", []
+(
+  const std::vector<double> & A,
+  std::vector<double> & C,
+  std::vector<size_t> & IA,
+  std::vector<size_t> & IC
+)
+{
+  return igl::unique(A,C,IA,IC);
+}, __doc_igl_unique,
+py::arg("A"), py::arg("C"), py::arg("IA"), py::arg("IC"));
+
+m.def("unique", []
+(
+  const std::vector<double> & A,
+  std::vector<double> & C
+)
+{
+  return igl::unique(A,C);
+}, __doc_igl_unique,
+py::arg("A"), py::arg("C"));
+
+m.def("unique", []
+(
+  const Eigen::MatrixXd& A,
+  Eigen::MatrixXd& C,
+  Eigen::MatrixXi& IA,
+  Eigen::MatrixXi& IC
+)
+{
+  return igl::unique(A,C,IA,IC);
+}, __doc_igl_unique,
+py::arg("A"), py::arg("C"), py::arg("IA"), py::arg("IC"));
+
+m.def("unique", []
+(
+  const Eigen::MatrixXd& A,
+  Eigen::MatrixXd& C
+)
+{
+  return igl::unique(A,C);
+}, __doc_igl_unique,
+py::arg("A"), py::arg("C"));
+
+m.def("unique_rows", []
+(
+  const Eigen::MatrixXd& A,
+  Eigen::MatrixXd& C,
+  Eigen::MatrixXi& IA,
+  Eigen::MatrixXi& IC
+)
+{
+  return igl::unique_rows(A,C,IA,IC);
+}, __doc_igl_unique,
+py::arg("A"), py::arg("C"), py::arg("IA"), py::arg("IC"));
+
+
+
+// int
+
+
+m.def("unique", []
+(
+  const std::vector<int> & A,
+  std::vector<int> & C,
+  std::vector<size_t> & IA,
+  std::vector<size_t> & IC
+)
+{
+  return igl::unique(A,C,IA,IC);
+}, __doc_igl_unique,
+py::arg("A"), py::arg("C"), py::arg("IA"), py::arg("IC"));
+
+m.def("unique", []
+(
+  const std::vector<int> & A,
+  std::vector<int> & C
+)
+{
+  return igl::unique(A,C);
+}, __doc_igl_unique,
+py::arg("A"), py::arg("C"));
+
+m.def("unique", []
+(
+  const Eigen::MatrixXi& A,
+  Eigen::MatrixXi& C,
+  Eigen::MatrixXi& IA,
+  Eigen::MatrixXi& IC
+)
+{
+  return igl::unique(A,C,IA,IC);
+}, __doc_igl_unique,
+py::arg("A"), py::arg("C"), py::arg("IA"), py::arg("IC"));
+
+m.def("unique", []
+(
+  const Eigen::MatrixXi& A,
+  Eigen::MatrixXi& C
+)
+{
+  return igl::unique(A,C);
+}, __doc_igl_unique,
+py::arg("A"), py::arg("C"));
+
+m.def("unique_rows", []
+(
+  const Eigen::MatrixXi& A,
+  Eigen::MatrixXi& C,
+  Eigen::MatrixXi& IA,
+  Eigen::MatrixXi& IC
+)
+{
+  return igl::unique_rows(A,C,IA,IC);
+}, __doc_igl_unique,
+py::arg("A"), py::arg("C"), py::arg("IA"), py::arg("IC"));

+ 25 - 0
python/py_igl/py_writeOBJ.cpp

@@ -0,0 +1,25 @@
+m.def("writeOBJ", []
+(
+  const std::string str,
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F,
+  const Eigen::MatrixXd& CN,
+  const Eigen::MatrixXi& FN,
+  const Eigen::MatrixXd& TC,
+  const Eigen::MatrixXi& FTC
+)
+{
+  return igl::writeOBJ(str,V,F,CN,FN,TC,FTC);
+}, __doc_igl_writeOBJ,
+py::arg("str"), py::arg("V"), py::arg("F"), py::arg("CN"), py::arg("FN"), py::arg("TC"), py::arg("FTC"));
+
+m.def("writeOBJ", []
+(
+  const std::string str,
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F
+)
+{
+  return igl::writeOBJ(str,V,F);
+}, __doc_igl_writeOBJ,
+py::arg("str"), py::arg("V"), py::arg("F"));

+ 371 - 0
python/py_igl_viewer.cpp

@@ -0,0 +1,371 @@
+#include <Eigen/Dense>
+#include <Eigen/Sparse>
+
+#include "python.h"
+#define ENABLE_SERIALIZATION
+#include <igl/viewer/Viewer.h>
+#include <igl/viewer/ViewerCore.h>
+#include <igl/viewer/ViewerData.h>
+
+void python_export_igl_viewer(py::module &m)
+{
+
+  py::module me = m.def_submodule(
+    "viewer", "Mesh viewer");
+
+/////////////////////// DATA
+
+py::class_<igl::viewer::ViewerData> viewerdata_class(me, "ViewerData");
+
+py::enum_<igl::viewer::ViewerData::DirtyFlags>(viewerdata_class, "DirtyFlags")
+    .value("DIRTY_NONE", igl::viewer::ViewerData::DIRTY_NONE)
+    .value("DIRTY_POSITION", igl::viewer::ViewerData::DIRTY_POSITION)
+    .value("DIRTY_UV", igl::viewer::ViewerData::DIRTY_UV)
+    .value("DIRTY_NORMAL", igl::viewer::ViewerData::DIRTY_NORMAL)
+    .value("DIRTY_AMBIENT", igl::viewer::ViewerData::DIRTY_AMBIENT)
+    .value("DIRTY_DIFFUSE", igl::viewer::ViewerData::DIRTY_DIFFUSE)
+    .value("DIRTY_SPECULAR", igl::viewer::ViewerData::DIRTY_SPECULAR)
+    .value("DIRTY_TEXTURE", igl::viewer::ViewerData::DIRTY_TEXTURE)
+    .value("DIRTY_FACE", igl::viewer::ViewerData::DIRTY_FACE)
+    .value("DIRTY_MESH", igl::viewer::ViewerData::DIRTY_MESH)
+    .value("DIRTY_OVERLAY_LINES", igl::viewer::ViewerData::DIRTY_OVERLAY_LINES)
+    .value("DIRTY_OVERLAY_POINTS", igl::viewer::ViewerData::DIRTY_OVERLAY_POINTS)
+    .value("DIRTY_ALL", igl::viewer::ViewerData::DIRTY_ALL)
+    .export_values();
+
+
+    viewerdata_class
+    .def(py::init<>())
+    .def("set_mesh", &igl::viewer::ViewerData::set_mesh)
+    .def("set_colors", &igl::viewer::ViewerData::set_colors)
+    .def("clear", &igl::viewer::ViewerData::clear)
+    .def("set_face_based", &igl::viewer::ViewerData::set_face_based)
+
+    .def("set_vertices", &igl::viewer::ViewerData::set_vertices)
+    .def("set_normals", &igl::viewer::ViewerData::set_normals)
+
+    .def("set_uv",
+       (void (igl::viewer::ViewerData::*) (const Eigen::MatrixXd &)) &igl::viewer::ViewerData::set_uv
+    )
+
+    .def("set_uv",
+       (void (igl::viewer::ViewerData::*) (const Eigen::MatrixXd &, const Eigen::MatrixXi&)) &igl::viewer::ViewerData::set_uv
+    )
+
+    .def("set_texture", &igl::viewer::ViewerData::set_texture)
+    .def("set_points", &igl::viewer::ViewerData::set_points)
+    .def("add_points", &igl::viewer::ViewerData::add_points)
+    .def("set_edges", &igl::viewer::ViewerData::set_edges)
+    .def("add_edges", &igl::viewer::ViewerData::add_edges)
+
+    .def("add_label", [] (igl::viewer::ViewerData& data, const Eigen::MatrixXd& P,  const std::string& str)
+    {
+      assert_is_VectorX("P",P);
+      data.add_label(P,str);
+    })
+
+    .def("compute_normals", &igl::viewer::ViewerData::compute_normals)
+
+    .def("uniform_colors", [] (igl::viewer::ViewerData& data, const Eigen::MatrixXd& ambient, const Eigen::MatrixXd& diffuse, const Eigen::MatrixXd& specular)
+    {
+      assert_is_Vector3("ambient",ambient);
+      assert_is_Vector3("diffuse",diffuse);
+      assert_is_Vector3("specular",specular);
+      data.uniform_colors(ambient,diffuse, specular);
+    })
+
+    .def("grid_texture", &igl::viewer::ViewerData::grid_texture)
+
+    .def_readwrite("V", &igl::viewer::ViewerData::V)
+    .def_readwrite("F", &igl::viewer::ViewerData::F)
+
+    .def_readwrite("F_normals", &igl::viewer::ViewerData::F_normals)
+    .def_readwrite("F_material_ambient", &igl::viewer::ViewerData::F_material_ambient)
+    .def_readwrite("F_material_diffuse", &igl::viewer::ViewerData::F_material_diffuse)
+    .def_readwrite("F_material_specular", &igl::viewer::ViewerData::F_material_specular)
+
+    .def_readwrite("V_normals", &igl::viewer::ViewerData::V_normals)
+    .def_readwrite("V_material_ambient", &igl::viewer::ViewerData::V_material_ambient)
+    .def_readwrite("V_material_diffuse", &igl::viewer::ViewerData::V_material_diffuse)
+    .def_readwrite("V_material_specular", &igl::viewer::ViewerData::V_material_specular)
+
+    .def_readwrite("V_uv", &igl::viewer::ViewerData::V_uv)
+    .def_readwrite("F_uv", &igl::viewer::ViewerData::F_uv)
+
+    .def_readwrite("texture_R", &igl::viewer::ViewerData::texture_R)
+    .def_readwrite("texture_G", &igl::viewer::ViewerData::texture_G)
+    .def_readwrite("texture_B", &igl::viewer::ViewerData::texture_B)
+
+    .def_readwrite("lines", &igl::viewer::ViewerData::lines)
+    .def_readwrite("points", &igl::viewer::ViewerData::points)
+    .def_readwrite("labels_positions", &igl::viewer::ViewerData::labels_positions)
+    .def_readwrite("labels_strings", &igl::viewer::ViewerData::labels_strings)
+    .def_readwrite("dirty", &igl::viewer::ViewerData::dirty)
+    .def_readwrite("face_based", &igl::viewer::ViewerData::face_based)
+    .def("serialize", [](igl::viewer::ViewerData& data)
+    {
+      std::vector<char> a;
+      igl::serialize(data,"Data",a);
+      return a;
+    })
+
+    .def("deserialize", [](igl::viewer::ViewerData& data, const std::vector<char>& a)
+    {
+      igl::deserialize(data,"Data",a);
+      return;
+    })
+
+    ;
+
+//////////////////////// CORE
+
+py::class_<igl::viewer::ViewerCore> viewercore_class(me, "ViewerCore");
+
+    py::enum_<igl::viewer::ViewerCore::RotationType>(viewercore_class, "RotationType")
+        .value("ROTATION_TYPE_TRACKBALL", igl::viewer::ViewerCore::ROTATION_TYPE_TRACKBALL)
+        .value("ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP", igl::viewer::ViewerCore::ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP)
+        .value("NUM_ROTATION_TYPES", igl::viewer::ViewerCore::NUM_ROTATION_TYPES)
+        .export_values();
+
+    viewercore_class
+    .def(py::init<>())
+    //.def("align_camera_center", [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& V, const Eigen::MatrixXi& F){return core.align_camera_center(V,F);})
+    .def("init", &igl::viewer::ViewerCore::init)
+    .def("shut", &igl::viewer::ViewerCore::shut)
+    //.def("InitSerialization", &igl::viewer::ViewerCore::InitSerialization)
+    .def("align_camera_center",
+       (void (igl::viewer::ViewerCore::*) (const Eigen::MatrixXd &, const Eigen::MatrixXi &)) &igl::viewer::ViewerCore::align_camera_center
+    )
+
+    .def("align_camera_center",
+       (void (igl::viewer::ViewerCore::*) (const Eigen::MatrixXd &)) &igl::viewer::ViewerCore::align_camera_center
+    )
+
+    .def("clear_framebuffers",&igl::viewer::ViewerCore::clear_framebuffers)
+    .def("draw",&igl::viewer::ViewerCore::draw)
+    .def("draw_buffer",&igl::viewer::ViewerCore::draw_buffer)
+
+    .def_readwrite("textrenderer",&igl::viewer::ViewerCore::textrenderer)
+    .def_readwrite("shininess",&igl::viewer::ViewerCore::shininess)
+
+    .def_property("background_color",
+    [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.background_color.cast<double>());},
+    [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
+    {
+      assert_is_Vector3("background_color",v);
+      core.background_color = Eigen::Vector3f(v.cast<float>());
+    })
+
+    .def_property("line_color",
+    [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.line_color.cast<double>());},
+    [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
+    {
+      assert_is_Vector3("line_color",v);
+      core.line_color = Eigen::Vector3f(v.cast<float>());
+    })
+
+    .def_property("light_position",
+    [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.light_position.cast<double>());},
+    [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
+    {
+      assert_is_Vector3("light_position",v);
+      core.light_position = Eigen::Vector3f(v.cast<float>());
+    })
+
+    .def_readwrite("lighting_factor",&igl::viewer::ViewerCore::lighting_factor)
+
+    .def_readwrite("model_zoom",&igl::viewer::ViewerCore::model_zoom)
+
+    .def_property("model_translation",
+    [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.model_translation.cast<double>());},
+    [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
+    {
+      assert_is_Vector3("model_translation",v);
+      core.model_translation = Eigen::Vector3f(v.cast<float>());
+    })
+
+    .def_readwrite("model_zoom_uv",&igl::viewer::ViewerCore::model_zoom_uv)
+
+    .def_property("model_translation_uv",
+    [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.model_translation_uv.cast<double>());},
+    [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
+    {
+      assert_is_Vector3("model_translation_uv",v);
+      core.model_translation_uv = Eigen::Vector3f(v.cast<float>());
+    })
+
+    .def_readwrite("camera_zoom",&igl::viewer::ViewerCore::camera_zoom)
+    .def_readwrite("orthographic",&igl::viewer::ViewerCore::orthographic)
+
+    .def_property("camera_eye",
+    [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.camera_eye.cast<double>());},
+    [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
+    {
+      assert_is_Vector3("camera_eye",v);
+      core.camera_eye = Eigen::Vector3f(v.cast<float>());
+    })
+
+    .def_property("camera_up",
+    [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.camera_up.cast<double>());},
+    [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
+    {
+      assert_is_Vector3("camera_up",v);
+      core.camera_up = Eigen::Vector3f(v.cast<float>());
+    })
+
+    .def_property("camera_center",
+    [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.camera_center.cast<double>());},
+    [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
+    {
+      assert_is_Vector3("camera_center",v);
+      core.camera_center = Eigen::Vector3f(v.cast<float>());
+    })
+
+    .def_readwrite("camera_view_angle",&igl::viewer::ViewerCore::camera_view_angle)
+
+    .def_readwrite("camera_dnear",&igl::viewer::ViewerCore::camera_dnear)
+    .def_readwrite("camera_dfar",&igl::viewer::ViewerCore::camera_dfar)
+
+    .def_readwrite("show_overlay",&igl::viewer::ViewerCore::show_overlay)
+    .def_readwrite("show_overlay_depth",&igl::viewer::ViewerCore::show_overlay_depth)
+    .def_readwrite("show_texture",&igl::viewer::ViewerCore::show_texture)
+    .def_readwrite("show_faces",&igl::viewer::ViewerCore::show_faces)
+
+    .def_readwrite("show_lines",&igl::viewer::ViewerCore::show_lines)
+    .def_readwrite("show_vertid",&igl::viewer::ViewerCore::show_vertid)
+    .def_readwrite("show_faceid",&igl::viewer::ViewerCore::show_faceid)
+    .def_readwrite("invert_normals",&igl::viewer::ViewerCore::invert_normals)
+    .def_readwrite("depth_test",&igl::viewer::ViewerCore::depth_test)
+
+    .def_readwrite("point_size",&igl::viewer::ViewerCore::point_size)
+    .def_readwrite("line_width",&igl::viewer::ViewerCore::line_width)
+
+    .def_readwrite("is_animating",&igl::viewer::ViewerCore::is_animating)
+    .def_readwrite("animation_max_fps",&igl::viewer::ViewerCore::animation_max_fps)
+
+    .def_readwrite("object_scale",&igl::viewer::ViewerCore::object_scale)
+
+    .def_property("viewport",
+    [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.viewport.cast<double>());},
+    [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
+    {
+      assert_is_Vector4("viewport",v);
+      core.viewport = Eigen::Vector4f(v.cast<float>());
+    })
+
+    .def_property("view",
+    [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.view.cast<double>());},
+    [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
+    {
+      assert_is_Matrix4("view",v);
+      core.view = Eigen::Matrix4f(v.cast<float>());
+    })
+
+    .def_property("model",
+    [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.model.cast<double>());},
+    [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
+    {
+      assert_is_Matrix4("model",v);
+      core.model = Eigen::Matrix4f(v.cast<float>());
+    })
+
+    .def_property("proj",
+    [](const igl::viewer::ViewerCore& core) {return Eigen::MatrixXd(core.proj.cast<double>());},
+    [](igl::viewer::ViewerCore& core, const Eigen::MatrixXd& v)
+    {
+      assert_is_Matrix4("proj",v);
+      core.proj = Eigen::Matrix4f(v.cast<float>());
+    })
+
+    .def_readwrite("rotation_type",&igl::viewer::ViewerCore::rotation_type)
+
+    .def("serialize", [](igl::viewer::ViewerCore& core)
+    {
+      std::vector<char> a;
+      igl::serialize(core,"Core",a);
+      return a;
+    })
+
+    .def("deserialize", [](igl::viewer::ViewerCore& core, const std::vector<char>& a)
+    {
+      igl::deserialize(core,"Core",a);
+      return;
+    })
+
+    // TODO: wrap this!
+    // Eigen::Quaternionf trackball_angle;
+    ;
+
+///////////////////////// VIEWER
+
+// UI Enumerations
+    py::class_<igl::viewer::Viewer> viewer_class(me, "Viewer");
+
+    py::enum_<igl::viewer::Viewer::MouseButton>(viewer_class, "MouseButton")
+        .value("Left", igl::viewer::Viewer::MouseButton::Left)
+        .value("Middle", igl::viewer::Viewer::MouseButton::Middle)
+        .value("Right", igl::viewer::Viewer::MouseButton::Right)
+        .export_values();
+
+    viewer_class
+    .def(py::init<>())
+    .def_readwrite("data", &igl::viewer::Viewer::data)
+    .def_readwrite("core", &igl::viewer::Viewer::core)
+    .def("launch", &igl::viewer::Viewer::launch, py::arg("resizable") = true, py::arg("fullscreen") = false)
+    .def("launch_init", &igl::viewer::Viewer::launch_init, py::arg("resizable") = true, py::arg("fullscreen") = false)
+    .def("launch_rendering", &igl::viewer::Viewer::launch_rendering, py::arg("loop") = true)
+    .def("launch_shut", &igl::viewer::Viewer::launch_shut)
+    .def("init", &igl::viewer::Viewer::init)
+    .def("serialize", [](igl::viewer::Viewer& viewer)
+    {
+      std::vector<char> a;
+      igl::serialize(viewer.core,"Core",a);
+      igl::serialize(viewer.data,"Data",a);
+
+      return a;
+    })
+
+    .def("deserialize", [](igl::viewer::Viewer& viewer, const std::vector<char>& a)
+    {
+      igl::deserialize(viewer.core,"Core",a);
+      igl::deserialize(viewer.data,"Data",a);
+      return;
+    })
+
+    // Scene IO
+    .def("load_scene", [](igl::viewer::Viewer& viewer)
+    {
+      viewer.load_scene();
+    })
+
+    .def("load_scene", [](igl::viewer::Viewer& viewer, std::string str)
+    {
+      viewer.load_scene(str);
+    })
+
+    .def("save_scene", &igl::viewer::Viewer::save_scene)
+
+    // Draw everything
+    .def("draw", &igl::viewer::Viewer::draw)
+
+    // OpenGL context resize
+    .def("resize", &igl::viewer::Viewer::resize)
+
+    // Helper functions
+    .def("snap_to_canonical_quaternion", &igl::viewer::Viewer::snap_to_canonical_quaternion)
+    .def("open_dialog_load_mesh", &igl::viewer::Viewer::open_dialog_load_mesh)
+    .def("open_dialog_save_mesh", &igl::viewer::Viewer::open_dialog_save_mesh)
+
+    // Callbacks
+    .def_readwrite("callback_init", &igl::viewer::Viewer::callback_init)
+    .def_readwrite("callback_pre_draw", &igl::viewer::Viewer::callback_pre_draw)
+    .def_readwrite("callback_post_draw", &igl::viewer::Viewer::callback_post_draw)
+    .def_readwrite("callback_mouse_down", &igl::viewer::Viewer::callback_mouse_down)
+    .def_readwrite("callback_mouse_up", &igl::viewer::Viewer::callback_mouse_up)
+    .def_readwrite("callback_mouse_move", &igl::viewer::Viewer::callback_mouse_move)
+    .def_readwrite("callback_mouse_scroll", &igl::viewer::Viewer::callback_mouse_scroll)
+    .def_readwrite("callback_key_pressed", &igl::viewer::Viewer::callback_key_pressed)
+    .def_readwrite("callback_key_down", &igl::viewer::Viewer::callback_key_down)
+    .def_readwrite("callback_key_up", &igl::viewer::Viewer::callback_key_up)
+    ;
+}

+ 623 - 0
python/py_vector.cpp

@@ -0,0 +1,623 @@
+#include <Eigen/Dense>
+#include <Eigen/Sparse>
+
+#include "python.h"
+
+/// Creates Python bindings for a dynamic Eigen matrix
+template <typename Type>
+py::class_<Type> bind_eigen_2(py::module &m, const char *name,
+                                py::object parent = py::object()) {
+    typedef typename Type::Scalar Scalar;
+
+    /* Many Eigen functions are templated and can't easily be referenced using
+       a function pointer, thus a big portion of the binding code below
+       instantiates Eigen code using small anonymous wrapper functions */
+    py::class_<Type> matrix(m, name, parent);
+
+    matrix
+        /* Constructors */
+        .def(py::init<>())
+        .def(py::init<size_t, size_t>())
+        .def("__init__", [](Type &m, Scalar f) {
+            new (&m) Type(1, 1);
+            m(0, 0) = f;
+        })
+        .def("__init__", [](Type &m, std::vector<std::vector< Scalar> >& b) {
+          if (b.size() == 0)
+          {
+            new (&m) Type(0, 0);
+            return;
+          }
+
+          // Size checks
+          unsigned rows = b.size();
+          unsigned cols = b[0].size();
+          for (unsigned i=0;i<rows;++i)
+            if (b[i].size() != cols)
+              throw std::runtime_error("All rows should have the same size!");
+
+          new (&m) Type(rows, cols);
+
+          m.resize(rows,cols);
+          for (unsigned i=0;i<rows;++i)
+            for (unsigned j=0;j<cols;++j)
+              m(i,j) = b[i][j];
+
+          return;
+        })
+        .def("__init__", [](Type &m, py::buffer b) {
+            py::buffer_info info = b.request();
+            if (info.format != py::format_descriptor<Scalar>::value())
+                throw std::runtime_error("Incompatible buffer format!");
+            if (info.ndim == 1) {
+                new (&m) Type(info.shape[0], 1);
+                memcpy(m.data(), info.ptr, sizeof(Scalar) * m.size());
+            } else if (info.ndim == 2) {
+                if (info.strides[0] == sizeof(Scalar)) {
+                    new (&m) Type(info.shape[0], info.shape[1]);
+                    memcpy(m.data(), info.ptr, sizeof(Scalar) * m.size());
+                } else {
+                    new (&m) Type(info.shape[1], info.shape[0]);
+                    memcpy(m.data(), info.ptr, sizeof(Scalar) * m.size());
+                    m.transposeInPlace();
+                }
+            } else {
+                throw std::runtime_error("Incompatible buffer dimension!");
+            }
+        })
+
+        /* Size query functions */
+        .def("size", [](const Type &m) { return m.size(); })
+        .def("cols", [](const Type &m) { return m.cols(); })
+        .def("rows", [](const Type &m) { return m.rows(); })
+
+        /* Extract rows and colums */
+        .def("col", [](const Type &m, int i) {
+            if (i<0 || i>=m.cols())
+              throw std::runtime_error("Column index out of bound.");
+            return Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>(m.col(i));
+        })
+        .def("row", [](const Type &m, int i) {
+            if (i<0 || i>=m.rows())
+              throw std::runtime_error("Row index out of bound.");
+            return Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>(m.row(i));
+        })
+
+
+        /* Initialization */
+        .def("setZero", [](Type &m) { m.setZero(); })
+        .def("setIdentity", [](Type &m) { m.setIdentity(); })
+        .def("setConstant", [](Type &m, Scalar value) { m.setConstant(value); })
+        .def("setRandom", [](Type &m) { m.setRandom(); })
+
+        .def("setZero", [](Type &m, const int& r, const int& c) { m.setZero(r,c); })
+        .def("setIdentity", [](Type &m, const int& r, const int& c) { m.setIdentity(r,c); })
+        .def("setConstant", [](Type &m, const int& r, const int& c, Scalar value) { m.setConstant(r,c,value); })
+        .def("setRandom", [](Type &m, const int& r, const int& c) { m.setRandom(r,c); })
+
+        .def("setCol", [](Type &m, int i, const Type& v) { m.col(i) = v; })
+        .def("setRow", [](Type &m, int i, const Type& v) { m.row(i) = v; })
+
+
+        .def("rightCols", [](Type &m, const int& k) { return Type(m.rightCols(k)); })
+        .def("leftCols", [](Type &m, const int& k) { return Type(m.leftCols(k)); })
+
+        .def("topRows", [](Type &m, const int& k) { return Type(m.topRows(k)); })
+        .def("bottomRows", [](Type &m, const int& k) { return Type(m.bottomRows(k)); })
+
+        .def("topLeftCorner", [](Type &m, const int& p, const int&q) { return Type(m.topLeftCorner(p,q)); })
+        .def("bottomLeftCorner", [](Type &m, const int& p, const int&q) { return Type(m.bottomLeftCorner(p,q)); })
+        .def("topRightCorner", [](Type &m, const int& p, const int&q) { return Type(m.topRightCorner(p,q)); })
+        .def("bottomRightCorner", [](Type &m, const int& p, const int&q) { return Type(m.bottomRightCorner(p,q)); })
+
+        /* Resizing */
+        .def("resize", [](Type &m, size_t s0, size_t s1) { m.resize(s0, s1); })
+        .def("resizeLike", [](Type &m, const Type &m2) { m.resizeLike(m2); })
+        .def("conservativeResize", [](Type &m, size_t s0, size_t s1) { m.conservativeResize(s0, s1); })
+
+
+        .def("mean", [](const Type &m) {return m.mean();})
+
+        .def("sum", [](const Type &m) {return m.sum();})
+        .def("prod", [](const Type &m) {return m.prod();})
+        .def("trace", [](const Type &m) {return m.trace();})
+        .def("norm", [](const Type &m) {return m.norm();})
+        .def("squaredNorm", [](const Type &m) {return m.squaredNorm();})
+
+        .def("minCoeff", [](const Type &m) {return m.minCoeff();} )
+        .def("maxCoeff", [](const Type &m) {return m.maxCoeff();} )
+
+        .def("castdouble", [](const Type &m) {return Eigen::MatrixXd(m.template cast<double>());})
+        .def("castint", [](const Type &m) {return Eigen::MatrixXi(m.template cast<int>());})
+
+        /* Component-wise operations */
+        .def("cwiseAbs", &Type::cwiseAbs)
+        .def("cwiseAbs2", &Type::cwiseAbs2)
+        .def("cwiseSqrt", &Type::cwiseSqrt)
+        .def("cwiseInverse", &Type::cwiseInverse)
+        .def("cwiseMin", [](const Type &m1, const Type &m2) -> Type { return m1.cwiseMin(m2); })
+        .def("cwiseMax", [](const Type &m1, const Type &m2) -> Type { return m1.cwiseMax(m2); })
+        .def("cwiseMin", [](const Type &m1, Scalar s) -> Type { return m1.cwiseMin(s); })
+        .def("cwiseMax", [](const Type &m1, Scalar s) -> Type { return m1.cwiseMax(s); })
+        .def("cwiseProduct", [](const Type &m1, const Type &m2) -> Type { return m1.cwiseProduct(m2); })
+        .def("cwiseQuotient", [](const Type &m1, const Type &m2) -> Type { return m1.cwiseQuotient(m2); })
+
+        /* Row and column-wise operations */
+        .def("rowwiseSum", [](const Type &m) {return Type(m.rowwise().sum());} )
+        .def("rowwiseProd", [](const Type &m) {return Type(m.rowwise().prod());} )
+        .def("rowwiseMean", [](const Type &m) {return Type(m.rowwise().mean());} )
+        .def("rowwiseNorm", [](const Type &m) {return Type(m.rowwise().norm());} )
+        .def("rowwiseNormalized", [](const Type &m) {return Type(m.rowwise().normalized());} )
+        .def("rowwiseMinCoeff", [](const Type &m) {return Type(m.rowwise().minCoeff());} )
+        .def("rowwiseMaxCoeff", [](const Type &m) {return Type(m.rowwise().maxCoeff());} )
+
+        .def("colwiseSum", [](const Type &m) {return Type(m.colwise().sum());} )
+        .def("colwiseProd", [](const Type &m) {return Type(m.colwise().prod());} )
+        .def("colwiseMean", [](const Type &m) {return Type(m.colwise().mean());} )
+        .def("colwiseNorm", [](const Type &m) {return Type(m.colwise().norm());} )
+        .def("colwiseMinCoeff", [](const Type &m) {return Type(m.colwise().minCoeff());} )
+        .def("colwiseMaxCoeff", [](const Type &m) {return Type(m.colwise().maxCoeff());} )
+
+        .def("replicate", [](const Type &m, const int& r, const int& c) {return Type(m.replicate(r,c));} )
+        .def("asDiagonal", [](const Type &m) {return Eigen::DiagonalMatrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>(m.asDiagonal());} )
+
+        .def("sparseView", [](Type &m) { return Eigen::SparseMatrix<Scalar>(m.sparseView()); })
+
+        /* Arithmetic operators (def_cast forcefully casts the result back to a
+           Type to avoid type issues with Eigen's crazy expression templates) */
+        .def_cast(-py::self)
+        .def_cast(py::self + py::self)
+        .def_cast(py::self - py::self)
+        .def_cast(py::self * py::self)
+        // .def_cast(py::self - Scalar())
+        // .def_cast(py::self * Scalar())
+        // .def_cast(py::self / Scalar())
+
+        .def("__mul__", []
+        (const Type &a, const Scalar& b)
+        {
+          return Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>(a * b);
+        })
+        .def("__rmul__", [](const Type& a, const Scalar& b)
+        {
+          return Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>(b * a);
+        })
+
+        .def("__add__", []
+        (const Type &a, const Scalar& b)
+        {
+          return Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>(a.array() + b);
+        })
+        .def("__radd__", [](const Type& a, const Scalar& b)
+        {
+          return Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>(b + a.array());
+        })
+
+        .def("__sub__", []
+        (const Type &a, const Scalar& b)
+        {
+          return Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>(a.array() - b);
+        })
+        .def("__rsub__", [](const Type& a, const Scalar& b)
+        {
+          return Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>(b - a.array());
+        })
+
+        .def("__div__", []
+        (const Type &a, const Scalar& b)
+        {
+          return Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>(a / b);
+        })
+
+        .def("__truediv__", []
+        (const Type &a, const Scalar& b)
+        {
+          return Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>(a / b);
+        })
+
+        /* Arithmetic in-place operators */
+        .def_cast(py::self += py::self)
+        .def_cast(py::self -= py::self)
+        .def_cast(py::self *= py::self)
+        // .def_cast(py::self *= Scalar())
+        // .def_cast(py::self /= Scalar())
+
+        /* Comparison operators */
+        .def(py::self == py::self)
+        .def(py::self != py::self)
+
+        .def("transposeInPlace", [](Type &m) { m.transposeInPlace(); })
+        /* Other transformations */
+        .def("transpose", [](Type &m) -> Type { return m.transpose(); })
+        /* Python protocol implementations */
+        .def("__repr__", [](const Type &v) {
+            std::ostringstream oss;
+            oss << v;
+            return oss.str();
+        })
+        .def("__getitem__", [](const Type &m, std::pair<size_t, size_t> i) {
+            if (i.first >= (size_t) m.rows() || i.second >= (size_t) m.cols())
+                throw py::index_error();
+            return m(i.first, i.second);
+         })
+        .def("__setitem__", [](Type &m, std::pair<size_t, size_t> i, Scalar v) {
+            if (i.first >= (size_t) m.rows() || i.second >= (size_t) m.cols())
+                throw py::index_error();
+            m(i.first, i.second) = v;
+         })
+
+        /* Buffer access for interacting with NumPy */
+        .def_buffer([](Type &m) -> py::buffer_info {
+            return py::buffer_info(
+                m.data(),                /* Pointer to buffer */
+                sizeof(Scalar),          /* Size of one scalar */
+                /* Python struct-style format descriptor */
+                py::format_descriptor<Scalar>::value(),
+                2,                       /* Number of dimensions */
+                { (size_t) m.rows(),     /* Buffer dimensions */
+                  (size_t) m.cols() },
+                { sizeof(Scalar),        /* Strides (in bytes) for each index */
+                  sizeof(Scalar) * m.rows() }
+            );
+         })
+
+        /* Static initializers */
+        .def_static("Zero", [](size_t n, size_t m) { return Type(Type::Zero(n, m)); })
+        .def_static("Random", [](size_t n, size_t m) { return Type(Type::Random(n, m)); })
+        .def_static("Ones", [](size_t n, size_t m) { return Type(Type::Ones(n, m)); })
+        .def_static("Constant", [](size_t n, size_t m, Scalar value) { return Type(Type::Constant(n, m, value)); })
+        .def_static("Identity", [](size_t n, size_t m) { return Type(Type::Identity(n, m)); })
+        .def("MapMatrix", [](const Type& m, size_t r, size_t c)
+        {
+          return Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>(Eigen::Map<const Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>>(m.data(),r,c));
+        })
+        ;
+    return matrix;
+}
+
+/// Creates Python bindings for a dynamic Eigen sparse order-2 tensor (i.e. a matrix)
+template <typename Type>
+py::class_<Type> bind_eigen_sparse_2(py::module &m, const char *name,
+                                py::object parent = py::object()) {
+    typedef typename Type::Scalar Scalar;
+
+    /* Many Eigen functions are templated and can't easily be referenced using
+       a function pointer, thus a big portion of the binding code below
+       instantiates Eigen code using small anonymous wrapper functions */
+    py::class_<Type> matrix(m, name, parent);
+
+    matrix
+        /* Constructors */
+        .def(py::init<>())
+        .def(py::init<size_t, size_t>())
+        // .def("__init__", [](Type &m, Scalar f) {
+        //     new (&m) Type(1, 1);
+        //     m(0, 0) = f;
+        // })
+        // .def("__init__", [](Type &m, py::buffer b) {
+        //     py::buffer_info info = b.request();
+        //     if (info.format != py::format_descriptor<Scalar>::value())
+        //         throw std::runtime_error("Incompatible buffer format!");
+        //     if (info.ndim == 1) {
+        //         new (&m) Type(info.shape[0], 1);
+        //         memcpy(m.data(), info.ptr, sizeof(Scalar) * m.size());
+        //     } else if (info.ndim == 2) {
+        //         if (info.strides[0] == sizeof(Scalar)) {
+        //             new (&m) Type(info.shape[0], info.shape[1]);
+        //             memcpy(m.data(), info.ptr, sizeof(Scalar) * m.size());
+        //         } else {
+        //             new (&m) Type(info.shape[1], info.shape[0]);
+        //             memcpy(m.data(), info.ptr, sizeof(Scalar) * m.size());
+        //             m.transposeInPlace();
+        //         }
+        //     } else {
+        //         throw std::runtime_error("Incompatible buffer dimension!");
+        //     }
+        // })
+
+        /* Size query functions */
+        .def("size", [](const Type &m) { return m.size(); })
+        .def("cols", [](const Type &m) { return m.cols(); })
+        .def("rows", [](const Type &m) { return m.rows(); })
+
+        /* Initialization */
+        .def("setZero", [](Type &m) { m.setZero(); })
+        .def("setIdentity", [](Type &m) { m.setIdentity(); })
+
+        .def("transpose", [](Type &m) { return Type(m.transpose()); })
+        .def("norm", [](Type &m) { return m.norm(); })
+
+        /* Resizing */
+        // .def("resize", [](Type &m, size_t s0, size_t s1) { m.resize(s0, s1); })
+        // .def("resizeLike", [](Type &m, const Type &m2) { m.resizeLike(m2); })
+        // .def("conservativeResize", [](Type &m, size_t s0, size_t s1) { m.conservativeResize(s0, s1); })
+
+        /* Component-wise operations */
+        // .def("cwiseAbs", &Type::cwiseAbs)
+        // .def("cwiseAbs2", &Type::cwiseAbs2)
+        // .def("cwiseSqrt", &Type::cwiseSqrt)
+        // .def("cwiseInverse", &Type::cwiseInverse)
+        // .def("cwiseMin", [](const Type &m1, const Type &m2) -> Type { return m1.cwiseMin(m2); })
+        // .def("cwiseMax", [](const Type &m1, const Type &m2) -> Type { return m1.cwiseMax(m2); })
+        // .def("cwiseMin", [](const Type &m1, Scalar s) -> Type { return m1.cwiseMin(s); })
+        // .def("cwiseMax", [](const Type &m1, Scalar s) -> Type { return m1.cwiseMax(s); })
+        // .def("cwiseProduct", [](const Type &m1, const Type &m2) -> Type { return m1.cwiseProduct(m2); })
+        // .def("cwiseQuotient", [](const Type &m1, const Type &m2) -> Type { return m1.cwiseQuotient(m2); })
+
+        /* Arithmetic operators (def_cast forcefully casts the result back to a
+           Type to avoid type issues with Eigen's crazy expression templates) */
+        .def_cast(-py::self)
+        .def_cast(py::self + py::self)
+        .def_cast(py::self - py::self)
+        .def_cast(py::self * py::self)
+        .def_cast(py::self * Scalar())
+        .def_cast(Scalar() * py::self)
+        // Special case, sparse * dense produces a dense matrix
+
+        // .def("__mul__", []
+        // (const Type &a, const Scalar& b)
+        // {
+        //   return Type(a * b);
+        // })
+        // .def("__rmul__", [](const Type& a, const Scalar& b)
+        // {
+        //   return Type(b * a);
+        // })
+
+        .def("__mul__", []
+        (const Type &a, const Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>& b)
+        {
+          return Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>(a * b);
+        })
+        .def("__rmul__", [](const Type& a, const Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>& b)
+        {
+          return Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>(b * a);
+        })
+
+        .def("__mul__", []
+        (const Type &a, const Eigen::DiagonalMatrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>& b)
+        {
+          return Type(a * b);
+        })
+        .def("__rmul__", [](const Type& a, const Eigen::DiagonalMatrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>& b)
+        {
+          return Type(b * a);
+        })
+
+        //.def(py::self * Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>())
+//        .def_cast(py::self / Scalar())
+
+        /* Arithmetic in-place operators */
+        // .def_cast(py::self += py::self)
+        // .def_cast(py::self -= py::self)
+        // .def_cast(py::self *= py::self)
+        // .def_cast(py::self *= Scalar())
+        // .def_cast(py::self /= Scalar())
+
+        /* Comparison operators */
+        // .def(py::self == py::self)
+        // .def(py::self != py::self)
+
+        // .def("transposeInPlace", [](Type &m) { m.transposeInPlace(); })
+        // /* Other transformations */
+        // .def("transpose", [](Type &m) -> Type { return m.transpose(); })
+
+        /* Python protocol implementations */
+        .def("__repr__", [](const Type &v) {
+            std::ostringstream oss;
+            oss << v;
+            return oss.str();
+        })
+
+        /* Static initializers */
+        // .def_static("Zero", [](size_t n, size_t m) { return Type(Type::Zero(n, m)); })
+        // .def_static("Ones", [](size_t n, size_t m) { return Type(Type::Ones(n, m)); })
+        // .def_static("Constant", [](size_t n, size_t m, Scalar value) { return Type(Type::Constant(n, m, value)); })
+        // .def_static("Identity", [](size_t n, size_t m) { return Type(Type::Identity(n, m)); })
+        .def("toCOO",[](const Type& m)
+        {
+          Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> t(m.nonZeros(),3);
+          int count = 0;
+          for (int k=0; k<m.outerSize(); ++k)
+            for (typename Type::InnerIterator it(m,k); it; ++it)
+              t.row(count++) << it.row(), it.col(), it.value();
+          return t;
+        })
+
+        .def("fromCOO",[](Type& m, const Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>& t, int rows, int cols)
+        {
+          typedef Eigen::Triplet<Scalar> T;
+          std::vector<T> tripletList;
+          tripletList.reserve(t.rows());
+          for(unsigned i=0;i<t.rows();++i)
+            tripletList.push_back(T(round(t(i,0)),round(t(i,1)),t(i,2)));
+
+          if (rows == -1)
+            rows = t.col(0).maxCoeff()+1;
+
+          if (cols == -1)
+            cols = t.col(1).maxCoeff()+1;
+
+          m.resize(rows,cols);
+          m.setFromTriplets(tripletList.begin(), tripletList.end());
+        }, py::arg("t"), py::arg("rows") = -1, py::arg("cols") = -1)
+
+        .def("insert",[](Type& m, const int row, const int col, const Scalar value)
+        {
+          return m.insert(row,col) = value;
+        }, py::arg("row"), py::arg("col"), py::arg("value"))
+
+        .def("makeCompressed",[](Type& m)
+        {
+          return m.makeCompressed();
+        })
+
+        .def("diagonal", [](const Type &m) {return Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>(m.diagonal());} )
+
+        ;
+    return matrix;
+}
+
+/// Creates Python bindings for a diagonal Eigen sparse order-2 tensor (i.e. a matrix)
+template <typename Type>
+py::class_<Type> bind_eigen_diagonal_2(py::module &m, const char *name,
+                                py::object parent = py::object()) {
+    typedef typename Type::Scalar Scalar;
+
+    /* Many Eigen functions are templated and can't easily be referenced using
+       a function pointer, thus a big portion of the binding code below
+       instantiates Eigen code using small anonymous wrapper functions */
+    py::class_<Type> matrix(m, name, parent);
+
+    matrix
+        /* Constructors */
+        .def(py::init<>())
+        //.def(py::init<size_t, size_t>())
+
+        /* Size query functions */
+        .def("size", [](const Type &m) { return m.size(); })
+        .def("cols", [](const Type &m) { return m.cols(); })
+        .def("rows", [](const Type &m) { return m.rows(); })
+
+        /* Initialization */
+        .def("setZero", [](Type &m) { m.setZero(); })
+        .def("setIdentity", [](Type &m) { m.setIdentity(); })
+
+        /* Arithmetic operators (def_cast forcefully casts the result back to a
+           Type to avoid type issues with Eigen's crazy expression templates) */
+        // .def_cast(-py::self)
+        // .def_cast(py::self + py::self)
+        // .def_cast(py::self - py::self)
+        // .def_cast(py::self * py::self)
+        .def_cast(py::self * Scalar())
+        .def_cast(Scalar() * py::self)
+
+        // // Special case, sparse * dense produces a dense matrix
+        // .def("__mul__", []
+        // (const Type &a, const Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>& b)
+        // {
+        //   return Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>(a * b);
+        // })
+        // .def("__rmul__", [](const Type& a, const Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>& b)
+        // {
+        //   return Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>(b * a);
+        // })
+
+        .def("__mul__", []
+        (const Type &a, const Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>& b)
+        {
+          return Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>(a * b);
+        })
+        .def("__rmul__", [](const Type& a, const Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>& b)
+        {
+          return Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>(b * a);
+        })
+
+        .def("__mul__", []
+        (const Type &a, const Eigen::SparseMatrix<Scalar>& b)
+        {
+          return Eigen::SparseMatrix<Scalar>(a * b);
+        })
+        .def("__rmul__", [](const Type& a, const Eigen::SparseMatrix<Scalar>& b)
+        {
+          return Eigen::SparseMatrix<Scalar>(b * a);
+        })
+
+        /* Python protocol implementations */
+        .def("__repr__", [](const Type &/*v*/) {
+            std::ostringstream oss;
+            oss << "<< operator undefined for diagonal matrices";
+            return oss.str();
+        })
+
+        /* Other transformations */
+
+        ;
+    return matrix;
+}
+
+
+void python_export_vector(py::module &m) {
+
+  py::module me = m.def_submodule(
+    "eigen", "Wrappers for Eigen types");
+
+    /* Bindings for VectorXd */
+    // bind_eigen_1<Eigen::VectorXd> (me, "VectorXd");
+    // py::implicitly_convertible<py::buffer, Eigen::VectorXd>();
+    // py::implicitly_convertible<double, Eigen::VectorXd>();
+
+    /* Bindings for VectorXi */
+    // bind_eigen_1<Eigen::VectorXi> (me, "VectorXi");
+    // py::implicitly_convertible<py::buffer, Eigen::VectorXi>();
+    // py::implicitly_convertible<double, Eigen::VectorXi>();
+
+    /* Bindings for MatrixXd */
+    bind_eigen_2<Eigen::MatrixXd> (me, "MatrixXd");
+    //py::implicitly_convertible<py::buffer, Eigen::MatrixXd>();
+    //py::implicitly_convertible<double, Eigen::MatrixXd>();
+
+    /* Bindings for MatrixXi */
+    bind_eigen_2<Eigen::MatrixXi> (me, "MatrixXi");
+//    py::implicitly_convertible<py::buffer, Eigen::MatrixXi>();
+    //py::implicitly_convertible<double, Eigen::MatrixXi>();
+
+    /* Bindings for MatrixXuc */
+    bind_eigen_2<Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> > (me, "MatrixXuc");
+    // py::implicitly_convertible<py::buffer, Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> >();
+    // py::implicitly_convertible<double, Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> >();
+
+    // /* Bindings for Vector3d */
+    // auto vector3 = bind_eigen_1_3<Eigen::Vector3d>(me, "Vector3d");
+    // vector3
+    //     .def("norm", [](const Eigen::Vector3d &v) { return v.norm(); })
+    //     .def("squaredNorm", [](const Eigen::Vector3d &v) { return v.squaredNorm(); })
+    //     .def("normalize", [](Eigen::Vector3d &v) { v.normalize(); })
+    //     .def("normalized", [](const Eigen::Vector3d &v) -> Eigen::Vector3d { return v.normalized(); })
+    //     .def("dot", [](const Eigen::Vector3d &v1, const Eigen::Vector3d &v2) { return v1.dot(v2); })
+    //     .def("cross", [](const Eigen::Vector3d &v1, const Eigen::Vector3d &v2) -> Eigen::Vector3d { return v1.cross(v2); })
+    //     .def_property("x", [](const Eigen::Vector3d &v) -> double { return v.x(); },
+    //                        [](Eigen::Vector3d &v, double x) { v.x() = x; }, "X coordinate")
+    //     .def_property("y", [](const Eigen::Vector3d &v) -> double { return v.y(); },
+    //                        [](Eigen::Vector3d &v, double y) { v.y() = y; }, "Y coordinate")
+    //     .def_property("z", [](const Eigen::Vector3d &v) -> double { return v.z(); },
+    //                        [](Eigen::Vector3d &v, double z) { v.z() = z; }, "Z coordinate");
+    //
+    // py::implicitly_convertible<py::buffer, Eigen::Vector3d>();
+    // py::implicitly_convertible<double, Eigen::Vector3d>();
+
+    /* Bindings for SparseMatrix<double> */
+    bind_eigen_sparse_2< Eigen::SparseMatrix<double> > (me, "SparseMatrixd");
+
+    /* Bindings for SparseMatrix<int> */
+    bind_eigen_sparse_2< Eigen::SparseMatrix<int> > (me, "SparseMatrixi");
+
+    /* Bindings for DiagonalMatrix<double> */
+    bind_eigen_diagonal_2< Eigen::DiagonalMatrix<double,Eigen::Dynamic,Eigen::Dynamic> > (me, "DiagonalMatrixd");
+
+    /* Bindings for DiagonalMatrix<int> */
+    bind_eigen_diagonal_2< Eigen::DiagonalMatrix<int,Eigen::Dynamic,Eigen::Dynamic> > (me, "DiagonalMatrixi");
+
+    /* Bindings for SimplicialLLT*/
+
+    py::class_<Eigen::SimplicialLLT<Eigen::SparseMatrix<double > >> simpliciallltsparse(me, "SimplicialLLTsparse");
+
+    simpliciallltsparse
+    .def(py::init<>())
+    .def(py::init<Eigen::SparseMatrix<double>>())
+    .def("info",[](const Eigen::SimplicialLLT<Eigen::SparseMatrix<double > >& s)
+    {
+       if (s.info() == Eigen::Success)
+          return "Success";
+       else
+          return "Numerical Issue";
+    })
+    .def("solve",[](const Eigen::SimplicialLLT<Eigen::SparseMatrix<double > >& s, const Eigen::MatrixXd& rhs) { return Eigen::MatrixXd(s.solve(rhs)); })
+
+    ;
+
+
+
+
+
+}

+ 19 - 0
python/python.cpp

@@ -0,0 +1,19 @@
+#include "python.h"
+#include <sstream>
+#include <string>
+#include <fstream>
+
+extern void python_export_vector(py::module &);
+extern void python_export_igl(py::module &);
+extern void python_export_igl_viewer(py::module &);
+
+PYTHON_PLUGIN(igl) {
+    py::init_threading();
+    py::module m("igl", "Python wrappers for libigl");
+
+    python_export_vector(m);
+    python_export_igl(m);
+    python_export_igl_viewer(m);
+
+    return m.ptr();
+}

+ 86 - 0
python/python.h

@@ -0,0 +1,86 @@
+#pragma once
+
+#include <pybind/pybind.h>
+#include <pybind/operators.h>
+#include <pybind/complex.h>
+#include <pybind/numpy.h>
+#include <pybind/stl.h>
+#include <pybind/functional.h>
+
+#include "py_doc.h"
+
+#include <Eigen/Dense>
+
+template<typename Scalar>
+void assert_is_VectorX(const std::string name, const Eigen::PlainObjectBase<Scalar>& v)
+{
+  if (v.size() == 0)
+    return;
+
+  if (v.cols() != 1)
+    throw std::runtime_error(name + " must be a column vector.");
+}
+
+template<typename Scalar>
+void assert_is_RowVectorX(const std::string name, const Eigen::PlainObjectBase<Scalar>& v)
+{
+  if (v.size() == 0)
+    return;
+
+  if (v.rows() != 1)
+    throw std::runtime_error(name + " must be a row vector.");
+}
+
+template<typename Scalar>
+void assert_is_Vector3(const std::string name, const Eigen::PlainObjectBase<Scalar>& v)
+{
+  if (v.size() == 0)
+    return;
+
+  if ((v.cols() != 1) || (v.rows() != 3))
+    throw std::runtime_error(name + " must be a column vector with 3 entries.");
+}
+
+template<typename Scalar>
+void assert_is_RowVector3(const std::string name, const Eigen::PlainObjectBase<Scalar>& v)
+{
+  if (v.size() == 0)
+    return;
+
+  if ((v.cols() != 3) || (v.rows() != 1))
+    throw std::runtime_error(name + " must be a row vector with 3 entries.");
+}
+
+template<typename Scalar>
+void assert_is_Vector4(const std::string name, const Eigen::PlainObjectBase<Scalar>& v)
+{
+  if (v.size() == 0)
+    return;
+
+  if ((v.cols() != 1) || (v.rows() != 4))
+    throw std::runtime_error(name + " must be a column vector with 4 entries.");
+}
+
+template<typename Scalar>
+void assert_is_RowVector4(const std::string name, const Eigen::PlainObjectBase<Scalar>& v)
+{
+  if (v.size() == 0)
+    return;
+
+  if ((v.cols() != 4) || (v.rows() != 1))
+    throw std::runtime_error(name + " must be a row vector with 4 entries.");
+}
+
+template<typename Scalar>
+void assert_is_Matrix4(const std::string name, const Eigen::PlainObjectBase<Scalar>& v)
+{
+  if (v.size() == 0)
+    return;
+
+  if ((v.cols() != 4) || (v.rows() != 4))
+    throw std::runtime_error(name + " must be a 4x4 matrix.");
+}
+
+
+
+namespace py = pybind;

+ 68 - 0
python/scripts/mk_py_doc.py

@@ -0,0 +1,68 @@
+#!/usr/bin/env python3
+#
+#  Syntax: mkdoc.py <path_of_header_files>
+#
+#  Extract documentation from C++ header files to use it in libiglPython bindings
+#
+
+import os, sys, glob
+
+#http://stackoverflow.com/questions/3207219/how-to-list-all-files-of-a-directory-in-python
+def get_filepaths(directory):
+    """
+    This function will generate the file names in a directory
+    tree by walking the tree either top-down or bottom-up. For each
+    directory in the tree rooted at directory top (including top itself),
+    it yields a 3-tuple (dirpath, dirnames, filenames).
+    """
+    file_paths = []  # List which will store all of the full filepaths.
+
+    # Walk the tree.
+    for root, directories, files in os.walk(directory):
+        for filename in files:
+            # Join the two strings in order to form the full filepath.
+            filepath = os.path.join(root, filename)
+            file_paths.append(filepath)  # Add it to the list.
+
+    return file_paths  # Self-explanatory.
+
+
+if __name__ == '__main__':
+
+    if len(sys.argv) != 2:
+        print('Syntax: %s <path_of_header_files>' % sys.argv[0])
+        exit(-1)
+
+    # Open two files, py_doc.h and py_doc.cpp
+    fh = open('py_doc.h', 'w')
+    fc = open('py_doc.cpp', 'w')
+
+    # List all files in the given folder and subfolders
+    base_path = sys.argv[1]
+    full_file_paths = get_filepaths(base_path)
+
+    # Add all the .h files
+    for f in full_file_paths:
+      if f.endswith(".h"):
+        f_clean = f[len(base_path):]
+        f_clean = f_clean.replace(base_path, "")
+        f_clean = f_clean.replace(".h", "")
+        f_clean = f_clean.replace("/", "_")
+        f_clean = f_clean.replace("\\", "_")
+        f_clean = f_clean.replace(" ", "_")
+        f_clean = f_clean.replace(".", "_")
+
+        #tmp = open(f, 'r', encoding="utf8")
+        tmp_string = f.replace("../include/", "libigl/") # " " # tmp.read()
+        tmp_string = "See " + tmp_string + " for the documentation."
+        #tmp.close()
+
+        h_string = "extern const char *__doc_" + f_clean + ";\n"
+        cpp_string = "const char *__doc_" + f_clean + " = R\"igl_Qu8mg5v7(" + tmp_string + ")igl_Qu8mg5v7\";\n"
+
+        fh.write(h_string)
+        fc.write(cpp_string)
+
+    # Close files
+    fh.close()
+    fc.close()

+ 45 - 0
python/tcpviewer.py

@@ -0,0 +1,45 @@
+import socket
+import multiprocessing
+import igl
+import array
+
+HOST = 'localhost'                 # Symbolic name meaning all available interfaces
+PORT = 50008              # Arbitrary non-privileged port
+
+def worker(data):
+    viewer = igl.viewer.Viewer()
+    temp = list(data)
+    viewer.deserialize(temp)
+    viewer.launch(True,False)
+    return
+
+class TCPViewer(igl.viewer.Viewer):
+    def launch(self):
+        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        s.connect((HOST, PORT))
+        a = array.array('u',self.serialize())
+        s.sendall(a)
+        s.close()
+
+if __name__ == "__main__": # The main script is a server
+    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    s.bind((HOST, PORT))
+    s.listen(1)
+    print("TCP iglviewer server listening on port " + str(PORT))
+    try:
+        while True:
+            conn, addr = s.accept()
+            slist = []
+            while True:
+                buf = conn.recv(4096)
+                if not buf:
+                    break
+                slist.append(buf.decode('unicode_internal','ignore'))
+            conn.close()
+
+            data = ''.join(slist)
+
+            t = multiprocessing.Process(target=worker, args=(data,))
+            t.start()
+    except:
+        s.close()

+ 69 - 0
python/tcpviewer_single.py

@@ -0,0 +1,69 @@
+import socket
+import threading
+import igl
+import array
+import time
+
+HOST = 'localhost'                 # Symbolic name meaning all available interfaces
+PORT = 50008              # Arbitrary non-privileged port
+
+def worker(viewer,lock):
+    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    s.bind((HOST, PORT))
+    s.listen(1)
+    print("TCP iglviewer server listening on port " + str(PORT))
+    try:
+        while True:
+            conn, addr = s.accept()
+            lock.acquire()
+            slist = []
+            while True:
+                buf = conn.recv(4096)
+                if not buf:
+                    break
+                slist.append(buf.decode('unicode_internal','ignore'))
+            conn.close()
+
+            data = ''.join(slist)
+            temp = list(data)
+
+            isempty = viewer.data.V.rows() == 0
+            viewer.data.deserialize(temp)
+            if isempty and viewer.data.V.rows() != 0:
+                viewer.core.align_camera_center(viewer.data.V,viewer.data.F)
+
+            lock.release()
+
+    except:
+        s.close()
+    return
+
+class TCPViewer(igl.viewer.Viewer):
+    def launch(self):
+        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        s.connect((HOST, PORT))
+        a = array.array('u',self.data.serialize())
+        s.sendall(a)
+        s.close()
+
+if __name__ == "__main__": # The main script is a server
+    viewer = igl.viewer.Viewer()
+
+    lock = threading.Lock()
+    t = threading.Thread(target=worker, args=(viewer,lock,))
+    t.setDaemon(True)
+    t.start()
+
+    viewer.core.is_animating = True
+    # viewer.data.dirty = int(0x03FF)
+
+    viewer.launch_init(True,False)
+    done = False
+    while not done:
+        lock.acquire()
+        done = not viewer.launch_rendering(False)
+        lock.release()
+
+        time.sleep(0.000001) # DO NOT REMOVE ME
+
+    viewer.launch_shut()

+ 29 - 0
scripts/update_gh-pages_nogit.sh

@@ -0,0 +1,29 @@
+#!/bin/bash
+# Usage: cd $LIBIGL; scripts/update_gh-pages.sh
+set -o xtrace
+
+HEADER="title: libigl
+author: Alec Jacobson and Daniele Panozzo and others
+css: tutorial/style.css
+html header:   <script type='text/javascript' src='http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML'></script>
+<link rel='stylesheet' href='http://yandex.st/highlightjs/7.3/styles/default.min.css'>
+<script src='http://yandex.st/highlightjs/7.3/highlight.min.js'></script>
+<script>hljs.initHighlightingOnLoad();</script>
+
+"
+
+echo "$HEADER" \
+  | cat - README.md | multimarkdown -o index.html
+
+HEADER="title: libigl
+author: Alec Jacobson and Daniele Panozzo and others
+css: ../tutorial/style.css
+html header:   <script type='text/javascript' src='http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML'></script>
+<link rel='stylesheet' href='http://yandex.st/highlightjs/7.3/styles/default.min.css'>
+<script src='http://yandex.st/highlightjs/7.3/highlight.min.js'></script>
+<script>hljs.initHighlightingOnLoad();</script>
+
+"
+
+echo "$HEADER" \
+  | cat - optional/README.md | multimarkdown -o optional/index.html