Browse Source

merge

Former-commit-id: 0a5c31384224c0ecba660ce8a7bf205bdafcb1fd
Alec Jacobson 9 years ago
parent
commit
d42f56073e
100 changed files with 4220 additions and 287 deletions
  1. 11 0
      .gitignore
  2. 6 1
      .gitmodules
  3. 4 4
      README.md
  4. 10 10
      include/igl/AABB.h
  5. 3 1
      include/igl/ConjugateFFSolverData.h
  6. 1 1
      include/igl/EPS.h
  7. 0 1
      include/igl/HalfEdgeIterator.h
  8. 2 2
      include/igl/IndexComparison.h
  9. 4 0
      include/igl/NormalType.h
  10. 3 3
      include/igl/ONE.h
  11. 1 0
      include/igl/Viewport.h
  12. 5 2
      include/igl/WindingNumberMethod.h
  13. 7 3
      include/igl/WindingNumberTree.h
  14. 3 3
      include/igl/ZERO.h
  15. 0 2
      include/igl/active_set.h
  16. 1 1
      include/igl/biharmonic_coordinates.cpp
  17. 175 0
      include/igl/boolean/CSGTree.h
  18. 53 26
      include/igl/boolean/mesh_boolean.cpp
  19. 48 0
      include/igl/boolean/string_to_mesh_boolean_type.cpp
  20. 41 0
      include/igl/boolean/string_to_mesh_boolean_type.h
  21. 7 0
      include/igl/cgal/assign_scalar.cpp
  22. 3 0
      include/igl/cgal/assign_scalar.h
  23. 15 3
      include/igl/cgal/mesh_to_cgal_triangle_list.cpp
  24. 211 0
      include/igl/cgal/order_facets_around_edge.cpp
  25. 53 0
      include/igl/cgal/order_facets_around_edge.h
  26. 78 0
      include/igl/cgal/order_facets_around_edges.cpp
  27. 30 1
      include/igl/cgal/order_facets_around_edges.h
  28. 74 0
      include/igl/cgal/outer_facet.cpp
  29. 55 0
      include/igl/cgal/outer_facet.h
  30. 3 106
      include/igl/cgal/outer_hull.cpp
  31. 0 15
      include/igl/cgal/outer_hull.h
  32. 13 31
      include/igl/cgal/peel_outer_hull_layers.cpp
  33. 0 13
      include/igl/cgal/peel_outer_hull_layers.h
  34. 5 1
      include/igl/cgal/remesh_intersections.cpp
  35. 1 2
      include/igl/file_dialog_open.cpp
  36. 2 2
      include/igl/normal_derivative.cpp
  37. 2 2
      include/igl/parula.cpp
  38. 65 20
      include/igl/serialize.h
  39. 9 10
      include/igl/unique.cpp
  40. 5 9
      include/igl/unique.h
  41. 24 4
      include/igl/viewer/Viewer.cpp
  42. 7 0
      include/igl/viewer/Viewer.h
  43. 5 2
      include/igl/viewer/ViewerCore.cpp
  44. 2 0
      include/igl/viewer/ViewerCore.h
  45. 8 4
      include/igl/viewer/ViewerData.cpp
  46. 2 2
      index.html
  47. 48 0
      python/001_BasicTypes.py
  48. 14 0
      python/101_FileIO.py
  49. 11 0
      python/102_DrawMesh.py
  50. 24 0
      python/102_DrawMeshTCP.py
  51. 40 0
      python/103_Events.py
  52. 24 0
      python/104_Colors.py
  53. 67 0
      python/105_Overlays.py
  54. 48 0
      python/201_Normals.py
  55. 20 0
      python/202_GaussianCurvature.py
  56. 61 0
      python/203_CurvatureDirections.py
  57. 50 0
      python/204_Gradient.py
  58. 108 0
      python/205_Laplacian.py
  59. 34 0
      python/301_Slice.py
  60. 34 0
      python/302_Sort.py
  61. 73 0
      python/303_LaplaceEquation.py
  62. 96 0
      python/304_LinearEqualityConstraints.py
  63. 86 0
      python/305_QuadraticProgramming.py
  64. 56 0
      python/306_EigenDecomposition.py
  65. 154 0
      python/CMakeLists.txt
  66. 159 0
      python/README.md
  67. 51 0
      python/iglhelpers.py
  68. 59 0
      python/matlab/CurvatureDirections.m
  69. 12 0
      python/matlab/t102DrawMesh.m
  70. 409 0
      python/py_doc.cpp
  71. 409 0
      python/py_doc.h
  72. 69 0
      python/py_igl.cpp
  73. 6 0
      python/py_igl/py_SolverStatus.cpp
  74. 48 0
      python/py_igl/py_active_set.cpp
  75. 9 0
      python/py_igl/py_avg_edge_length.cpp
  76. 10 0
      python/py_igl/py_barycenter.cpp
  77. 30 0
      python/py_igl/py_boundary_facets.cpp
  78. 74 0
      python/py_igl/py_colon.cpp
  79. 10 0
      python/py_igl/py_cotmatrix.cpp
  80. 54 0
      python/py_igl/py_doublearea.cpp
  81. 22 0
      python/py_igl/py_eigs.cpp
  82. 9 0
      python/py_igl/py_floor.cpp
  83. 10 0
      python/py_igl/py_gaussian_curvature.cpp
  84. 10 0
      python/py_igl/py_grad.cpp
  85. 9 0
      python/py_igl/py_invert_diag.cpp
  86. 24 0
      python/py_igl/py_jet.cpp
  87. 19 0
      python/py_igl/py_massmatrix.cpp
  88. 73 0
      python/py_igl/py_min_quad_with_fixed.cpp
  89. 24 0
      python/py_igl/py_parula.cpp
  90. 38 0
      python/py_igl/py_per_corner_normals.cpp
  91. 34 0
      python/py_igl/py_per_face_normals.cpp
  92. 55 0
      python/py_igl/py_per_vertex_normals.cpp
  93. 15 0
      python/py_igl/py_principal_curvature.cpp
  94. 10 0
      python/py_igl/py_readDMAT.cpp
  95. 22 0
      python/py_igl/py_readOFF.cpp
  96. 36 0
      python/py_igl/py_read_triangle_mesh.cpp
  97. 11 0
      python/py_igl/py_setdiff.cpp
  98. 155 0
      python/py_igl/py_slice.cpp
  99. 107 0
      python/py_igl/py_slice_into.cpp
  100. 23 0
      python/py_igl/py_sortrows.cpp

+ 11 - 0
.gitignore

@@ -78,3 +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

+ 6 - 1
.gitmodules

@@ -3,7 +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

+ 10 - 10
include/igl/AABB.h

@@ -8,18 +8,18 @@
 #ifndef IGL_AABB_H
 #define IGL_AABB_H
 
