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/py_igl/todo
 python/build
 python/build
 python/.idea
 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
 url=https://github.com/libigl/nanogui.git
         fetchRecursiveSubmodules = true
         fetchRecursiveSubmodules = true
         ignore = dirty
         ignore = dirty
-
 [submodule "external/embree"]
 [submodule "external/embree"]
 	path = external/embree
 	path = external/embree
 	url = https://github.com/embree/embree.git
 	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
 header file contains a single function (e.g. `igl/cotmatrix.h` contains
 `igl::cotmatrix()`). Most are tailored to operate on a generic triangle mesh
 `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
 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
 _Optionally_ the library may also be [pre-compiled](optional/) into a statically
 linked library, for faster compile times with your projects. This only effects
 linked library, for faster compile times with your projects. This only effects
@@ -37,7 +37,7 @@ conversion table](matlab-to-eigen.html).
 ## Tutorial
 ## Tutorial
 
 
 As of version 1.0, libigl includes an introductory
 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
 ## 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
 them probably work just fine). This requires setting up unit testing, which is
 a major _todo_ for our development.
 a major _todo_ for our development.
 
 
-## Git Submodules 
+## Git Submodules
 Libigl uses git submodules for its _optional_ dependencies,
 Libigl uses git submodules for its _optional_ dependencies,
 in particular, those needed by the OpenGL viewer to run the examples in the
 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
 [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
  - 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
  - George Mason University, [CraGL](http://cs.gmu.edu/~ygingold/), USA
  - [Hong Kong University of Science and Technology](http://www.ust.hk/), 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
  - New York University, [Media Research Lab](http://mrl.nyu.edu/), USA
  - NYUPoly, [Game Innovation Lab](http://game.engineering.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
  - [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
 #ifndef IGL_AABB_H
 #define 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/Core>
 #include <Eigen/Geometry>
 #include <Eigen/Geometry>
 #include <vector>
 #include <vector>
 namespace igl
 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>
   template <typename DerivedV, int DIM>
     class AABB 
     class AABB 
     {
     {
@@ -75,9 +75,9 @@ public:
       AABB(AABB&& other):
       AABB(AABB&& other):
         // initialize via default constructor
         // initialize via default constructor
         AABB() 
         AABB() 
-    {
-      swap(*this,other);
-    }
+      {
+        swap(*this,other);
+      }
       // Seems like there should have been an elegant solution to this using
       // Seems like there should have been an elegant solution to this using
       // the copy-swap idiom above:
       // the copy-swap idiom above:
       inline void deinit()
       inline void deinit()

+ 3 - 1
include/igl/ConjugateFFSolverData.h

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

+ 1 - 1
include/igl/EPS.h

@@ -8,9 +8,9 @@
 #ifndef IGL_EPS_H
 #ifndef IGL_EPS_H
 #define IGL_EPS_H
 #define IGL_EPS_H
 #include "igl_inline.h"
 #include "igl_inline.h"
-// Define a standard value for double epsilon
 namespace igl
 namespace igl
 {
 {
+  // Define a standard value for double epsilon
   const double DOUBLE_EPS    = 1.0e-14;
   const double DOUBLE_EPS    = 1.0e-14;
   const double DOUBLE_EPS_SQ = 1.0e-28;
   const double DOUBLE_EPS_SQ = 1.0e-28;
   const float FLOAT_EPS    = 1.0e-7;
   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
 // 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
 // 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/.
 // obtain one at http://mozilla.org/MPL/2.0/.
-
 #ifndef IGL_HALFEDGEITERATOR_H
 #ifndef IGL_HALFEDGEITERATOR_H
 #define IGL_HALFEDGEITERATOR_H
 #define IGL_HALFEDGEITERATOR_H
 
 

+ 2 - 2
include/igl/IndexComparison.h

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

+ 4 - 0
include/igl/NormalType.h

@@ -10,6 +10,10 @@
 
 
 namespace igl
 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
   enum NormalType
   {
   {
     PER_VERTEX_NORMALS,
     PER_VERTEX_NORMALS,

+ 3 - 3
include/igl/ONE.h

@@ -7,11 +7,11 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #ifndef IGL_ONE_H
 #ifndef IGL_ONE_H
 #define 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
 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 char CHAR_ONE = 1;
   const int INT_ONE = 1;
   const int INT_ONE = 1;
   const unsigned int UNSIGNED_INT_ONE = 1;
   const unsigned int UNSIGNED_INT_ONE = 1;

+ 1 - 0
include/igl/Viewport.h

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

+ 5 - 2
include/igl/WindingNumberMethod.h

@@ -9,11 +9,14 @@
 #define IGL_WINDINGNUMBERMETHOD_H
 #define IGL_WINDINGNUMBERMETHOD_H
 namespace igl
 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
   enum WindingNumberMethod
   {
   {
-    EXACT_WINDING_NUMBER_METHOD = 0, // Exact hierarchical evaluation
+    EXACT_WINDING_NUMBER_METHOD = 0,
     APPROX_SIMPLE_WINDING_NUMBER_METHOD = 1,
     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
     NUM_WINDING_NUMBER_METHODS = 3
   };
   };
 }
 }

+ 7 - 3
include/igl/WindingNumberTree.h

@@ -12,9 +12,13 @@
 #include <Eigen/Dense>
 #include <Eigen/Dense>
 #include "WindingNumberMethod.h"
 #include "WindingNumberMethod.h"
 
 
-static Eigen::MatrixXd dummyV;
 namespace igl
 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:
   // Templates:
   //   Point  type for points in space, e.g. Eigen::Vector3d
   //   Point  type for points in space, e.g. Eigen::Vector3d
   template <typename Point>
   template <typename Point>
@@ -146,7 +150,7 @@ template <typename Point>
 inline igl::WindingNumberTree<Point>::WindingNumberTree():
 inline igl::WindingNumberTree<Point>::WindingNumberTree():
   method(EXACT_WINDING_NUMBER_METHOD),
   method(EXACT_WINDING_NUMBER_METHOD),
   parent(NULL),
   parent(NULL),
-  V(dummyV),
+  V(igl::dummyV),
   SV(),
   SV(),
   F(),
   F(),
   //boundary(igl::boundary_facets<Eigen::MatrixXi,Eigen::MatrixXi>(F))
   //boundary(igl::boundary_facets<Eigen::MatrixXi,Eigen::MatrixXi>(F))
@@ -162,7 +166,7 @@ inline igl::WindingNumberTree<Point>::WindingNumberTree(
   const Eigen::MatrixXi & _F):
   const Eigen::MatrixXi & _F):
   method(EXACT_WINDING_NUMBER_METHOD),
   method(EXACT_WINDING_NUMBER_METHOD),
   parent(NULL),
   parent(NULL),
-  V(dummyV),
+  V(igl::dummyV),
   SV(),
   SV(),
   F(),
   F(),
   //boundary(igl::boundary_facets<Eigen::MatrixXi,Eigen::MatrixXi>(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/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #ifndef IGL_ZERO_H
 #ifndef IGL_ZERO_H
 #define 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
 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 char CHAR_ZERO = 0;
   const int INT_ZERO = 0;
   const int INT_ZERO = 0;
   const unsigned int UNSIGNED_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
   // and further optionally subject to the linear inequality constraints that
   // Aieq*Z <= Bieq and constant inequality constraints lx <= x <= ux
   // Aieq*Z <= Bieq and constant inequality constraints lx <= x <= ux
   //
   //
-  // Templates:
   // Inputs:
   // Inputs:
   //   A  n by n matrix of quadratic coefficients
   //   A  n by n matrix of quadratic coefficients
   //   B  n by 1 column of linear 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
   // Benchmark: For a harmonic solve on a mesh with 325K facets, matlab 2.2
   // secs, igl/min_quad_with_fixed.h 7.1 secs
   // secs, igl/min_quad_with_fixed.h 7.1 secs
   //
   //
-
   template <
   template <
     typename AT, 
     typename AT, 
     typename DerivedB,
     typename DerivedB,

+ 1 - 1
include/igl/biharmonic_coordinates.cpp

@@ -142,7 +142,7 @@ IGL_INLINE bool igl::biharmonic_coordinates(
   // minimize    ½ W' A W'
   // minimize    ½ W' A W'
   // subject to  W(b,:) = J
   // subject to  W(b,:) = J
   return min_quad_with_fixed(
   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
 #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 
 // 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/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "mesh_boolean.h"
 #include "mesh_boolean.h"
+#include <igl/cgal/assign_scalar.h>
 #include <igl/per_face_normals.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/peel_outer_hull_layers.h>
 #include <igl/cgal/remesh_self_intersections.h>
 #include <igl/cgal/remesh_self_intersections.h>
 #include <igl/remove_unreferenced.h>
 #include <igl/remove_unreferenced.h>
@@ -103,7 +106,7 @@ IGL_INLINE void igl::boolean::mesh_boolean(
   using namespace igl::cgal;
   using namespace igl::cgal;
   MeshBooleanType eff_type = type;
   MeshBooleanType eff_type = type;
   // Concatenate A and B into a single mesh
   // 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 Kernel::FT ExactScalar;
   typedef typename DerivedVC::Scalar Scalar;
   typedef typename DerivedVC::Scalar Scalar;
   typedef typename DerivedFC::Scalar Index;
   typedef typename DerivedFC::Scalar Index;
@@ -176,7 +179,9 @@ IGL_INLINE void igl::boolean::mesh_boolean(
     CV.resize(EV.rows(), EV.cols());
     CV.resize(EV.rows(), EV.cols());
     std::transform(EV.data(), EV.data() + EV.rows()*EV.cols(),
     std::transform(EV.data(), EV.data() + EV.rows()*EV.cols(),
             CV.data(), [&](ExactScalar val) {
             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;
     J = CJ;
     return;
     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
 #ifdef IGL_MESH_BOOLEAN_DEBUG
   cout<<"peel..."<<endl;
   cout<<"peel..."<<endl;
@@ -202,13 +200,7 @@ IGL_INLINE void igl::boolean::mesh_boolean(
   // peel layers keeping track of odd and even flips
   // peel layers keeping track of odd and even flips
   VectorXi I;
   VectorXi I;
   Matrix<bool,Dynamic,1> flip;
   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
   // 0 is "first" iteration, so it's odd
   Array<bool,Dynamic,1> odd = igl::mod(I,2).array()==0;
   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]);
     G.row(g) = Gflip[g] ? CF.row(vG[g]).reverse().eval() : CF.row(vG[g]);
     GJ(g) = CJ(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
 #ifdef IGL_MESH_BOOLEAN_DEBUG
   cout<<"clean..."<<endl;
   cout<<"clean..."<<endl;
 #endif
 #endif
@@ -270,6 +270,7 @@ IGL_INLINE void igl::boolean::mesh_boolean(
     vector<vector<Index> > uG2G(uG.rows());
     vector<vector<Index> > uG2G(uG.rows());
     // signed counts
     // signed counts
     VectorXi counts = VectorXi::Zero(uG.rows());
     VectorXi counts = VectorXi::Zero(uG.rows());
+    VectorXi ucounts = VectorXi::Zero(uG.rows());
     // loop over all faces
     // loop over all faces
     for(Index g = 0;g<gm;g++)
     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,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));
         (G(g,0) == uG(ug,2) && G(g,1) == uG(ug,0) && G(g,2) == uG(ug,1));
       counts(ug) += consistent ? 1 : -1;
       counts(ug) += consistent ? 1 : -1;
+      ucounts(ug)++;
     }
     }
     MatrixX3I oldG = G;
     MatrixX3I oldG = G;
     // Faces of output vG[i] = j means ith face of output should be jth face in
     // 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
       // if signed occurrences is zero or ±two then keep none
       // else if signed occurrences is ±one then keep just one facet
       // 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
 #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
 #endif
+          assert(false && "Shouldn't count be -1/0/1 ?");
+      }
     }
     }
     G.resize(vG.size(),3);
     G.resize(vG.size(),3);
     J.resize(vG.size());
     J.resize(vG.size());
@@ -317,6 +335,14 @@ IGL_INLINE void igl::boolean::mesh_boolean(
   //cerr<<"warning not removing unref"<<endl;
   //cerr<<"warning not removing unref"<<endl;
   //VC = CV;
   //VC = CV;
   //FC = G;
   //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
 #ifdef IGL_STATIC_LIBRARY
@@ -325,9 +351,10 @@ IGL_INLINE void igl::boolean::mesh_boolean(
 #include <igl/remove_unreferenced.cpp>
 #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> >&);
 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>
 #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>
 #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
 // 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::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> >&);
 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);
   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(
     IGL_INLINE void assign_scalar(
       const typename CGAL::Epeck::FT & cgal,
       const typename CGAL::Epeck::FT & cgal,
       double & d);
       double & d);
+    IGL_INLINE void assign_scalar(
+      const double & c,
+      double & d);
   }
   }
 }
 }
 #ifndef IGL_STATIC_LIBRARY
 #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 
 // 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/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "mesh_to_cgal_triangle_list.h"
 #include "mesh_to_cgal_triangle_list.h"
+#include "assign_scalar.h"
 
 
 #include <cassert>
 #include <cassert>
 
 
@@ -22,6 +23,17 @@ IGL_INLINE void igl::cgal::mesh_to_cgal_triangle_list(
   typedef CGAL::Triangle_3<Kernel> Triangle_3; 
   typedef CGAL::Triangle_3<Kernel> Triangle_3; 
   // Must be 3D
   // Must be 3D
   assert(V.cols() == 3);
   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
   // Must be triangles
   assert(F.cols() == 3);
   assert(F.cols() == 3);
   T.reserve(F.rows());
   T.reserve(F.rows());
@@ -30,9 +42,9 @@ IGL_INLINE void igl::cgal::mesh_to_cgal_triangle_list(
   {
   {
     T.push_back(
     T.push_back(
       Triangle_3(
       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 
 // 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/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "order_facets_around_edges.h"
 #include "order_facets_around_edges.h"
+#include "order_facets_around_edge.h"
 #include "../sort_angles.h"
 #include "../sort_angles.h"
 #include <type_traits>
 #include <type_traits>
 #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
 #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 "../igl_inline.h"
 #include <Eigen/Core>
 #include <Eigen/Core>
 #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
 #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+#include <vector>
 
 
 namespace igl
 namespace igl
 {
 {
   namespace cgal
   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:
     // Inputs:
     //   V    #V by 3 list of vertices.
     //   V    #V by 3 list of vertices.
@@ -79,6 +87,27 @@ namespace igl
             const std::vector<std::vector<uE2EType> >& uE2E,
             const std::vector<std::vector<uE2EType> >& uE2E,
             std::vector<std::vector<uE2oEType> >& uE2oE,
             std::vector<std::vector<uE2oEType> >& uE2oE,
             std::vector<std::vector<uE2CType > >& uE2C );
             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/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "outer_hull.h"
 #include "outer_hull.h"
 #include "order_facets_around_edges.h"
 #include "order_facets_around_edges.h"
-#include "../outer_element.h"
+#include "outer_facet.h"
 #include "../sortrows.h"
 #include "../sortrows.h"
 #include "../facet_components.h"
 #include "../facet_components.h"
 #include "../winding_number.h"
 #include "../winding_number.h"
@@ -30,14 +30,12 @@
 template <
 template <
   typename DerivedV,
   typename DerivedV,
   typename DerivedF,
   typename DerivedF,
-  typename DerivedN,
   typename DerivedG,
   typename DerivedG,
   typename DerivedJ,
   typename DerivedJ,
   typename Derivedflip>
   typename Derivedflip>
 IGL_INLINE void igl::cgal::outer_hull(
 IGL_INLINE void igl::cgal::outer_hull(
   const Eigen::PlainObjectBase<DerivedV> & V,
   const Eigen::PlainObjectBase<DerivedV> & V,
   const Eigen::PlainObjectBase<DerivedF> & F,
   const Eigen::PlainObjectBase<DerivedF> & F,
-  const Eigen::PlainObjectBase<DerivedN> & N,
   Eigen::PlainObjectBase<DerivedG> & G,
   Eigen::PlainObjectBase<DerivedG> & G,
   Eigen::PlainObjectBase<DerivedJ> & J,
   Eigen::PlainObjectBase<DerivedJ> & J,
   Eigen::PlainObjectBase<Derivedflip> & flip)
   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 DerivedF::Scalar,Dynamic,DerivedF::ColsAtCompileTime> MatrixXF;
   typedef Matrix<typename DerivedG::Scalar,Dynamic,DerivedG::ColsAtCompileTime> MatrixXG;
   typedef Matrix<typename DerivedG::Scalar,Dynamic,DerivedG::ColsAtCompileTime> MatrixXG;
   typedef Matrix<typename DerivedJ::Scalar,Dynamic,DerivedJ::ColsAtCompileTime> MatrixXJ;
   typedef Matrix<typename DerivedJ::Scalar,Dynamic,DerivedJ::ColsAtCompileTime> MatrixXJ;
-  typedef Matrix<typename DerivedN::Scalar,1,3> RowVector3N;
   const Index m = F.rows();
   const Index m = F.rows();
 
 
   // UNUSED:
   // UNUSED:
@@ -94,7 +91,7 @@ IGL_INLINE void igl::cgal::outer_hull(
 
 
   std::vector<std::vector<typename DerivedF::Index> > uE2oE;
   std::vector<std::vector<typename DerivedF::Index> > uE2oE;
   std::vector<std::vector<bool> > uE2C;
   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;
   uE2E = uE2oE;
   VectorXI diIM(3*m);
   VectorXI diIM(3*m);
   for (auto ue : uE2E) {
   for (auto ue : uE2E) {
@@ -160,7 +157,7 @@ IGL_INLINE void igl::cgal::outer_hull(
 #ifdef IGL_OUTER_HULL_DEBUG
 #ifdef IGL_OUTER_HULL_DEBUG
   cout<<"outer facet..."<<endl;
   cout<<"outer facet..."<<endl;
 #endif
 #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
 #ifdef IGL_OUTER_HULL_DEBUG
   cout<<"outer facet: "<<f<<endl;
   cout<<"outer facet: "<<f<<endl;
   //cout << V.row(F(f, 0)) << std::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;
               << uE2E[EMAP(e)][i] % m * (uE2C[EMAP(e)][i] ? 1:-1) << ")" << std::endl;
       }
       }
 #endif
 #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
       // is edge consistent with edge of face used for sorting
       const int e_cons = (uE2C[EMAP(e)][diIM(e)] ? 1: -1);
       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 nfei_new = (diIM(e) + 2*val + e_cons*step*(flip(f)?-1:1))%val;
         const int nf = uE2E[EMAP(e)][nfei_new] % m;
         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
 #ifdef IGL_OUTER_HULL_DEBUG
         //cout<<"Next facet: "<<(f+1)<<" --> "<<(nf+1)<<", |"<<
         //cout<<"Next facet: "<<(f+1)<<" --> "<<(nf+1)<<", |"<<
@@ -281,64 +260,6 @@ IGL_INLINE void igl::cgal::outer_hull(
       }
       }
 
 
       int max_ne = -1;
       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)
       if(nfei >= 0)
       {
       {
         max_ne = uE2E[EMAP(e)][nfei];
         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
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // 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, 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<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
 #endif

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

@@ -25,26 +25,11 @@ namespace igl
     // Inputs:
     // Inputs:
     //   V  #V by 3 list of vertex positions
     //   V  #V by 3 list of vertex positions
     //   F  #F by 3 list of triangle indices into V
     //   F  #F by 3 list of triangle indices into V
-    //   N  #F by 3 list of per-face normals
     // Outputs:
     // Outputs:
     //   G  #G by 3 list of output triangle indices into V
     //   G  #G by 3 list of output triangle indices into V
     //   J  #G list of indices into F
     //   J  #G list of indices into F
     //   flip  #F list of whether facet was added to G **and** flipped orientation
     //   flip  #F list of whether facet was added to G **and** flipped orientation
     //     (false for faces not added to G)
     //     (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 <
     template <
       typename DerivedV,
       typename DerivedV,
       typename DerivedF,
       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 
 // 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/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "peel_outer_hull_layers.h"
 #include "peel_outer_hull_layers.h"
-#include "../per_face_normals.h"
 #include "outer_hull.h"
 #include "outer_hull.h"
 #include <vector>
 #include <vector>
 #include <iostream>
 #include <iostream>
@@ -20,13 +19,11 @@
 template <
 template <
   typename DerivedV,
   typename DerivedV,
   typename DerivedF,
   typename DerivedF,
-  typename DerivedN,
   typename DerivedI,
   typename DerivedI,
   typename Derivedflip>
   typename Derivedflip>
 IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
 IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
   const Eigen::PlainObjectBase<DerivedV > & V,
   const Eigen::PlainObjectBase<DerivedV > & V,
   const Eigen::PlainObjectBase<DerivedF > & F,
   const Eigen::PlainObjectBase<DerivedF > & F,
-  const Eigen::PlainObjectBase<DerivedN > & N,
   Eigen::PlainObjectBase<DerivedI> & I,
   Eigen::PlainObjectBase<DerivedI> & I,
   Eigen::PlainObjectBase<Derivedflip > & flip)
   Eigen::PlainObjectBase<Derivedflip > & flip)
 {
 {
@@ -34,7 +31,6 @@ IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
   using namespace std;
   using namespace std;
   typedef typename DerivedF::Index Index;
   typedef typename DerivedF::Index Index;
   typedef Matrix<typename DerivedF::Scalar,Dynamic,DerivedF::ColsAtCompileTime> MatrixXF;
   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<Index,Dynamic,1> MatrixXI;
   typedef Matrix<typename Derivedflip::Scalar,Dynamic,Derivedflip::ColsAtCompileTime> MatrixXflip;
   typedef Matrix<typename Derivedflip::Scalar,Dynamic,Derivedflip::ColsAtCompileTime> MatrixXflip;
   const Index m = F.rows();
   const Index m = F.rows();
@@ -51,7 +47,6 @@ IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
 #endif
 #endif
   // keep track of iteration parity and whether flipped in hull
   // keep track of iteration parity and whether flipped in hull
   MatrixXF Fr = F;
   MatrixXF Fr = F;
-  MatrixXN Nr = N;
   I.resize(m,1);
   I.resize(m,1);
   flip.resize(m,1);
   flip.resize(m,1);
   // Keep track of index map
   // Keep track of index map
@@ -67,15 +62,24 @@ IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
     MatrixXI Jo;
     MatrixXI Jo;
     MatrixXflip flipr;
     MatrixXflip flipr;
 #ifdef IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
 #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
 #endif
-    outer_hull(V,Fr,Nr,Fo,Jo,flipr);
+    outer_hull(V,Fr,Fo,Jo,flipr);
 #ifdef IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
 #ifdef IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
   writePLY(STR("outer-hull-output-"<<iter<<".ply"),V,Fo);
   writePLY(STR("outer-hull-output-"<<iter<<".ply"),V,Fo);
   cout<<"reindex, flip..."<<endl;
   cout<<"reindex, flip..."<<endl;
 #endif
 #endif
+    assert(Fo.rows() != 0);
     assert(Fo.rows() == Jo.rows());
     assert(Fo.rows() == Jo.rows());
     // all faces in Fo of Fr
     // all faces in Fo of Fr
     vector<bool> in_outer(Fr.rows(),false);
     vector<bool> in_outer(Fr.rows(),false);
@@ -89,10 +93,8 @@ IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
     // Fr = Fr - Fo
     // Fr = Fr - Fo
     // update IM
     // update IM
     MatrixXF prev_Fr = Fr;
     MatrixXF prev_Fr = Fr;
-    MatrixXN prev_Nr = Nr;
     MatrixXI prev_IM = IM;
     MatrixXI prev_IM = IM;
     Fr.resize(prev_Fr.rows() - Fo.rows(),F.cols());
     Fr.resize(prev_Fr.rows() - Fo.rows(),F.cols());
-    Nr.resize(Fr.rows(),3);
     IM.resize(Fr.rows());
     IM.resize(Fr.rows());
     {
     {
       Index g = 0;
       Index g = 0;
@@ -101,7 +103,6 @@ IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
         if(!in_outer[f])
         if(!in_outer[f])
         {
         {
           Fr.row(g) = prev_Fr.row(f);
           Fr.row(g) = prev_Fr.row(f);
-          Nr.row(g) = prev_Nr.row(f);
           IM(g) = prev_IM(f);
           IM(g) = prev_IM(f);
           g++;
           g++;
         }
         }
@@ -112,26 +113,7 @@ IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
   return iter;
   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
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // 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<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
 #endif

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

@@ -20,24 +20,11 @@ namespace igl
     // Inputs:
     // Inputs:
     //   V  #V by 3 list of vertex positions
     //   V  #V by 3 list of vertex positions
     //   F  #F by 3 list of triangle indices into V
     //   F  #F by 3 list of triangle indices into V
-    //   N  #F by 3 list of per-face normals
     // Outputs:
     // Outputs:
     //   I  #F list of which peel Iation a facet belongs 
     //   I  #F list of which peel Iation a facet belongs 
     //   flip  #F list of whether a facet's orientation was flipped when facet
     //   flip  #F list of whether a facet's orientation was flipped when facet
     //     "peeled" into its associated outer hull layer.
     //     "peeled" into its associated outer hull layer.
     // Returns number of peels
     // 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 <
     template <
       typename DerivedV,
       typename DerivedV,
       typename DerivedF,
       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.
   // incoming reps are different then the points are unique.
   for(Index v = 0;v<V.rows();v++)
   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)
     if(vv2i.count(p)==0)
     {
     {
       vv2i[p] = v;
       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];
       buffer[pos] = (char)ofn.lpstrFile[pos];
       pos++;
       pos++;
     }
     }
-    buffer[pos] = 0;
   } 
   } 
-  
+  buffer[pos] = 0;
 #else
 #else
   
   
   // For linux use zenity
   // For linux use zenity

+ 2 - 2
include/igl/normal_derivative.cpp

@@ -64,7 +64,7 @@ IGL_INLINE void igl::normal_derivative(
           2);
           2);
       DDV *= S;
       DDV *= S;
 
 
-      IJV.resize(DDV.size());
+      IJV.reserve(DDV.size());
       for(size_t f = 0;f<6*4;f++)
       for(size_t f = 0;f<6*4;f++)
       {
       {
         for(size_t e = 0;e<m;e++)
         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);
         slice(C,(VectorXi(12)<<1,1,2,2,2,2,0,0,0,0,1,1).finished(),2);
       DDV *= S;
       DDV *= S;
 
 
-      IJV.resize(DDV.size());
+      IJV.reserve(DDV.size());
       for(size_t f = 0;f<12;f++)
       for(size_t f = 0;f<12;f++)
       {
       {
         for(size_t e = 0;e<m;e++)
         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));
   const float eff_f = (f>=1.?1.:(f<=0.?0.:f));
   // continuous index into array
   // continuous index into array
   const float ff = eff_f*(PARULA_COLOR_MAP.rows()-1);
   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));
   const float t = (s==d ? 0. : (ff-s)/float(d-s));
 
 
   assert(t>=0 && t<=1);
   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)
 // 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>
 #include <type_traits>
@@ -45,16 +45,28 @@
 #define SERIALIZE_TYPE(Type,Params) \
 #define SERIALIZE_TYPE(Type,Params) \
 namespace igl { namespace serialization { \
 namespace igl { namespace serialization { \
   void _serialization(bool s,Type& obj,std::vector<char>& buffer) {Params} \
   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); \
     _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)); \
     _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
 namespace igl
 {
 {
@@ -101,21 +113,23 @@ namespace igl
   // Wrapper to expose both, the de- and serialization as one function
   // Wrapper to expose both, the de- and serialization as one function
   //
   //
   template <typename T>
   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>
   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>
   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()
   // User defined types have to either overload the function igl::serialization::serialize()
   // and igl::serialization::deserialize() for their type (non-intrusive serialization):
   // 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) {
   //   inline void serialize(const UserType& obj,std::vector<char>& buffer) {
   //     ::igl::serialize(obj.var,"var",buffer);
   //     ::igl::serialize(obj.var,"var",buffer);
   //   }
   //   }
-  //     
+  //
+  //   template<>
   //   inline void deserialize(UserType& obj,const std::vector<char>& buffer) {
   //   inline void deserialize(UserType& obj,const std::vector<char>& buffer) {
   //     ::igl::deserialize(obj.var,"var",buffer);
   //     ::igl::deserialize(obj.var,"var",buffer);
   //   }
   //   }
@@ -281,7 +295,7 @@ namespace igl
     template <typename T>
     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);
     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>
     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
     // stl containers
     // std::pair
     // std::pair
@@ -333,6 +347,13 @@ namespace igl
     template<typename T,int P,typename I>
     template<typename T,int P,typename I>
     inline void deserialize(Eigen::SparseMatrix<T,P,I>& obj,std::vector<char>::const_iterator& iter);
     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
     // raw pointers
     template <typename T>
     template <typename T>
     inline typename std::enable_if<std::is_pointer<T>::value,size_t>::type getByteSize(const T& obj);
     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
   // Wrapper function which combines both, de- and serialization
   template <typename T>
   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);
     return s ? serialize(obj,filename) : deserialize(obj,filename);
   }
   }
 
 
   template <typename T>
   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);
     return s ? serialize(obj,objectName,filename,overwrite) : deserialize(obj,objectName,filename);
   }
   }
 
 
   template <typename T>
   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);
     return s ? serialize(obj,objectName,buffer) : deserialize(obj,objectName,buffer);
   }
   }
@@ -627,7 +648,7 @@ namespace igl
   }
   }
 
 
   template <typename T>
   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>();
     auto object = new SerializationObject<T>();
     object->Binary = binary;
     object->Binary = binary;
@@ -650,7 +671,7 @@ namespace igl
     {
     {
       // data
       // data
       std::vector<char> tmp;
       std::vector<char> tmp;
-      serialize(obj,tmp);
+      serialize<>(obj,tmp);
 
 
       // size
       // size
       size_t size = buffer.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)
     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;
       std::vector<char>::size_type size;
-      serialization::deserialize(size,iter);
+      serialization::deserialize<>(size,iter);
 
 
       std::vector<char> tmp;
       std::vector<char> tmp;
       tmp.resize(size);
       tmp.resize(size);
       std::copy(iter,iter+size,tmp.begin());
       std::copy(iter,iter+size,tmp.begin());
 
 
-      deserialize(obj,tmp);
+      deserialize<>(obj,tmp);
       iter += size;
       iter += size;
     }
     }
 
 
@@ -1010,6 +1031,30 @@ namespace igl
       obj.setFromTriplets(triplets.begin(),triplets.end());
       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
     // pointers
 
 
     template <typename T>
     template <typename T>
@@ -1115,13 +1160,13 @@ namespace igl
     template <typename T>
     template <typename T>
     inline void serialize(const T& obj,std::vector<char>& buffer)
     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>
     template <typename T>
     inline void deserialize(T& obj,const std::vector<char>& buffer)
     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
     // helper functions

+ 9 - 10
include/igl/unique.cpp

@@ -1,9 +1,9 @@
 // This file is part of libigl, a simple c++ geometry processing library.
 // This file is part of libigl, a simple c++ geometry processing library.
-// 
+//
 // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
 // 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/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "unique.h"
 #include "unique.h"
 #include "sort.h"
 #include "sort.h"
@@ -97,9 +97,8 @@ IGL_INLINE void igl::unique(
 
 
 template <
 template <
   typename DerivedA,
   typename DerivedA,
-  typename DerivedC,
-  typename DerivedIA,
-  typename DerivedIC>
+  typename DerivedC
+  >
 IGL_INLINE void igl::unique(
 IGL_INLINE void igl::unique(
     const Eigen::PlainObjectBase<DerivedA> & A,
     const Eigen::PlainObjectBase<DerivedA> & A,
     Eigen::PlainObjectBase<DerivedC> & C)
     Eigen::PlainObjectBase<DerivedC> & C)
@@ -123,7 +122,7 @@ IGL_INLINE void igl::unique(
 //   Eigen::PlainObjectBase<DerivedIC>& IC)
 //   Eigen::PlainObjectBase<DerivedIC>& IC)
 // {
 // {
 //   using namespace std;
 //   using namespace std;
-// 
+//
 //   typedef Eigen::Matrix<typename DerivedA::Scalar, Eigen::Dynamic, 1> RowVector;
 //   typedef Eigen::Matrix<typename DerivedA::Scalar, Eigen::Dynamic, 1> RowVector;
 //   vector<SortableRow<RowVector> > rows;
 //   vector<SortableRow<RowVector> > rows;
 //   rows.resize(A.rows());
 //   rows.resize(A.rows());
@@ -134,12 +133,12 @@ IGL_INLINE void igl::unique(
 //     rows[i] = SortableRow<RowVector>(ri);
 //     rows[i] = SortableRow<RowVector>(ri);
 //   }
 //   }
 //   vector<SortableRow<RowVector> > vC;
 //   vector<SortableRow<RowVector> > vC;
-// 
+//
 //   // unique on rows
 //   // unique on rows
 //   vector<size_t> vIA;
 //   vector<size_t> vIA;
 //   vector<size_t> vIC;
 //   vector<size_t> vIC;
 //   unique(rows,vC,vIA,vIC);
 //   unique(rows,vC,vIA,vIC);
-// 
+//
 //   // Convert to eigen
 //   // Convert to eigen
 //   C.resize(vC.size(),A.cols());
 //   C.resize(vC.size(),A.cols());
 //   IA.resize(vIA.size(),1);
 //   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.
 // This file is part of libigl, a simple c++ geometry processing library.
-// 
+//
 // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
 // 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/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #ifndef IGL_UNIQUE_H
 #ifndef IGL_UNIQUE_H
 #define IGL_UNIQUE_H
 #define IGL_UNIQUE_H
@@ -45,9 +45,7 @@ namespace igl
       Eigen::PlainObjectBase<DerivedIC> & IC);
       Eigen::PlainObjectBase<DerivedIC> & IC);
   template <
   template <
     typename DerivedA,
     typename DerivedA,
-    typename DerivedC,
-    typename DerivedIA,
-    typename DerivedIC>
+    typename DerivedC>
   IGL_INLINE void unique(
   IGL_INLINE void unique(
       const Eigen::PlainObjectBase<DerivedA> & A,
       const Eigen::PlainObjectBase<DerivedA> & A,
       Eigen::PlainObjectBase<DerivedC> & C);
       Eigen::PlainObjectBase<DerivedC> & C);
@@ -76,5 +74,3 @@ namespace igl
 #endif
 #endif
 
 
 #endif
 #endif
-
-

+ 24 - 4
include/igl/viewer/Viewer.cpp

@@ -279,7 +279,6 @@ namespace viewer
     callback_mouse_scroll_data  = nullptr;
     callback_mouse_scroll_data  = nullptr;
     callback_key_down_data      = nullptr;
     callback_key_down_data      = nullptr;
     callback_key_up_data        = nullptr;
     callback_key_up_data        = nullptr;
-
   }
   }
 
 
   IGL_INLINE void Viewer::init_plugins()
   IGL_INLINE void Viewer::init_plugins()
@@ -726,10 +725,9 @@ namespace viewer
     this->save_mesh_to_file(fname.c_str());
     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);
     glfwSetErrorCallback(glfw_error_callback);
     if (!glfwInit())
     if (!glfwInit())
       return EXIT_FAILURE;
       return EXIT_FAILURE;
@@ -818,6 +816,12 @@ namespace viewer
 
 
     // Initialize IGL viewer
     // Initialize IGL viewer
     init();
     init();
+    return EXIT_SUCCESS;
+  }
+
+  IGL_INLINE bool Viewer::launch_rendering(bool loop)
+  {
+    // glfwMakeContextCurrent(window);
 
 
     // Rendering loop
     // Rendering loop
     while (!glfwWindowShouldClose(window))
     while (!glfwWindowShouldClose(window))
@@ -841,8 +845,15 @@ namespace viewer
       {
       {
         glfwWaitEvents();
         glfwWaitEvents();
       }
       }
+
+      if (!loop)
+        return !glfwWindowShouldClose(window);
     }
     }
+    return EXIT_SUCCESS;
+  }
 
 
+  IGL_INLINE void Viewer::launch_shut()
+  {
     opengl.free();
     opengl.free();
     core.shut();
     core.shut();
 
 
@@ -850,6 +861,15 @@ namespace viewer
 
 
     glfwDestroyWindow(window);
     glfwDestroyWindow(window);
     glfwTerminate();
     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;
     return EXIT_SUCCESS;
   }
   }
 } // end namespace
 } // end namespace

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

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

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

@@ -32,6 +32,7 @@ namespace igl {
       SERIALIZE_MEMBER(lighting_factor);
       SERIALIZE_MEMBER(lighting_factor);
 
 
       SERIALIZE_MEMBER(trackball_angle);
       SERIALIZE_MEMBER(trackball_angle);
+      SERIALIZE_MEMBER(rotation_type);
 
 
       SERIALIZE_MEMBER(model_zoom);
       SERIALIZE_MEMBER(model_zoom);
       SERIALIZE_MEMBER(model_translation);
       SERIALIZE_MEMBER(model_translation);
@@ -39,8 +40,6 @@ namespace igl {
       SERIALIZE_MEMBER(model_zoom_uv);
       SERIALIZE_MEMBER(model_zoom_uv);
       SERIALIZE_MEMBER(model_translation_uv);
       SERIALIZE_MEMBER(model_translation_uv);
 
 
-      SERIALIZE_MEMBER(object_scale);
-
       SERIALIZE_MEMBER(camera_zoom);
       SERIALIZE_MEMBER(camera_zoom);
       SERIALIZE_MEMBER(orthographic);
       SERIALIZE_MEMBER(orthographic);
       SERIALIZE_MEMBER(camera_view_angle);
       SERIALIZE_MEMBER(camera_view_angle);
@@ -65,17 +64,21 @@ namespace igl {
       SERIALIZE_MEMBER(is_animating);
       SERIALIZE_MEMBER(is_animating);
       SERIALIZE_MEMBER(animation_max_fps);
       SERIALIZE_MEMBER(animation_max_fps);
 
 
+      SERIALIZE_MEMBER(object_scale);
+
       SERIALIZE_MEMBER(viewport);
       SERIALIZE_MEMBER(viewport);
       SERIALIZE_MEMBER(view);
       SERIALIZE_MEMBER(view);
       SERIALIZE_MEMBER(model);
       SERIALIZE_MEMBER(model);
       SERIALIZE_MEMBER(proj);
       SERIALIZE_MEMBER(proj);
     }
     }
 
 
+    template<>
     IGL_INLINE void serialize(const igl::viewer::ViewerCore& obj,std::vector<char>& buffer)
     IGL_INLINE void serialize(const igl::viewer::ViewerCore& obj,std::vector<char>& buffer)
     {
     {
       serialization(true,const_cast<igl::viewer::ViewerCore&>(obj),buffer);
       serialization(true,const_cast<igl::viewer::ViewerCore&>(obj),buffer);
     }
     }
 
 
+    template<>
     IGL_INLINE void deserialize(igl::viewer::ViewerCore& obj,const std::vector<char>& buffer)
     IGL_INLINE void deserialize(igl::viewer::ViewerCore& obj,const std::vector<char>& buffer)
     {
     {
       serialization(false,obj,const_cast<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 view;
   Eigen::Matrix4f model;
   Eigen::Matrix4f model;
   Eigen::Matrix4f proj;
   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_positions);
       SERIALIZE_MEMBER(labels_strings);
       SERIALIZE_MEMBER(labels_strings);
 
 
+      SERIALIZE_MEMBER(dirty);
+
       SERIALIZE_MEMBER(face_based);
       SERIALIZE_MEMBER(face_based);
     }
     }
 
 
+    template<>
     IGL_INLINE void serialize(const igl::viewer::ViewerData& obj,std::vector<char>& buffer)
     IGL_INLINE void serialize(const igl::viewer::ViewerData& obj,std::vector<char>& buffer)
     {
     {
       serialization(true,const_cast<igl::viewer::ViewerData&>(obj),buffer);
       serialization(true,const_cast<igl::viewer::ViewerData&>(obj),buffer);
     }
     }
 
 
+    template<>
     IGL_INLINE void deserialize(igl::viewer::ViewerData& obj,const std::vector<char>& buffer)
     IGL_INLINE void deserialize(igl::viewer::ViewerData& obj,const std::vector<char>& buffer)
     {
     {
       serialization(false,obj,const_cast<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;
       F = _F;
     }
     }
     else
     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;
   dirty |= DIRTY_FACE | DIRTY_POSITION;
 }
 }
@@ -140,7 +144,7 @@ IGL_INLINE void igl::viewer::ViewerData::set_normals(const Eigen::MatrixXd& N)
     F_normals = N;
     F_normals = N;
   }
   }
   else
   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;
   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);
     F_material_specular = specular(F_material_diffuse);
   }
   }
   else
   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;
   dirty |= DIRTY_DIFFUSE;
 
 
 }
 }
@@ -205,7 +209,7 @@ IGL_INLINE void igl::viewer::ViewerData::set_uv(const Eigen::MatrixXd& UV)
     V_uv = UV;
     V_uv = UV;
   }
   }
   else
   else
-    cerr << "ERROR (set_UV): Please provide uv per vertex.";
+    cerr << "ERROR (set_UV): Please provide uv per vertex."<<endl;;
   dirty |= DIRTY_UV;
   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
 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
 <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
 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
 <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
 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>
 <h2 id="tutorial">Tutorial</h2>
 
 
 <p>As of version 1.0, libigl includes an introductory
 <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>
 <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