-// Implementation of semi-general purpose axis-aligned bounding box hierarchy.
-// The mesh (V,Ele) is stored and managed by the caller and each routine here
-// simply takes it as references (it better not change between calls).
-//
-// It's a little annoying that the Dimension is a template parameter and not
-// picked up at run time from V. This leads to duplicated code for 2d/3d (up to
-// dim).
 #include <Eigen/Core>
 #include <Eigen/Geometry>
 #include <vector>
 namespace igl
 {
+  // Implementation of semi-general purpose axis-aligned bounding box hierarchy.
+  // The mesh (V,Ele) is stored and managed by the caller and each routine here
+  // simply takes it as references (it better not change between calls).
+  //
+  // It's a little annoying that the Dimension is a template parameter and not
+  // picked up at run time from V. This leads to duplicated code for 2d/3d (up to
+  // dim).
   template <typename DerivedV, int DIM>
     class AABB 
     {
@@ -75,9 +75,9 @@ public:
       AABB(AABB&& other):
         // initialize via default constructor
         AABB() 
-    {
-      swap(*this,other);
-    }
+      {
+        swap(*this,other);
+      }
       // Seems like there should have been an elegant solution to this using
       // the copy-swap idiom above:
       inline void deinit()

+ 3 - 1
include/igl/ConjugateFFSolverData.h

@@ -11,7 +11,9 @@
 #include <Eigen/Core>
 #include <Eigen/Sparse>
 
-namespace igl {
+namespace igl 
+{
+  // Data class for the Conjugate Frame Field Solver
   template <typename DerivedV, typename DerivedF>
   class ConjugateFFSolverData
   {

+ 1 - 1
include/igl/EPS.h

@@ -8,9 +8,9 @@
 #ifndef IGL_EPS_H
 #define IGL_EPS_H
 #include "igl_inline.h"
-// Define a standard value for double epsilon
 namespace igl
 {
+  // Define a standard value for double epsilon
   const double DOUBLE_EPS    = 1.0e-14;
   const double DOUBLE_EPS_SQ = 1.0e-28;
   const float FLOAT_EPS    = 1.0e-7;

+ 0 - 1
include/igl/HalfEdgeIterator.h

@@ -5,7 +5,6 @@
 // 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_HALFEDGEITERATOR_H
 #define IGL_HALFEDGEITERATOR_H
 

+ 2 - 2
include/igl/IndexComparison.h

@@ -8,9 +8,9 @@
 #ifndef IGL_INDEXCOMPARISON_H
 #define IGL_INDEXCOMPARISON_H
 #include <iostream>
-// Comparison struct used by sort
-// http://bytes.com/topic/c/answers/132045-sort-get-index
 namespace igl{
+  // Comparison struct used by sort
+  // http://bytes.com/topic/c/answers/132045-sort-get-index
 
   // For use with functions like std::sort
   template<class T> struct IndexLessThan

+ 4 - 0
include/igl/NormalType.h

@@ -10,6 +10,10 @@
 
 namespace igl
 {
+  // PER_VERTEX_NORMALS  Normals computed per vertex based on incident faces
+  // PER_FACE_NORMALS  Normals computed per face
+  // PER_CORNER_NORMALS  Normals computed per corner (aka wedge) based on
+  //   incident faces without sharp edge
   enum NormalType
   {
     PER_VERTEX_NORMALS,

+ 3 - 3
include/igl/ONE.h

@@ -7,11 +7,11 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 #ifndef IGL_ONE_H
 #define IGL_ONE_H
-// Often one needs a reference to a dummy variable containing one as its
-// value, for example when using AntTweakBar's
-// TwSetParam( "3D View", "opened", TW_PARAM_INT32, 1, &INT_ONE);
 namespace igl
 {
+  // Often one needs a reference to a dummy variable containing one as its
+  // value, for example when using AntTweakBar's
+  // TwSetParam( "3D View", "opened", TW_PARAM_INT32, 1, &INT_ONE);
   const char CHAR_ONE = 1;
   const int INT_ONE = 1;
   const unsigned int UNSIGNED_INT_ONE = 1;

+ 1 - 0
include/igl/Viewport.h

@@ -10,6 +10,7 @@
 
 namespace igl
 {
+  // Simple Viewport class for an opengl context. Handles reshaping and mouse.
   struct Viewport
   {
     int x,y,width,height;

+ 5 - 2
include/igl/WindingNumberMethod.h

@@ -9,11 +9,14 @@
 #define IGL_WINDINGNUMBERMETHOD_H
 namespace igl
 {
+  // EXACT_WINDING_NUMBER_METHOD  exact hierarchical evaluation
+  // APPROX_SIMPLE_WINDING_NUMBER_METHOD  poor approximation
+  // APPROX_CACHE_WINDING_NUMBER_METHOD  another poor approximation
   enum WindingNumberMethod
   {
-    EXACT_WINDING_NUMBER_METHOD = 0, // Exact hierarchical evaluation
+    EXACT_WINDING_NUMBER_METHOD = 0,
     APPROX_SIMPLE_WINDING_NUMBER_METHOD = 1,
-    APPROX_CACHE_WINDING_NUMBER_METHOD = 2, // Approximate hierarchical evaluation
+    APPROX_CACHE_WINDING_NUMBER_METHOD = 2,
     NUM_WINDING_NUMBER_METHODS = 3
   };
 }

+ 7 - 3
include/igl/WindingNumberTree.h

@@ -12,9 +12,13 @@
 #include <Eigen/Dense>
 #include "WindingNumberMethod.h"
 
-static Eigen::MatrixXd dummyV;
 namespace igl
 {
+  // This is only need to fill in references, it should never actually be touched
+  // and shouldn't cause race conditions. (This is a hack, but I think it's "safe")
+  static Eigen::MatrixXd dummyV;
+  // Space partitioning tree for computing winding number hierarchically.
+  //
   // Templates:
   //   Point  type for points in space, e.g. Eigen::Vector3d
   template <typename Point>
@@ -146,7 +150,7 @@ template <typename Point>
 inline igl::WindingNumberTree<Point>::WindingNumberTree():
   method(EXACT_WINDING_NUMBER_METHOD),
   parent(NULL),
-  V(dummyV),
+  V(igl::dummyV),
   SV(),
   F(),
   //boundary(igl::boundary_facets<Eigen::MatrixXi,Eigen::MatrixXi>(F))
@@ -162,7 +166,7 @@ inline igl::WindingNumberTree<Point>::WindingNumberTree(
   const Eigen::MatrixXi & _F):
   method(EXACT_WINDING_NUMBER_METHOD),
   parent(NULL),
-  V(dummyV),
+  V(igl::dummyV),
   SV(),
   F(),
   //boundary(igl::boundary_facets<Eigen::MatrixXi,Eigen::MatrixXi>(F))

+ 3 - 3
include/igl/ZERO.h

@@ -7,11 +7,11 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 #ifndef IGL_ZERO_H
 #define IGL_ZERO_H
-// Often one needs a reference to a dummy variable containing zero as its
-// value, for example when using AntTweakBar's
-// TwSetParam( "3D View", "opened", TW_PARAM_INT32, 1, &INT_ZERO);
 namespace igl
 {
+  // Often one needs a reference to a dummy variable containing zero as its
+  // value, for example when using AntTweakBar's
+  // TwSetParam( "3D View", "opened", TW_PARAM_INT32, 1, &INT_ZERO);
   const char CHAR_ZERO = 0;
   const int INT_ZERO = 0;
   const unsigned int UNSIGNED_INT_ZERO = 0;

+ 0 - 2
include/igl/active_set.h

@@ -28,7 +28,6 @@ namespace igl
   // and further optionally subject to the linear inequality constraints that
   // Aieq*Z <= Bieq and constant inequality constraints lx <= x <= ux
   //
-  // Templates:
   // Inputs:
   //   A  n by n matrix of quadratic coefficients
   //   B  n by 1 column of linear coefficients
@@ -50,7 +49,6 @@ namespace igl
   // Benchmark: For a harmonic solve on a mesh with 325K facets, matlab 2.2
   // secs, igl/min_quad_with_fixed.h 7.1 secs
   //
-
   template <
     typename AT, 
     typename DerivedB,

+ 1 - 1
include/igl/biharmonic_coordinates.cpp

@@ -142,7 +142,7 @@ IGL_INLINE bool igl::biharmonic_coordinates(
   // minimize    ½ W' A W'
   // subject to  W(b,:) = J
   return min_quad_with_fixed(
-    A,VectorXd::Zero(A.rows()).eval(),b,J,{},VectorXd(),true,W);
+    A,VectorXd::Zero(A.rows()).eval(),b,J,SparseMatrix<double>(),VectorXd(),true,W);
 }
 
 #ifdef IGL_STATIC_LIBRARY

+ 175 - 0
include/igl/boolean/CSGTree.h

@@ -0,0 +1,175 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_BOOLEAN_CSG_TREE_H
+#define IGL_BOOLEAN_CSG_TREE_H
+
+#include <igl/boolean/string_to_mesh_boolean_type.h>
+#include <igl/boolean/MeshBooleanType.h>
+#include <igl/boolean/mesh_boolean.h>
+
+namespace igl
+{
+  namespace boolean
+  {
+    // Class for defining and computing a constructive solid geometry result
+    // out of a tree of boolean operations on "solid" triangle meshes.
+    //
+    template <typename DerivedF>
+    class CSGTree
+    {
+      private:
+        typedef CGAL::Epeck::FT ExactScalar;
+        typedef Eigen::Matrix<ExactScalar,Eigen::Dynamic,3> MatrixX3E;
+        typedef Eigen::PlainObjectBase<DerivedF> POBF;
+        typedef Eigen::Matrix<typename DerivedF::Index,Eigen::Dynamic,1> 
+          VectorJ;
+        // Resulting mesh
+        MatrixX3E m_V;
+        POBF m_F;
+        VectorJ m_J;
+        // Number of birth faces in A + those in B. I.e. sum of original "leaf"
+        // faces involved in result.
+        size_t m_number_of_birth_faces;
+      public:
+        CSGTree()
+        {
+        }
+        //typedef Eigen::MatrixXd MatrixX3E;
+        //typedef Eigen::MatrixXi POBF;
+        // http://stackoverflow.com/a/3279550/148668
+        CSGTree(const CSGTree & other)
+          :
+          // copy things
+          m_V(other.m_V),
+          m_F(other.m_F),
+          m_J(other.m_J),
+          m_number_of_birth_faces(other.m_number_of_birth_faces)
+        {
+        }
+        // copy-swap idiom
+        friend void swap(CSGTree& first, CSGTree& second)
+        {
+          using std::swap;
+          // swap things
+          swap(first.m_V,second.m_V);
+          swap(first.m_F,second.m_F);
+          swap(first.m_J,second.m_J);
+          swap(first.m_number_of_birth_faces,second.m_number_of_birth_faces);
+        }
+        // Pass-by-value (aka copy)
+        CSGTree& operator=(CSGTree other)
+        {
+          swap(*this,other);
+          return *this;
+        }
+        CSGTree(CSGTree&& other):
+          // initialize via default constructor
+          CSGTree() 
+        {
+          swap(*this,other);
+        }
+        // Construct and compute a boolean operation on existing CSGTree nodes.
+        //
+        // Inputs:
+        //   A  Solid result of previous CSG operation (or identity, see below)
+        //   B  Solid result of previous CSG operation (or identity, see below)
+        //   type  type of mesh boolean to compute 
+        CSGTree(
+          const CSGTree & A,
+          const CSGTree & B,
+          const MeshBooleanType & type)
+        {
+          // conduct boolean operation
+          mesh_boolean(A.V(),A.F(),B.V(),B.F(),type,m_V,m_F,m_J);
+          // reindex m_J
+          std::for_each(m_J.data(),m_J.data()+m_J.size(),
+            [&](typename VectorJ::Scalar & j)
+            {
+              if(j < A.F().rows())
+              {
+                j = A.J()(j);
+              }else
+              {
+                assert(j<(A.F().rows()+B.F().rows()));
+                j = A.number_of_birth_faces()+(B.J()(j-A.F().rows()));
+              }
+            });
+          m_number_of_birth_faces = 
+            A.number_of_birth_faces() + B.number_of_birth_faces();
+        }
+        // Overload using string for type
+        CSGTree(
+          const CSGTree & A,
+          const CSGTree & B,
+          const std::string & s):
+          CSGTree(A,B,string_to_mesh_boolean_type(s))
+        {
+          // do nothing (all done in constructor).
+        }
+        // "Leaf" node with identity operation on assumed "solid" mesh (V,F)
+        //
+        // Inputs:
+        //   V  #V by 3 list of mesh vertices (in any precision, will be
+        //     converted to exact)
+        //   F  #F by 3 list of mesh face indices into V
+        template <typename DerivedV>
+        CSGTree(const Eigen::PlainObjectBase<DerivedV> & V, const POBF & F)//:
+        // Possible Eigen bug:
+        // https://forum.kde.org/viewtopic.php?f=74&t=128414
+          //m_V(V.template cast<ExactScalar>()),m_F(F)
+        {
+          m_V = V.template cast<ExactScalar>();
+          m_F = F;
+          // number of faces
+          m_number_of_birth_faces = m_F.rows();
+          // identity birth index
+          m_J = VectorJ::LinSpaced(
+            m_number_of_birth_faces,0,m_number_of_birth_faces-1);
+        }
+        // Returns reference to resulting mesh vertices m_V in exact scalar
+        // representation
+        const MatrixX3E & V() const
+        {
+          return m_V;
+        }
+        // Returns mesh vertices in the desired output type, casting when
+        // appropriate to floating precision.
+        template <typename DerivedV>
+        Eigen::PlainObjectBase<DerivedV> cast_V() const
+        {
+          Eigen::PlainObjectBase<DerivedV> dV;
+          dV.resize(m_V.rows(),m_V.cols());
+          for(int i = 0;i<m_V.size();i++)
+          {
+            *(dV.data()+i) = CGAL::to_double((*(m_V.data()+i)));
+          }
+          return dV;
+        }
+        // Returns reference to resulting mesh faces m_F
+        const POBF & F() const
+        {
+          return m_F;
+        }
+        // Returns reference to "birth parents" indices into [F1;F2;...;Fn]
+        // where F1, ... , Fn are the face lists of the leaf ("original") input
+        // meshes.
+        const VectorJ & J() const
+        {
+          return m_J;
+        }
+        // The number of leaf faces = #F1 + #F2 + ... + #Fn
+        const size_t & number_of_birth_faces() const
+        {
+          return m_number_of_birth_faces;
+        }
+    };
+  }
+}
+
+
+#endif

+ 53 - 26
include/igl/boolean/mesh_boolean.cpp

@@ -6,7 +6,10 @@
 // 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 "mesh_boolean.h"
+#include <igl/cgal/assign_scalar.h>
 #include <igl/per_face_normals.h>
+#include <igl/boundary_facets.h>
+#include <igl/exterior_edges.h>
 #include <igl/cgal/peel_outer_hull_layers.h>
 #include <igl/cgal/remesh_self_intersections.h>
 #include <igl/remove_unreferenced.h>
@@ -103,7 +106,7 @@ IGL_INLINE void igl::boolean::mesh_boolean(
   using namespace igl::cgal;
   MeshBooleanType eff_type = type;
   // Concatenate A and B into a single mesh
-  typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
+  typedef CGAL::Epeck Kernel;
   typedef Kernel::FT ExactScalar;
   typedef typename DerivedVC::Scalar Scalar;
   typedef typename DerivedFC::Scalar Index;
@@ -176,7 +179,9 @@ IGL_INLINE void igl::boolean::mesh_boolean(
     CV.resize(EV.rows(), EV.cols());
     std::transform(EV.data(), EV.data() + EV.rows()*EV.cols(),
             CV.data(), [&](ExactScalar val) {
-            return CGAL::to_double(val);
+            Scalar c;
+            assign_scalar(val,c);
+            return c;
             });
   }
 
@@ -187,13 +192,6 @@ IGL_INLINE void igl::boolean::mesh_boolean(
     J = CJ;
     return;
   }
-  MatrixX3S N,CN;
-  per_face_normals_stable(V,F,N);
-  CN.resize(CF.rows(),3);
-  for(size_t f = 0;f<(size_t)CN.rows();f++)
-  {
-    CN.row(f) = N.row(CJ(f));
-  }
 
 #ifdef IGL_MESH_BOOLEAN_DEBUG
   cout<<"peel..."<<endl;
@@ -202,13 +200,7 @@ IGL_INLINE void igl::boolean::mesh_boolean(
   // peel layers keeping track of odd and even flips
   VectorXi I;
   Matrix<bool,Dynamic,1> flip;
-  peel_outer_hull_layers(EV,CF,CN,I,flip);
-#ifdef IGL_MESH_BOOLEAN_DEBUG
-  for(int f = 0;f<I.size();f++)
-  {
-    cout<<I(f)<<"\t"<<flip(f)<<endl;
-  }
-#endif
+  peel_outer_hull_layers(EV,CF,I,flip);
   // 0 is "first" iteration, so it's odd
   Array<bool,Dynamic,1> odd = igl::mod(I,2).array()==0;
 
@@ -257,6 +249,14 @@ IGL_INLINE void igl::boolean::mesh_boolean(
     G.row(g) = Gflip[g] ? CF.row(vG[g]).reverse().eval() : CF.row(vG[g]);
     GJ(g) = CJ(vG[g]);
   }
+#ifdef IGL_MESH_BOOLEAN_DEBUG
+  {
+    MatrixXi O;
+    boundary_facets(FC,O);
+    cout<<"# boundary: "<<O.rows()<<endl;
+  }
+  cout<<"# exterior: "<<exterior_edges(FC).rows()<<endl;
+#endif
 #ifdef IGL_MESH_BOOLEAN_DEBUG
   cout<<"clean..."<<endl;
 #endif
@@ -270,6 +270,7 @@ IGL_INLINE void igl::boolean::mesh_boolean(
     vector<vector<Index> > uG2G(uG.rows());
     // signed counts
     VectorXi counts = VectorXi::Zero(uG.rows());
+    VectorXi ucounts = VectorXi::Zero(uG.rows());
     // loop over all faces
     for(Index g = 0;g<gm;g++)
     {
@@ -282,6 +283,7 @@ IGL_INLINE void igl::boolean::mesh_boolean(
         (G(g,0) == uG(ug,1) && G(g,1) == uG(ug,2) && G(g,2) == uG(ug,0)) ||
         (G(g,0) == uG(ug,2) && G(g,1) == uG(ug,0) && G(g,2) == uG(ug,1));
       counts(ug) += consistent ? 1 : -1;
+      ucounts(ug)++;
     }
     MatrixX3I oldG = G;
     // Faces of output vG[i] = j means ith face of output should be jth face in
@@ -291,17 +293,33 @@ IGL_INLINE void igl::boolean::mesh_boolean(
     {
       // if signed occurrences is zero or ±two then keep none
       // else if signed occurrences is ±one then keep just one facet
-      if(abs(counts(ug)) == 1)
+      switch(abs(counts(ug)))
       {
-        assert(uG2G.size() > 0);
-        vG.push_back(uG2G[ug][0]);
-      }
+        case 1:
+          assert(uG2G[ug].size() > 0);
+          vG.push_back(uG2G[ug][0]);
 #ifdef IGL_MESH_BOOLEAN_DEBUG
-      else
-      {
-        cout<<"Skipping "<<uG2G[ug].size()<<" facets..."<<endl;
-      }
+          if(abs(ucounts(ug)) != 1)
+          {
+            cout<<"count,ucount of "<<counts(ug)<<","<<ucounts(ug)<<endl;
+          }
+#endif
+          break;
+        case 0:
+#ifdef IGL_MESH_BOOLEAN_DEBUG
+          cout<<"Skipping "<<uG2G[ug].size()<<" facets..."<<endl;
+          if(abs(ucounts(ug)) != 0)
+          {
+            cout<<"count,ucount of "<<counts(ug)<<","<<ucounts(ug)<<endl;
+          }
+#endif
+          break;
+        default:
+#ifdef IGL_MESH_BOOLEAN_DEBUG
+          cout<<"Didn't expect to be here."<<endl;
 #endif
+          assert(false && "Shouldn't count be -1/0/1 ?");
+      }
     }
     G.resize(vG.size(),3);
     J.resize(vG.size());
@@ -317,6 +335,14 @@ IGL_INLINE void igl::boolean::mesh_boolean(
   //cerr<<"warning not removing unref"<<endl;
   //VC = CV;
   //FC = G;
+#ifdef IGL_MESH_BOOLEAN_DEBUG
+  {
+    MatrixXi O;
+    boundary_facets(FC,O);
+    cout<<"# boundary: "<<O.rows()<<endl;
+  }
+  cout<<"# exterior: "<<exterior_edges(FC).rows()<<endl;
+#endif
 }
 
 #ifdef IGL_STATIC_LIBRARY
@@ -325,9 +351,10 @@ IGL_INLINE void igl::boolean::mesh_boolean(
 #include <igl/remove_unreferenced.cpp>
 template void igl::remove_unreferenced<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 #include <igl/cgal/peel_outer_hull_layers.cpp>
-template unsigned long igl::cgal::peel_outer_hull_layers<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<bool, -1, 1, 0, -1, 1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&);
+template unsigned long
+igl::cgal::peel_outer_hull_layers<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&);
 #include <igl/cgal/outer_hull.cpp>
-template void igl::cgal::outer_hull<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&);
+template void igl::cgal::outer_hull<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&);
 // Explicit template specialization
 template void igl::boolean::mesh_boolean<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, igl::boolean::MeshBooleanType const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::boolean::mesh_boolean<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, igl::boolean::MeshBooleanType const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);

+ 48 - 0
include/igl/boolean/string_to_mesh_boolean_type.cpp

@@ -0,0 +1,48 @@
+#include "string_to_mesh_boolean_type.h"
+#include <algorithm>
+#include <cassert>
+#include <vector>
+
+IGL_INLINE bool igl::boolean::string_to_mesh_boolean_type( 
+  const std::string & s,
+  MeshBooleanType & type)
+{
+  using namespace std;
+  string eff_s = s;
+  transform(eff_s.begin(), eff_s.end(), eff_s.begin(), ::tolower);
+  const auto & find_any = 
+    [](const vector<string> & haystack, const string & needle)->bool
+  {
+    return find(haystack.begin(), haystack.end(), needle) != haystack.end();
+  };
+  if(find_any({"union","unite","u","∪"},eff_s))
+  {
+    type = MESH_BOOLEAN_TYPE_UNION;
+  }else if(find_any({"intersect","intersection","i","∩"},eff_s))
+  {
+    type = MESH_BOOLEAN_TYPE_INTERSECT;
+  }else if(
+    find_any({"minus","subtract","difference","relative complement","m","\\"},eff_s))
+  {
+    type = MESH_BOOLEAN_TYPE_MINUS;
+  }else if(find_any({"xor","symmetric difference","x","∆"},eff_s))
+  {
+    type = MESH_BOOLEAN_TYPE_XOR;
+  }else if(find_any({"resolve"},eff_s))
+  {
+    type = MESH_BOOLEAN_TYPE_RESOLVE;
+  }else
+  {
+    return false;
+  }
+  return true;
+}
+
+IGL_INLINE igl::boolean::MeshBooleanType igl::boolean::string_to_mesh_boolean_type( 
+  const std::string & s)
+{
+  MeshBooleanType type;
+  const bool ret = string_to_mesh_boolean_type(s,type);
+  assert(ret && "Unknown MeshBooleanType name");
+  return type;
+}

+ 41 - 0
include/igl/boolean/string_to_mesh_boolean_type.h

@@ -0,0 +1,41 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_BOOLEAN_STRING_TO_MESH_BOOLEAN_H
+#define IGL_BOOLEAN_STRING_TO_MESH_BOOLEAN_H
+
+#include <igl/igl_inline.h>
+#include "MeshBooleanType.h"
+#include <string>
+
+namespace igl
+{
+  namespace boolean
+  {
+    // Convert string to boolean type
+    //
+    //  Inputs:
+    //    s  string identifying type, one of the following:
+    //      "union","intersect","minus","xor","resolve"
+    //  Outputs:
+    //    type  type of boolean operation
+    // Returns true only on success
+    //     
+    IGL_INLINE bool string_to_mesh_boolean_type(
+      const std::string & s,
+      MeshBooleanType & type);
+    // Returns type without error handling
+    IGL_INLINE MeshBooleanType string_to_mesh_boolean_type(
+      const std::string & s);
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "string_to_mesh_boolean_type.cpp"
+#endif
+
+#endif

+ 7 - 0
include/igl/cgal/assign_scalar.cpp

@@ -20,3 +20,10 @@ IGL_INLINE void igl::cgal::assign_scalar(
 {
   d = CGAL::to_double(cgal);
 }
+
+IGL_INLINE void igl::cgal::assign_scalar(
+  const double & c,
+  double & d)
+{
+  d = c;
+}

+ 3 - 0
include/igl/cgal/assign_scalar.h

@@ -23,6 +23,9 @@ namespace igl
     IGL_INLINE void assign_scalar(
       const typename CGAL::Epeck::FT & cgal,
       double & d);
+    IGL_INLINE void assign_scalar(
+      const double & c,
+      double & d);
   }
 }
 #ifndef IGL_STATIC_LIBRARY

+ 15 - 3
include/igl/cgal/mesh_to_cgal_triangle_list.cpp

@@ -6,6 +6,7 @@
 // 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 "mesh_to_cgal_triangle_list.h"
+#include "assign_scalar.h"
 
 #include <cassert>
 
@@ -22,6 +23,17 @@ IGL_INLINE void igl::cgal::mesh_to_cgal_triangle_list(
   typedef CGAL::Triangle_3<Kernel> Triangle_3; 
   // Must be 3D
   assert(V.cols() == 3);
+  // **Copy** to convert to output type (this is especially/only needed if the
+  // input type DerivedV::Scalar is CGAL::Epeck
+  Eigen::Matrix<
+    typename Kernel::FT,
+    DerivedV::RowsAtCompileTime,
+    DerivedV::ColsAtCompileTime> 
+    KV(V.rows(),V.cols());
+  for(int i = 0;i<V.size();i++)
+  {
+    assign_scalar(*(V.data()+i),*(KV.data()+i));
+  }
   // Must be triangles
   assert(F.cols() == 3);
   T.reserve(F.rows());
@@ -30,9 +42,9 @@ IGL_INLINE void igl::cgal::mesh_to_cgal_triangle_list(
   {
     T.push_back(
       Triangle_3(
-        Point_3( V(F(f,0),0), V(F(f,0),1), V(F(f,0),2)),
-        Point_3( V(F(f,1),0), V(F(f,1),1), V(F(f,1),2)),
-        Point_3( V(F(f,2),0), V(F(f,2),1), V(F(f,2),2))));
+        Point_3( KV(F(f,0),0), KV(F(f,0),1), KV(F(f,0),2)),
+        Point_3( KV(F(f,1),0), KV(F(f,1),1), KV(F(f,1),2)),
+        Point_3( KV(F(f,2),0), KV(F(f,2),1), KV(F(f,2),2))));
   }
 }
 

+ 211 - 0
include/igl/cgal/order_facets_around_edge.cpp

@@ -0,0 +1,211 @@
+#include "order_facets_around_edge.h"
+#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+
+namespace igl {
+    namespace cgal {
+        namespace order_facets_around_edges_helper {
+            template<typename T>
+            std::vector<size_t> index_sort(const std::vector<T>& data) {
+                const size_t len = data.size();
+                std::vector<size_t> order(len);
+                for (size_t i=0; i<len; i++) order[i] = i;
+
+                auto comp = [&](size_t i, size_t j) {
+                    return data[i] < data[j];
+                };
+                std::sort(order.begin(), order.end(), comp);
+                return order;
+            }
+        }
+    }
+}
+
+// adj_faces contains signed index starting from +- 1.
+template<
+    typename DerivedV,
+    typename DerivedF,
+    typename DerivedI >
+void igl::cgal::order_facets_around_edge(
+    const Eigen::PlainObjectBase<DerivedV>& V,
+    const Eigen::PlainObjectBase<DerivedF>& F,
+    size_t s, size_t d, 
+    const std::vector<int>& adj_faces,
+    Eigen::PlainObjectBase<DerivedI>& order) {
+
+    using namespace igl::cgal::order_facets_around_edges_helper;
+
+    // Although we only need exact predicates in the algorithm,
+    // exact constructions are needed to avoid degeneracies due to
+    // casting to double.
+    typedef CGAL::Exact_predicates_exact_constructions_kernel K;
+    typedef K::Point_3 Point_3;
+    typedef K::Plane_3 Plane_3;
+
+    auto get_face_index = [&](int adj_f)->size_t{
+        return abs(adj_f) - 1;
+    };
+
+    auto get_opposite_vertex = [&](size_t fid)->size_t {
+        if (F(fid, 0) != s && F(fid, 0) != d) return F(fid, 0);
+        if (F(fid, 1) != s && F(fid, 1) != d) return F(fid, 1);
+        if (F(fid, 2) != s && F(fid, 2) != d) return F(fid, 2);
+        assert(false);
+        return -1;
+    };
+
+    // Handle base cases
+    if (adj_faces.size() == 0) {
+        order.resize(0, 1);
+        return;
+    } else if (adj_faces.size() == 1) {
+        order.resize(1, 1);
+        order(0, 0) = 0;
+        return;
+    } else if (adj_faces.size() == 2) {
+        const size_t o1 =
+            get_opposite_vertex(get_face_index(adj_faces[0]));
+        const size_t o2 =
+            get_opposite_vertex(get_face_index(adj_faces[1]));
+        const Point_3 ps(V(s, 0), V(s, 1), V(s, 2));
+        const Point_3 pd(V(d, 0), V(d, 1), V(d, 2));
+        const Point_3 p1(V(o1, 0), V(o1, 1), V(o1, 2));
+        const Point_3 p2(V(o2, 0), V(o2, 1), V(o2, 2));
+        order.resize(2, 1);
+        switch (CGAL::orientation(ps, pd, p1, p2)) {
+            case CGAL::POSITIVE:
+                order(0, 0) = 1;
+                order(1, 0) = 0;
+                break;
+            case CGAL::NEGATIVE:
+                order(0, 0) = 0;
+                order(1, 0) = 1;
+                break;
+            case CGAL::COPLANAR:
+                order(0, 0) = adj_faces[0] < adj_faces[1] ? 0:1;
+                order(1, 0) = adj_faces[0] < adj_faces[1] ? 1:0;
+                break;
+            default:
+                assert(false);
+        }
+        return;
+    }
+
+    const size_t num_adj_faces = adj_faces.size();
+    const size_t o = get_opposite_vertex(
+            get_face_index(adj_faces[0]));
+    const Point_3 p_s(V(s, 0), V(s, 1), V(s, 2));
+    const Point_3 p_d(V(d, 0), V(d, 1), V(d, 2));
+    const Point_3 p_o(V(o, 0), V(o, 1), V(o, 2));
+    const Plane_3 separator(p_s, p_d, p_o);
+    assert(!separator.is_degenerate());
+
+    std::vector<Point_3> opposite_vertices;
+    for (size_t i=0; i<num_adj_faces; i++) {
+        const size_t o = get_opposite_vertex(
+                get_face_index(adj_faces[i]));
+        opposite_vertices.emplace_back(
+                V(o, 0), V(o, 1), V(o, 2));
+    }
+
+    std::vector<int> positive_side;
+    std::vector<int> negative_side;
+    std::vector<int> tie_positive_oriented;
+    std::vector<int> tie_negative_oriented;
+
+    std::vector<size_t> positive_side_index;
+    std::vector<size_t> negative_side_index;
+    std::vector<size_t> tie_positive_oriented_index;
+    std::vector<size_t> tie_negative_oriented_index;
+
+    for (size_t i=0; i<num_adj_faces; i++) {
+        const int f = adj_faces[i];
+        const Point_3& p_a = opposite_vertices[i];
+        auto orientation = separator.oriented_side(p_a);
+        switch (orientation) {
+            case CGAL::ON_POSITIVE_SIDE:
+                positive_side.push_back(f);
+                positive_side_index.push_back(i);
+                break;
+            case CGAL::ON_NEGATIVE_SIDE:
+                negative_side.push_back(f);
+                negative_side_index.push_back(i);
+                break;
+            case CGAL::ON_ORIENTED_BOUNDARY:
+                {
+                    const Plane_3 other(p_s, p_d, p_a);
+                    const auto target_dir = separator.orthogonal_direction();
+                    const auto query_dir = other.orthogonal_direction();
+                    if (target_dir == query_dir) {
+                        tie_positive_oriented.push_back(f);
+                        tie_positive_oriented_index.push_back(i);
+                    } else if (target_dir == -query_dir) {
+                        tie_negative_oriented.push_back(f);
+                        tie_negative_oriented_index.push_back(i);
+                    } else {
+                        assert(false);
+                    }
+                }
+                break;
+            default:
+                // Should not be here.
+                assert(false);
+        }
+    }
+
+    Eigen::PlainObjectBase<DerivedI> positive_order, negative_order;
+    order_facets_around_edge(V, F, s, d, positive_side, positive_order);
+    order_facets_around_edge(V, F, s, d, negative_side, negative_order);
+    std::vector<size_t> tie_positive_order =
+        index_sort(tie_positive_oriented);
+    std::vector<size_t> tie_negative_order =
+        index_sort(tie_negative_oriented);
+
+    // Copy results into order vector.
+    const size_t tie_positive_size = tie_positive_oriented.size();
+    const size_t tie_negative_size = tie_negative_oriented.size();
+    const size_t positive_size = positive_order.size();
+    const size_t negative_size = negative_order.size();
+
+    order.resize(tie_positive_size + positive_size +
+            tie_negative_size + negative_size, 1);
+
+    size_t count=0;
+    for (size_t i=0; i<tie_positive_size; i++) {
+        order(count+i, 0) =
+            tie_positive_oriented_index[tie_positive_order[i]];
+    }
+    count += tie_positive_size;
+
+    for (size_t i=0; i<negative_size; i++) {
+        order(count+i, 0) = negative_side_index[negative_order(i, 0)];
+    }
+    count += negative_size;
+
+    for (size_t i=0; i<tie_negative_size; i++) {
+        order(count+i, 0) =
+            tie_negative_oriented_index[tie_negative_order[i]];
+    }
+    count += tie_negative_size;
+
+    for (size_t i=0; i<positive_size; i++) {
+        order(count+i, 0) = positive_side_index[positive_order(i, 0)];
+    }
+    count += positive_size;
+    assert(count == num_adj_faces);
+
+    // Find the correct start point.
+    size_t start_idx = 0;
+    for (size_t i=0; i<num_adj_faces; i++) {
+        const Point_3& p_a = opposite_vertices[order(i, 0)];
+        const Point_3& p_b =
+            opposite_vertices[order((i+1)%num_adj_faces, 0)];
+        if (CGAL::orientation(p_s, p_d, p_a, p_b) == CGAL::POSITIVE) {
+            start_idx = (i+1)%num_adj_faces;
+            break;
+        }
+    }
+    DerivedI circular_order = order;
+    for (size_t i=0; i<num_adj_faces; i++) {
+        order(i, 0) = circular_order((start_idx + i)%num_adj_faces, 0);
+    }
+}

+ 53 - 0
include/igl/cgal/order_facets_around_edge.h

@@ -0,0 +1,53 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Qingnan Zhou <qnzhou@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+//
+#ifndef ORDER_FACETS_AROUND_EDGE_H
+#define ORDER_FACETS_AROUND_EDGE_H
+#include "../igl_inline.h"
+#include <Eigen/Core>
+#include <vector>
+
+namespace igl {
+    namespace cgal {
+        // Given a directed edge, sort its adjacent faces.  Assuming the
+        // directed edge is (s, d).  Sort the adjacent faces clockwise around the
+        // axis (d - s), i.e. left-hand rule.  An adjacent face is consistently
+        // oriented if it contains (d, s) as a directed edge.
+        //
+        // For overlapping faces, break the tie using signed face index, smaller
+        // signed index comes before the larger signed index.  Signed index is
+        // computed as (consistent? 1:-1) * (face_index + 1).
+        //
+        // Inputs:
+        //   V          #V by 3 list of vertices.
+        //   F          #F by 3 list of faces
+        //   s          Index of source vertex.
+        //   d          Index of desination vertex.
+        //   adj_faces  List of adjacent face signed indices.
+        //
+        // Output:
+        //   order      List of face indices that orders adjacent faces around
+        //              edge (s, d) clockwise.
+        template<
+            typename DerivedV,
+            typename DerivedF,
+            typename DerivedI >
+        IGL_INLINE
+        void order_facets_around_edge(
+                const Eigen::PlainObjectBase<DerivedV>& V,
+                const Eigen::PlainObjectBase<DerivedF>& F,
+                size_t s, size_t d, 
+                const std::vector<int>& adj_faces,
+                Eigen::PlainObjectBase<DerivedI>& order);
+    }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#include "order_facets_around_edge.cpp"
+#endif
+#endif

+ 78 - 0
include/igl/cgal/order_facets_around_edges.cpp

@@ -6,6 +6,7 @@
 // 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 "order_facets_around_edges.h"
+#include "order_facets_around_edge.h"
 #include "../sort_angles.h"
 #include <type_traits>
 #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
@@ -252,3 +253,80 @@ igl::cgal::order_facets_around_edges(
         }
     }
 }
+
+template<
+    typename DerivedV,
+    typename DerivedF,
+    typename DerivedE,
+    typename DeriveduE,
+    typename DerivedEMAP,
+    typename uE2EType,
+    typename uE2oEType,
+    typename uE2CType >
+IGL_INLINE void igl::cgal::order_facets_around_edges(
+        const Eigen::PlainObjectBase<DerivedV>& V,
+        const Eigen::PlainObjectBase<DerivedF>& F,
+        const Eigen::PlainObjectBase<DerivedE>& E,
+        const Eigen::PlainObjectBase<DeriveduE>& uE,
+        const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
+        const std::vector<std::vector<uE2EType> >& uE2E,
+        std::vector<std::vector<uE2oEType> >& uE2oE,
+        std::vector<std::vector<uE2CType > >& uE2C ) {
+
+    typedef Eigen::Matrix<typename DerivedV::Scalar, 3, 1> Vector3E;
+    const size_t num_faces = F.rows();
+    const size_t num_undirected_edges = uE.rows();
+
+    auto edge_index_to_face_index = [&](size_t ei) { return ei % num_faces; };
+    auto edge_index_to_corner_index = [&](size_t ei) { return ei / num_faces; };
+
+    uE2oE.resize(num_undirected_edges);
+    uE2C.resize(num_undirected_edges);
+
+    for(size_t ui = 0;ui<num_undirected_edges;ui++)
+    {
+        const auto& adj_edges = uE2E[ui];
+        const size_t edge_valance = adj_edges.size();
+        assert(edge_valance > 0);
+
+        const auto ref_edge = adj_edges[0];
+        const auto ref_face = edge_index_to_face_index(ref_edge);
+
+        const auto ref_corner_o = edge_index_to_corner_index(ref_edge);
+        const auto ref_corner_s = (ref_corner_o+1)%3;
+        const auto ref_corner_d = (ref_corner_o+2)%3;
+
+        const typename DerivedF::Scalar o = F(ref_face, ref_corner_o);
+        const typename DerivedF::Scalar s = F(ref_face, ref_corner_s);
+        const typename DerivedF::Scalar d = F(ref_face, ref_corner_d);
+
+        std::vector<bool> cons(edge_valance);
+        std::vector<int> adj_faces(edge_valance);
+        for (size_t fei=0; fei<edge_valance; fei++) {
+            const auto fe = adj_edges[fei];
+            const auto f = edge_index_to_face_index(fe);
+            const auto c = edge_index_to_corner_index(fe);
+            cons[fei] = (d == F(f, (c+1)%3));
+            adj_faces[fei] = (f+1) * (cons[fei] ? 1:-1);
+
+            assert( cons[fei] ||  (d == F(f,(c+2)%3)));
+            assert(!cons[fei] || (s == F(f,(c+2)%3)));
+            assert(!cons[fei] || (d == F(f,(c+1)%3)));
+        }
+
+        Eigen::VectorXi order;
+        order_facets_around_edge(V, F, s, d, adj_faces, order);
+        assert(order.size() == edge_valance);
+
+        auto& ordered_edges = uE2oE[ui];
+        auto& consistency = uE2C[ui];
+
+        ordered_edges.resize(edge_valance);
+        consistency.resize(edge_valance);
+        for (size_t fei=0; fei<edge_valance; fei++) {
+            ordered_edges[fei] = adj_edges[order[fei]];
+            consistency[fei] = cons[order[fei]];
+        }
+    }
+}
+

+ 30 - 1
include/igl/cgal/order_facets_around_edges.h

@@ -10,12 +10,20 @@
 #include "../igl_inline.h"
 #include <Eigen/Core>
 #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+#include <vector>
 
 namespace igl
 {
   namespace cgal
   {
-    // For each undirected edge, sort its adjacent faces.
+    // For each undirected edge, sort its adjacent faces.  Assuming the
+    // undirected edge is (s, d).  Sort the adjacent faces clockwise around the
+    // axis (d - s), i.e. left-hand rule.  An adjacent face is consistently
+    // oriented if it contains (d, s) as a directed edge.
+    //
+    // For overlapping faces, break the tie using signed face index, smaller
+    // signed index comes before the larger signed index.  Signed index is
+    // computed as (consistent? 1:-1) * index.
     //
     // Inputs:
     //   V    #V by 3 list of vertices.
@@ -79,6 +87,27 @@ namespace igl
             const std::vector<std::vector<uE2EType> >& uE2E,
             std::vector<std::vector<uE2oEType> >& uE2oE,
             std::vector<std::vector<uE2CType > >& uE2C );
+
+    // Order faces around each edge. Only exact predicate is used in the algorithm.
+    // Normal is not needed.
+    template<
+        typename DerivedV,
+        typename DerivedF,
+        typename DerivedE,
+        typename DeriveduE,
+        typename DerivedEMAP,
+        typename uE2EType,
+        typename uE2oEType,
+        typename uE2CType >
+    IGL_INLINE void order_facets_around_edges(
+            const Eigen::PlainObjectBase<DerivedV>& V,
+            const Eigen::PlainObjectBase<DerivedF>& F,
+            const Eigen::PlainObjectBase<DerivedE>& E,
+            const Eigen::PlainObjectBase<DeriveduE>& uE,
+            const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
+            const std::vector<std::vector<uE2EType> >& uE2E,
+            std::vector<std::vector<uE2oEType> >& uE2oE,
+            std::vector<std::vector<uE2CType > >& uE2C );
   }
 }
 

+ 74 - 0
include/igl/cgal/outer_facet.cpp

@@ -0,0 +1,74 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Qingnan Zhou <qnzhou@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "outer_facet.h"
+#include "../outer_element.h"
+#include "order_facets_around_edge.h"
+#include <algorithm>
+
+template<
+    typename DerivedV,
+    typename DerivedF,
+    typename DerivedI,
+    typename IndexType
+    >
+IGL_INLINE void igl::cgal::outer_facet(
+        const Eigen::PlainObjectBase<DerivedV> & V,
+        const Eigen::PlainObjectBase<DerivedF> & F,
+        const Eigen::PlainObjectBase<DerivedI> & I,
+        IndexType & f,
+        bool & flipped) {
+
+    // Algorithm:
+    //
+    //    1. Find an outer edge (s, d).
+    //
+    //    2. Order adjacent facets around this edge. Because the edge is an
+    //    outer edge, there exists a plane passing through it such that all its
+    //    adjacent facets lie on the same side. The implementation of
+    //    order_facets_around_edge() will find a natural start facet such that
+    //    The first and last facets according to this order are on the outside.
+    //
+    //    3. Because the vertex s is an outer vertex by construction (see
+    //    implemnetation of outer_edge()). The first adjacent facet is facing
+    //    outside (i.e. flipped=false) if it contains directed edge (s, d).  
+    //
+    typedef typename DerivedV::Scalar Scalar; typedef typename DerivedV::Index
+        Index; const size_t INVALID = std::numeric_limits<size_t>::max();
+
+    Index s,d;
+    Eigen::Matrix<Index,Eigen::Dynamic,1> incident_faces;
+    outer_edge(V, F, I, s, d, incident_faces);
+    assert(incident_faces.size() > 0);
+
+    auto convert_to_signed_index = [&](size_t fid) -> int{
+        if ((F(fid, 0) == s && F(fid, 1) == d) ||
+            (F(fid, 1) == s && F(fid, 2) == d) ||
+            (F(fid, 2) == s && F(fid, 0) == d) ) {
+            return int(fid+1) * -1;
+        } else {
+            return int(fid+1);
+        }
+    };
+
+    auto signed_index_to_index = [&](int signed_id) -> size_t {
+        return size_t(abs(signed_id) - 1);
+    };
+
+    std::vector<int> adj_faces(incident_faces.size());
+    std::transform(incident_faces.data(),
+            incident_faces.data() + incident_faces.size(),
+            adj_faces.begin(),
+            convert_to_signed_index);
+
+    Eigen::VectorXi order;
+    order_facets_around_edge(V, F, s, d, adj_faces, order);
+
+    f = signed_index_to_index(adj_faces[order[0]]);
+    flipped = adj_faces[order[0]] > 0;
+}

+ 55 - 0
include/igl/cgal/outer_facet.h

@@ -0,0 +1,55 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Qingnan Zhou <qnzhou@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef IGL_CGAL_OUTER_FACET_H
+#define IGL_CGAL_OUTER_FACET_H
+#include "../igl_inline.h"
+#include <Eigen/Core>
+
+namespace igl
+{
+    namespace cgal
+    {
+        // Find a facet that is reachable from infinity without crossing any faces.
+        // Such facet is called "outer facet."
+        //
+        // Precondition: The input mesh must have all self-intersection resolved.  I.e
+        // there is no duplicated vertices, no overlapping edge and no intersecting
+        // faces (the only exception is there could be topologically duplicated faces).
+        // See cgal::remesh_self_intersections.h for how to obtain such input.
+        //
+        // This function differ from igl::outer_facet() in the fact this
+        // funciton is more robust because it does not rely on facet normals.
+        //
+        // Inputs:
+        //   V  #V by 3 list of vertex positions
+        //   F  #F by 3 list of triangle indices into V
+        //   I  #I list of facets to consider
+        // Outputs:
+        //   f  Index of the outer facet.
+        //   flipped  true iff the normal of f points inwards.
+        template<
+            typename DerivedV,
+            typename DerivedF,
+            typename DerivedI,
+            typename IndexType
+            >
+        IGL_INLINE void outer_facet(
+                const Eigen::PlainObjectBase<DerivedV> & V,
+                const Eigen::PlainObjectBase<DerivedF> & F,
+                const Eigen::PlainObjectBase<DerivedI> & I,
+                IndexType & f,
+                bool & flipped);
+    }
+
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "outer_facet.cpp"
+#endif
+#endif

+ 3 - 106
include/igl/cgal/outer_hull.cpp

@@ -7,7 +7,7 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "outer_hull.h"
 #include "order_facets_around_edges.h"
-#include "../outer_element.h"
+#include "outer_facet.h"
 #include "../sortrows.h"
 #include "../facet_components.h"
 #include "../winding_number.h"
@@ -30,14 +30,12 @@
 template <
   typename DerivedV,
   typename DerivedF,
-  typename DerivedN,
   typename DerivedG,
   typename DerivedJ,
   typename Derivedflip>
 IGL_INLINE void igl::cgal::outer_hull(
   const Eigen::PlainObjectBase<DerivedV> & V,
   const Eigen::PlainObjectBase<DerivedF> & F,
-  const Eigen::PlainObjectBase<DerivedN> & N,
   Eigen::PlainObjectBase<DerivedG> & G,
   Eigen::PlainObjectBase<DerivedJ> & J,
   Eigen::PlainObjectBase<Derivedflip> & flip)
@@ -53,7 +51,6 @@ IGL_INLINE void igl::cgal::outer_hull(
   typedef Matrix<typename DerivedF::Scalar,Dynamic,DerivedF::ColsAtCompileTime> MatrixXF;
   typedef Matrix<typename DerivedG::Scalar,Dynamic,DerivedG::ColsAtCompileTime> MatrixXG;
   typedef Matrix<typename DerivedJ::Scalar,Dynamic,DerivedJ::ColsAtCompileTime> MatrixXJ;
-  typedef Matrix<typename DerivedN::Scalar,1,3> RowVector3N;
   const Index m = F.rows();
 
   // UNUSED:
@@ -94,7 +91,7 @@ IGL_INLINE void igl::cgal::outer_hull(
 
   std::vector<std::vector<typename DerivedF::Index> > uE2oE;
   std::vector<std::vector<bool> > uE2C;
-  order_facets_around_edges(V, F, N, E, uE, EMAP, uE2E, uE2oE, uE2C);
+  order_facets_around_edges(V, F, E, uE, EMAP, uE2E, uE2oE, uE2C);
   uE2E = uE2oE;
   VectorXI diIM(3*m);
   for (auto ue : uE2E) {
@@ -160,7 +157,7 @@ IGL_INLINE void igl::cgal::outer_hull(
 #ifdef IGL_OUTER_HULL_DEBUG
   cout<<"outer facet..."<<endl;
 #endif
-    outer_facet(V,F,N,IM,f,f_flip);
+  igl::cgal::outer_facet(V,F,IM,f,f_flip);
 #ifdef IGL_OUTER_HULL_DEBUG
   cout<<"outer facet: "<<f<<endl;
   //cout << V.row(F(f, 0)) << std::endl;
@@ -223,19 +220,6 @@ IGL_INLINE void igl::cgal::outer_hull(
               << uE2E[EMAP(e)][i] % m * (uE2C[EMAP(e)][i] ? 1:-1) << ")" << std::endl;
       }
 #endif
-      //// find overlapping face-edges
-      //const auto & neighbors = uE2E[EMAP(e)];
-      //// normal after possible flipping
-      //const auto & fN = (flip(f)?-1.:1.)*N.row(f);
-      //// Edge vector according to f's (flipped) orientation.
-      ////const auto & eV = (V.row(fd)-V.row(fs)).normalized();
-
-//#warning "EXPERIMENTAL, DO NOT USE"
-      //// THIS IS WRONG! The first face is---after sorting---no longer the face
-      //// used for orienting the sort.
-      //const auto ui = EMAP(e);
-      //const auto fe0 = uE2E[ui][0];
-      //const auto es = F(fe0%m,((fe0/m)+1)%3);
 
       // is edge consistent with edge of face used for sorting
       const int e_cons = (uE2C[EMAP(e)][diIM(e)] ? 1: -1);
@@ -245,11 +229,6 @@ IGL_INLINE void igl::cgal::outer_hull(
       {
         const int nfei_new = (diIM(e) + 2*val + e_cons*step*(flip(f)?-1:1))%val;
         const int nf = uE2E[EMAP(e)][nfei_new] % m;
-        // Don't consider faces with identical dihedral angles
-        //if ((di[EMAP(e)][diIM(e)].array() != di[EMAP(e)][nfei_new].array()).any())
-        //if((di[EMAP(e)][diIM(e)] != di[EMAP(e)][nfei_new]))
-//#warning "THIS IS HACK, FIX ME"
-//        if( abs(di[EMAP(e)][diIM(e)] - di[EMAP(e)][nfei_new]) < 1e-15 )
         {
 #ifdef IGL_OUTER_HULL_DEBUG
         //cout<<"Next facet: "<<(f+1)<<" --> "<<(nf+1)<<", |"<<
@@ -281,64 +260,6 @@ IGL_INLINE void igl::cgal::outer_hull(
       }
 
       int max_ne = -1;
-      //// Loop over and find max dihedral angle
-      //typename DerivedV::Scalar max_di = -1;
-      //for(const auto & ne : neighbors)
-      //{
-      //  const int nf = ne%m;
-      //  if(nf == f)
-      //  {
-      //    continue;
-      //  }
-      //  // Corner of neighbor
-      //  const int nc = ne/m;
-      //  // Is neighbor oriented consistently with (flipped) f?
-      //  //const int ns = F(nf,(nc+1)%3);
-      //  const int nd = F(nf,(nc+2)%3);
-      //  const bool cons = (flip(f)?fd:fs) == nd;
-      //  // Normal after possibly flipping to match flip or orientation of f
-      //  const auto & nN = (cons? (flip(f)?-1:1.) : (flip(f)?1.:-1.) )*N.row(nf);
-      //  // Angle between n and f
-      //  const auto & ndi = M_PI - atan2( fN.cross(nN).dot(eV), fN.dot(nN));
-      //  if(ndi>=max_di)
-      //  {
-      //    max_ne = ne;
-      //    max_di = ndi;
-      //  }
-      //}
-
-      ////cout<<(max_ne != max_ne_2)<<" =?= "<<e_cons<<endl;
-      //if(max_ne != max_ne_2)
-      //{
-      //  cout<<(f+1)<<" ---> "<<(max_ne%m)+1<<" != "<<(max_ne_2%m)+1<<" ... "<<e_cons<<" "<<flip(f)<<endl;
-      //  typename DerivedV::Scalar max_di = -1;
-      //  for(size_t nei = 0;nei<neighbors.size();nei++)
-      //  {
-      //    const auto & ne = neighbors[nei];
-      //    const int nf = ne%m;
-      //    if(nf == f)
-      //    {
-      //      cout<<"  "<<(ne%m)+1<<":\t"<<0<<"\t"<<di[EMAP[e]][nei]<<" "<<diIM(ne)<<endl;
-      //      continue;
-      //    }
-      //    // Corner of neighbor
-      //    const int nc = ne/m;
-      //    // Is neighbor oriented consistently with (flipped) f?
-      //    //const int ns = F(nf,(nc+1)%3);
-      //    const int nd = F(nf,(nc+2)%3);
-      //    const bool cons = (flip(f)?fd:fs) == nd;
-      //    // Normal after possibly flipping to match flip or orientation of f
-      //    const auto & nN = (cons? (flip(f)?-1:1.) : (flip(f)?1.:-1.) )*N.row(nf);
-      //    // Angle between n and f
-      //    const auto & ndi = M_PI - atan2( fN.cross(nN).dot(eV), fN.dot(nN));
-      //    cout<<"  "<<(ne%m)+1<<":\t"<<ndi<<"\t"<<di[EMAP[e]][nei]<<" "<<diIM(ne)<<endl;
-      //    if(ndi>=max_di)
-      //    {
-      //      max_ne = ne;
-      //      max_di = ndi;
-      //    }
-      //  }
-      //}
       if(nfei >= 0)
       {
         max_ne = uE2E[EMAP(e)][nfei];
@@ -513,33 +434,9 @@ IGL_INLINE void igl::cgal::outer_hull(
   }
 }
 
-template <
-  typename DerivedV,
-  typename DerivedF,
-  typename DerivedG,
-  typename DerivedJ,
-  typename Derivedflip>
-IGL_INLINE void igl::cgal::outer_hull(
-  const Eigen::PlainObjectBase<DerivedV> & V,
-  const Eigen::PlainObjectBase<DerivedF> & F,
-  Eigen::PlainObjectBase<DerivedG> & G,
-  Eigen::PlainObjectBase<DerivedJ> & J,
-  Eigen::PlainObjectBase<Derivedflip> & flip)
-{
-  Eigen::Matrix<typename DerivedV::Scalar,DerivedF::RowsAtCompileTime,3> N;
-  per_face_normals_stable(V,F,N);
-  return outer_hull(V,F,N,G,J,flip);
-}
-
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
-#undef IGL_STATIC_LIBRARY
-#include <igl/barycenter.cpp>
-#include <igl/outer_element.cpp>
-#include <igl/cgal/order_facets_around_edges.cpp>
-#define IGL_STATIC_LIBRARY
 template void igl::cgal::outer_hull<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&);
 template void igl::cgal::outer_hull<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template void igl::cgal::outer_hull<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&);
 #endif

+ 0 - 15
include/igl/cgal/outer_hull.h

@@ -25,26 +25,11 @@ namespace igl
     // Inputs:
     //   V  #V by 3 list of vertex positions
     //   F  #F by 3 list of triangle indices into V
-    //   N  #F by 3 list of per-face normals
     // Outputs:
     //   G  #G by 3 list of output triangle indices into V
     //   J  #G list of indices into F
     //   flip  #F list of whether facet was added to G **and** flipped orientation
     //     (false for faces not added to G)
-    template <
-      typename DerivedV,
-      typename DerivedF,
-      typename DerivedN,
-      typename DerivedG,
-      typename DerivedJ,
-      typename Derivedflip>
-    IGL_INLINE void outer_hull(
-      const Eigen::PlainObjectBase<DerivedV> & V,
-      const Eigen::PlainObjectBase<DerivedF> & F,
-      const Eigen::PlainObjectBase<DerivedN> & N,
-      Eigen::PlainObjectBase<DerivedG> & G,
-      Eigen::PlainObjectBase<DerivedJ> & J,
-      Eigen::PlainObjectBase<Derivedflip> & flip);
     template <
       typename DerivedV,
       typename DerivedF,

+ 13 - 31
include/igl/cgal/peel_outer_hull_layers.cpp

@@ -6,7 +6,6 @@
 // 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 "peel_outer_hull_layers.h"
-#include "../per_face_normals.h"
 #include "outer_hull.h"
 #include <vector>
 #include <iostream>
@@ -20,13 +19,11 @@
 template <
   typename DerivedV,
   typename DerivedF,
-  typename DerivedN,
   typename DerivedI,
   typename Derivedflip>
 IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
   const Eigen::PlainObjectBase<DerivedV > & V,
   const Eigen::PlainObjectBase<DerivedF > & F,
-  const Eigen::PlainObjectBase<DerivedN > & N,
   Eigen::PlainObjectBase<DerivedI> & I,
   Eigen::PlainObjectBase<Derivedflip > & flip)
 {
@@ -34,7 +31,6 @@ IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
   using namespace std;
   typedef typename DerivedF::Index Index;
   typedef Matrix<typename DerivedF::Scalar,Dynamic,DerivedF::ColsAtCompileTime> MatrixXF;
-  typedef Matrix<typename DerivedN::Scalar,Dynamic,DerivedN::ColsAtCompileTime> MatrixXN;
   typedef Matrix<Index,Dynamic,1> MatrixXI;
   typedef Matrix<typename Derivedflip::Scalar,Dynamic,Derivedflip::ColsAtCompileTime> MatrixXflip;
   const Index m = F.rows();
@@ -51,7 +47,6 @@ IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
 #endif
   // keep track of iteration parity and whether flipped in hull
   MatrixXF Fr = F;
-  MatrixXN Nr = N;
   I.resize(m,1);
   flip.resize(m,1);
   // Keep track of index map
@@ -67,15 +62,24 @@ IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
     MatrixXI Jo;
     MatrixXflip flipr;
 #ifdef IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
-  cout<<"calling outer hull..."<<endl;
-  writePLY(STR("outer-hull-input-"<<iter<<".ply"),V,Fr);
-  writeDMAT(STR("outer-hull-input-"<<iter<<".dmat"),Nr);
+  {
+      cout<<"calling outer hull..." << iter <<endl;
+      std::stringstream ss;
+      ss << "outer_hull_" << iter << ".ply";
+      Eigen::MatrixXd vertices(V.rows(), V.cols());
+      std::transform(V.data(), V.data() + V.rows()*V.cols(),
+              vertices.data(),
+              [](typename DerivedV::Scalar val)
+              {return CGAL::to_double(val); });
+      writePLY(ss.str(), vertices, Fr);
+  }
 #endif
-    outer_hull(V,Fr,Nr,Fo,Jo,flipr);
+    outer_hull(V,Fr,Fo,Jo,flipr);
 #ifdef IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
   writePLY(STR("outer-hull-output-"<<iter<<".ply"),V,Fo);
   cout<<"reindex, flip..."<<endl;
 #endif
+    assert(Fo.rows() != 0);
     assert(Fo.rows() == Jo.rows());
     // all faces in Fo of Fr
     vector<bool> in_outer(Fr.rows(),false);
@@ -89,10 +93,8 @@ IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
     // Fr = Fr - Fo
     // update IM
     MatrixXF prev_Fr = Fr;
-    MatrixXN prev_Nr = Nr;
     MatrixXI prev_IM = IM;
     Fr.resize(prev_Fr.rows() - Fo.rows(),F.cols());
-    Nr.resize(Fr.rows(),3);
     IM.resize(Fr.rows());
     {
       Index g = 0;
@@ -101,7 +103,6 @@ IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
         if(!in_outer[f])
         {
           Fr.row(g) = prev_Fr.row(f);
-          Nr.row(g) = prev_Nr.row(f);
           IM(g) = prev_IM(f);
           g++;
         }
@@ -112,26 +113,7 @@ IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
   return iter;
 }
 
-template <
-  typename DerivedV,
-  typename DerivedF,
-  typename DerivedI,
-  typename Derivedflip>
-IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
-  const Eigen::PlainObjectBase<DerivedV > & V,
-  const Eigen::PlainObjectBase<DerivedF > & F,
-  Eigen::PlainObjectBase<DerivedI > & I,
-  Eigen::PlainObjectBase<Derivedflip > & flip)
-{
-  using namespace std;
-  Eigen::Matrix<typename DerivedV::Scalar,DerivedF::RowsAtCompileTime,3> N;
-  per_face_normals(V,F,N);
-  return peel_outer_hull_layers(V,F,N,I,flip);
-}
-
-
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 template size_t igl::cgal::peel_outer_hull_layers<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template size_t igl::cgal::peel_outer_hull_layers<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 #endif

+ 0 - 13
include/igl/cgal/peel_outer_hull_layers.h

@@ -20,24 +20,11 @@ namespace igl
     // Inputs:
     //   V  #V by 3 list of vertex positions
     //   F  #F by 3 list of triangle indices into V
-    //   N  #F by 3 list of per-face normals
     // Outputs:
     //   I  #F list of which peel Iation a facet belongs 
     //   flip  #F list of whether a facet's orientation was flipped when facet
     //     "peeled" into its associated outer hull layer.
     // Returns number of peels
-    template <
-      typename DerivedV,
-      typename DerivedF,
-      typename DerivedN,
-      typename DerivedI,
-      typename Derivedflip>
-    IGL_INLINE size_t peel_outer_hull_layers(
-      const Eigen::PlainObjectBase<DerivedV > & V,
-      const Eigen::PlainObjectBase<DerivedF > & F,
-      const Eigen::PlainObjectBase<DerivedN > & N,
-      Eigen::PlainObjectBase<DerivedI > & I,
-      Eigen::PlainObjectBase<Derivedflip > & flip);
     template <
       typename DerivedV,
       typename DerivedF,

+ 5 - 1
include/igl/cgal/remesh_intersections.cpp

@@ -274,7 +274,11 @@ IGL_INLINE void igl::cgal::remesh_intersections(
   // incoming reps are different then the points are unique.
   for(Index v = 0;v<V.rows();v++)
   {
-    const Point_3 p(V(v,0),V(v,1),V(v,2));
+    typename Kernel::FT p0,p1,p2;
+    assign_scalar(V(v,0),p0);
+    assign_scalar(V(v,1),p1);
+    assign_scalar(V(v,2),p2);
+    const Point_3 p(p0,p1,p2);
     if(vv2i.count(p)==0)
     {
       vv2i[p] = v;

+ 1 - 2
include/igl/file_dialog_open.cpp

@@ -68,9 +68,8 @@ IGL_INLINE std::string igl::file_dialog_open()
       buffer[pos] = (char)ofn.lpstrFile[pos];
       pos++;
     }
-    buffer[pos] = 0;
   } 
-  
+  buffer[pos] = 0;
 #else
   
   // For linux use zenity

+ 2 - 2
include/igl/normal_derivative.cpp

@@ -64,7 +64,7 @@ IGL_INLINE void igl::normal_derivative(
           2);
       DDV *= S;
 
-      IJV.resize(DDV.size());
+      IJV.reserve(DDV.size());
       for(size_t f = 0;f<6*4;f++)
       {
         for(size_t e = 0;e<m;e++)
@@ -95,7 +95,7 @@ IGL_INLINE void igl::normal_derivative(
         slice(C,(VectorXi(12)<<1,1,2,2,2,2,0,0,0,0,1,1).finished(),2);
       DDV *= S;
 
-      IJV.resize(DDV.size());
+      IJV.reserve(DDV.size());
       for(size_t f = 0;f<12;f++)
       {
         for(size_t e = 0;e<m;e++)

+ 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
-
-

+ 24 - 4
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,12 @@ namespace viewer
 
     // Initialize IGL viewer
     init();
+    return EXIT_SUCCESS;
+  }
+
+  IGL_INLINE bool Viewer::launch_rendering(bool loop)
+  {
+    // glfwMakeContextCurrent(window);
 
     // Rendering loop
     while (!glfwWindowShouldClose(window))
@@ -841,8 +845,15 @@ namespace viewer
       {
         glfwWaitEvents();
       }
+
+      if (!loop)
+        return !glfwWindowShouldClose(window);
     }
+    return EXIT_SUCCESS;
+  }
 
+  IGL_INLINE void Viewer::launch_shut()
+  {
     opengl.free();
     core.shut();
 
@@ -850,6 +861,15 @@ namespace viewer
 
     glfwDestroyWindow(window);
     glfwTerminate();
+    return;
+  }
+
+  IGL_INLINE int Viewer::launch(bool resizable,bool fullscreen)
+  {
+    // TODO return values are being ignored...
+    launch_init(resizable,fullscreen);
+    launch_rendering(true);
+    launch_shut();
     return EXIT_SUCCESS;
   }
 } // 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));

+ 2 - 0
include/igl/viewer/ViewerCore.h

@@ -150,6 +150,8 @@ public:
   Eigen::Matrix4f view;
   Eigen::Matrix4f model;
   Eigen::Matrix4f proj;
+  public:
+      EIGEN_MAKE_ALIGNED_OPERATOR_NEW
 };
 
 }

+ 8 - 4
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));
@@ -114,7 +118,7 @@ IGL_INLINE void igl::viewer::ViewerData::set_mesh(const Eigen::MatrixXd& _V, con
       F = _F;
     }
     else
-      cerr << "ERROR (set_mesh): The new mesh has a different number of vertices/faces. Please clear the mesh before plotting.";
+      cerr << "ERROR (set_mesh): The new mesh has a different number of vertices/faces. Please clear the mesh before plotting."<<endl;
   }
   dirty |= DIRTY_FACE | DIRTY_POSITION;
 }
@@ -140,7 +144,7 @@ IGL_INLINE void igl::viewer::ViewerData::set_normals(const Eigen::MatrixXd& N)
     F_normals = N;
   }
   else
-    cerr << "ERROR (set_normals): Please provide a normal per face, per corner or per vertex.";
+    cerr << "ERROR (set_normals): Please provide a normal per face, per corner or per vertex."<<endl;
   dirty |= DIRTY_NORMAL;
 }
 
@@ -191,7 +195,7 @@ IGL_INLINE void igl::viewer::ViewerData::set_colors(const Eigen::MatrixXd &C)
     F_material_specular = specular(F_material_diffuse);
   }
   else
-    cerr << "ERROR (set_colors): Please provide a single color, or a color per face or per vertex.";
+    cerr << "ERROR (set_colors): Please provide a single color, or a color per face or per vertex."<<endl;;
   dirty |= DIRTY_DIFFUSE;
 
 }
@@ -205,7 +209,7 @@ IGL_INLINE void igl::viewer::ViewerData::set_uv(const Eigen::MatrixXd& UV)
     V_uv = UV;
   }
   else
-    cerr << "ERROR (set_UV): Please provide uv per vertex.";
+    cerr << "ERROR (set_UV): Please provide uv per vertex."<<endl;;
   dirty |= DIRTY_UV;
 }
 

+ 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"));

Some files were not shown because too many files changed in this diff