Prechádzať zdrojové kódy

Merge remote-tracking branch 'upstream/master' into cgal

Former-commit-id: 35d6d673111371f331403178505d0dc21ce1460b
Jérémie Dumas 7 rokov pred
rodič
commit
162d26a78d

+ 2 - 0
.gitignore

@@ -98,3 +98,5 @@ python/builddebug
 tutorial/.idea
 python/buildstatic
 tutorial/cmake-build-debug
+.vscode/
+.idea/

+ 17 - 0
CONTRIBUTING.md

@@ -0,0 +1,17 @@
+Before opening an issue on creating a pull request, please check the following:
+
+## Compilation Issues
+
+- If you are on Windows, did you select the **x64** version of the Visual Studio compiler?
+
+- If you have a **CMake issue**, make sure you follow the same approach as the  [libigl-example-project](https://github.com/libigl/libigl-example-project) to build libigl with your project, and make sure that you can compile the example project.
+
+- If you have an issue with a **submodule**, check if your submodules are up to date. If you have a doubt about a submodule, delete its folder and run `git submodule update --init --recursive` in the libigl directory.
+
+- If you have an issue with a missing **template issue**, check if your code compile with the *header-only* option of libigl activated. Turn **`OFF`** the CMake option `LIBIGL_USE_STATIC_LIBRARY`: either modify your `CMakeCache.txt` via CMake GUI or ccmake, or delete your `CMakeCache.txt` and re-run `cmake -DLIBIGL_USE_STATIC_LIBRARY=OFF ..` in your build folder.
+
+- Make sure your read the [**FAQ**](https://github.com/libigl/libigl/wiki/FAQ) before asking a new question, and search [**existing issues**](https://github.com/libigl/libigl/issues?q=is%3Aissue+is%3Aclosed) for a problem similar to yours.
+
+- Make sure you read the informations contained in the libigl [homepage](https://github.com/libigl/libigl) as well as the [tutorials](http://libigl.github.io/libigl/tutorial/tutorial.html).
+
+- If none of these solve your problem, then please report your issue in the bug tracker!

+ 3 - 5
coding-guidelines.html

@@ -1,14 +1,11 @@
 <!DOCTYPE html>
-<html>
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
 <head>
 	<meta charset="utf-8"/>
 	<title>libigl</title>
 	<meta name="author" content="Alec Jacobson and Daniele Panozzo and others"/>
 	<link type="text/css" rel="stylesheet" href="../tutorial/style.css"/>
-<script type='text/javascript' src='http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML'></script>
-<link rel='stylesheet' href='http://yandex.st/highlightjs/7.3/styles/default.min.css'>
-<script src='http://yandex.st/highlightjs/7.3/highlight.min.js'></script>
-<script>hljs.initHighlightingOnLoad();</script>
+<script type='text/javascript' src='http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML'></script> <link rel='stylesheet' href='http://yandex.st/highlightjs/7.3/styles/default.min.css'> <script src='http://yandex.st/highlightjs/7.3/highlight.min.js'></script> <script>hljs.initHighlightingOnLoad();</script>
 </head>
 <body>
 
@@ -60,3 +57,4 @@
 
 </body>
 </html>
+

+ 1 - 0
include/igl/exact_geodesic.cpp.REMOVED.git-id

@@ -0,0 +1 @@
+0ffa8b0392da9471a2fd26ec71effd909d4a75f3

+ 55 - 0
include/igl/exact_geodesic.h

@@ -0,0 +1,55 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2017 Zhongshi Jiang <jiangzs@nyu.edu>
+//
+// 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_EXACT_GEODESIC_H
+#define IGL_EXACT_GEODESIC_H
+
+#include "igl_inline.h"
+#include <Eigen/Core>
+
+namespace igl 
+{
+  // Exact geodesic algorithm for triangular mesh with the implementation from https://code.google.com/archive/p/geodesic/, 
+  // and the algorithm first described by Mitchell, Mount and Papadimitriou in 1987
+  //
+  // Inputs:
+  //   V  #V by 3 list of 3D vertex positions
+  //   F  #F by 3 list of mesh faces
+  //   VS #VS by 1 vector specifying indices of source vertices
+  //   FS #FS by 1 vector specifying indices of source faces
+  //   VT #VT by 1 vector specifying indices of target vertices
+  //   FT #FT by 1 vector specifying indices of target faces
+  // Output:
+  //   D  #VT+#FT by 1 vector of geodesic distances of each target w.r.t. the nearest one in the source set
+  //
+  // Note: 
+  //      Specifying a face as target/source means its center. 
+  //
+    template <
+    typename DerivedV,
+    typename DerivedF,
+    typename DerivedVS,
+    typename DerivedFS,
+    typename DerivedVT,
+    typename DerivedFT,
+    typename DerivedD>
+    IGL_INLINE void exact_geodesic(
+      const Eigen::MatrixBase<DerivedV> &V,
+      const Eigen::MatrixBase<DerivedF> &F,
+      const Eigen::MatrixBase<DerivedVS> &VS,
+      const Eigen::MatrixBase<DerivedFS> &FS,
+      const Eigen::MatrixBase<DerivedVT> &VT,
+      const Eigen::MatrixBase<DerivedFT> &FT,
+      Eigen::PlainObjectBase<DerivedD> &D);
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "exact_geodesic.cpp"
+#endif
+
+#endif

+ 5 - 4
include/igl/grad.cpp

@@ -36,10 +36,11 @@ IGL_INLINE void grad_tet(const Eigen::PlainObjectBase<DerivedV>&V,
     F.row(3*m + i) << T(i,1), T(i,3), T(i,2);
   }
   // compute volume of each tet
-  VectorXd vol; igl::volume(V,T,vol);
+  Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 1> vol; 
+  igl::volume(V,T,vol);
 
-  VectorXd A(F.rows());
-  MatrixXd N(F.rows(),3);
+  Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 1> A(F.rows());
+  Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> N(F.rows(),3);
   if (!uniform) {
     // compute tetrahedron face normals
     igl::per_face_normals(V,F,N); int norm_rows = N.rows();
@@ -149,7 +150,7 @@ IGL_INLINE void grad_tri(const Eigen::PlainObjectBase<DerivedV>&V,
       // get h (by the area of the triangle)
       double h = sqrt( (dblA)/sin(M_PI / 3.0)); // (h^2*sin(60))/2. = Area => h = sqrt(2*Area/sin_60)
 
-      Eigen::Vector3d v1,v2,v3;
+      Eigen::Matrix<typename DerivedV::Scalar, 3, 1> v1,v2,v3;
       v1 << 0,0,0;
       v2 << h,0,0;
       v3 << h/2.,(sqrt(3)/2.)*h,0;

+ 0 - 3
include/igl/matlab/mexErrMsgTxt.cpp

@@ -7,9 +7,6 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "mexErrMsgTxt.h"
 
-// Overload mexErrMsgTxt to check an assertion then print text only if
-// assertion fails
-#include "mex.h"
 IGL_INLINE void igl::matlab::mexErrMsgTxt(bool assertion, const char * text)
 {
   if(!assertion)

+ 3 - 0
include/igl/matlab/mexErrMsgTxt.h

@@ -8,6 +8,9 @@
 #ifndef IGL_MATLAB_MEXERRMSGTXT_H
 #define IGL_MATLAB_MEXERRMSGTXT_H
 #include "../igl_inline.h"
+// Overload mexErrMsgTxt to check an assertion then print text only if
+// assertion fails
+#include "mex.h"
 namespace igl
 {
   namespace matlab

+ 105 - 100
include/igl/opengl/MeshGL.cpp

@@ -165,112 +165,117 @@ IGL_INLINE void igl::opengl::MeshGL::init()
   }
   is_initialized = true;
   std::string mesh_vertex_shader_string =
-  "#version 150\n"
-  "uniform mat4 model;"
-  "uniform mat4 view;"
-  "uniform mat4 proj;"
-  "in vec3 position;"
-  "in vec3 normal;"
-  "out vec3 position_eye;"
-  "out vec3 normal_eye;"
-  "in vec4 Ka;"
-  "in vec4 Kd;"
-  "in vec4 Ks;"
-  "in vec2 texcoord;"
-  "out vec2 texcoordi;"
-  "out vec4 Kai;"
-  "out vec4 Kdi;"
-  "out vec4 Ksi;"
-
-  "void main()"
-  "{"
-  "  position_eye = vec3 (view * model * vec4 (position, 1.0));"
-  "  normal_eye = vec3 (view * model * vec4 (normal, 0.0));"
-  "  normal_eye = normalize(normal_eye);"
-  "  gl_Position = proj * vec4 (position_eye, 1.0);" //proj * view * model * vec4(position, 1.0);"
-  "  Kai = Ka;"
-  "  Kdi = Kd;"
-  "  Ksi = Ks;"
-  "  texcoordi = texcoord;"
-  "}";
-
-  std::string mesh_fragment_shader_string =
-  "#version 150\n"
-  "uniform mat4 model;"
-  "uniform mat4 view;"
-  "uniform mat4 proj;"
-  "uniform vec4 fixed_color;"
-  "in vec3 position_eye;"
-  "in vec3 normal_eye;"
-  "uniform vec3 light_position_world;"
-  "vec3 Ls = vec3 (1, 1, 1);"
-  "vec3 Ld = vec3 (1, 1, 1);"
-  "vec3 La = vec3 (1, 1, 1);"
-  "in vec4 Ksi;"
-  "in vec4 Kdi;"
-  "in vec4 Kai;"
-  "in vec2 texcoordi;"
-  "uniform sampler2D tex;"
-  "uniform float specular_exponent;"
-  "uniform float lighting_factor;"
-  "uniform float texture_factor;"
-  "out vec4 outColor;"
-  "void main()"
-  "{"
-  "vec3 Ia = La * vec3(Kai);"    // ambient intensity
-
-  "vec3 light_position_eye = vec3 (view * vec4 (light_position_world, 1.0));"
-  "vec3 vector_to_light_eye = light_position_eye - position_eye;"
-  "vec3 direction_to_light_eye = normalize (vector_to_light_eye);"
-  "float dot_prod = dot (direction_to_light_eye, normal_eye);"
-  "float clamped_dot_prod = max (dot_prod, 0.0);"
-  "vec3 Id = Ld * vec3(Kdi) * clamped_dot_prod;"    // Diffuse intensity
-
-  "vec3 reflection_eye = reflect (-direction_to_light_eye, normal_eye);"
-  "vec3 surface_to_viewer_eye = normalize (-position_eye);"
-  "float dot_prod_specular = dot (reflection_eye, surface_to_viewer_eye);"
-  "dot_prod_specular = float(abs(dot_prod)==dot_prod) * max (dot_prod_specular, 0.0);"
-  "float specular_factor = pow (dot_prod_specular, specular_exponent);"
-  "vec3 Is = Ls * vec3(Ksi) * specular_factor;"    // specular intensity
-  "vec4 color = vec4(lighting_factor * (Is + Id) + Ia + (1.0-lighting_factor) * vec3(Kdi),(Kai.a+Ksi.a+Kdi.a)/3);"
-  "outColor = mix(vec4(1,1,1,1), texture(tex, texcoordi), texture_factor) * color;"
-  "if (fixed_color != vec4(0.0)) outColor = fixed_color;"
-  "}";
+R"(#version 150
+  uniform mat4 model;
+  uniform mat4 view;
+  uniform mat4 proj;
+  in vec3 position;
+  in vec3 normal;
+  out vec3 position_eye;
+  out vec3 normal_eye;
+  in vec4 Ka;
+  in vec4 Kd;
+  in vec4 Ks;
+  in vec2 texcoord;
+  out vec2 texcoordi;
+  out vec4 Kai;
+  out vec4 Kdi;
+  out vec4 Ksi;
+
+  void main()
+  {
+    position_eye = vec3 (view * model * vec4 (position, 1.0));
+    normal_eye = vec3 (view * model * vec4 (normal, 0.0));
+    normal_eye = normalize(normal_eye);
+    gl_Position = proj * vec4 (position_eye, 1.0); //proj * view * model * vec4(position, 1.0);
+    Kai = Ka;
+    Kdi = Kd;
+    Ksi = Ks;
+    texcoordi = texcoord;
+  }
+)";
+
+  std::string mesh_fragment_shader_string = 
+R"(#version 150
+  uniform mat4 model;
+  uniform mat4 view;
+  uniform mat4 proj;
+  uniform vec4 fixed_color;
+  in vec3 position_eye;
+  in vec3 normal_eye;
+  uniform vec3 light_position_world;
+  vec3 Ls = vec3 (1, 1, 1);
+  vec3 Ld = vec3 (1, 1, 1);
+  vec3 La = vec3 (1, 1, 1);
+  in vec4 Ksi;
+  in vec4 Kdi;
+  in vec4 Kai;
+  in vec2 texcoordi;
+  uniform sampler2D tex;
+  uniform float specular_exponent;
+  uniform float lighting_factor;
+  uniform float texture_factor;
+  out vec4 outColor;
+  void main()
+  {
+    vec3 Ia = La * vec3(Kai);    // ambient intensity
+
+    vec3 light_position_eye = vec3 (view * vec4 (light_position_world, 1.0));
+    vec3 vector_to_light_eye = light_position_eye - position_eye;
+    vec3 direction_to_light_eye = normalize (vector_to_light_eye);
+    float dot_prod = dot (direction_to_light_eye, normal_eye);
+    float clamped_dot_prod = max (dot_prod, 0.0);
+    vec3 Id = Ld * vec3(Kdi) * clamped_dot_prod;    // Diffuse intensity
+
+    vec3 reflection_eye = reflect (-direction_to_light_eye, normal_eye);
+    vec3 surface_to_viewer_eye = normalize (-position_eye);
+    float dot_prod_specular = dot (reflection_eye, surface_to_viewer_eye);
+    dot_prod_specular = float(abs(dot_prod)==dot_prod) * max (dot_prod_specular, 0.0);
+    float specular_factor = pow (dot_prod_specular, specular_exponent);
+    vec3 Is = Ls * vec3(Ksi) * specular_factor;    // specular intensity
+    vec4 color = vec4(lighting_factor * (Is + Id) + Ia + (1.0-lighting_factor) * vec3(Kdi),(Kai.a+Ksi.a+Kdi.a)/3);
+    outColor = mix(vec4(1,1,1,1), texture(tex, texcoordi), texture_factor) * color;
+    if (fixed_color != vec4(0.0)) outColor = fixed_color;
+  }
+  )";
 
   std::string overlay_vertex_shader_string =
-  "#version 150\n"
-  "uniform mat4 model;"
-  "uniform mat4 view;"
-  "uniform mat4 proj;"
-  "in vec3 position;"
-  "in vec3 color;"
-  "out vec3 color_frag;"
-
-  "void main()"
-  "{"
-  "  gl_Position = proj * view * model * vec4 (position, 1.0);"
-  "  color_frag = color;"
-  "}";
+R"(#version 150
+  uniform mat4 model;
+  uniform mat4 view;
+  uniform mat4 proj;
+  in vec3 position;
+  in vec3 color;
+  out vec3 color_frag;
+
+  void main()
+  {
+    gl_Position = proj * view * model * vec4 (position, 1.0);
+    color_frag = color;
+  }
+)";
 
   std::string overlay_fragment_shader_string =
-  "#version 150\n"
-  "in vec3 color_frag;"
-  "out vec4 outColor;"
-  "void main()"
-  "{"
-  "  outColor = vec4(color_frag, 1.0);"
-  "}";
+R"(#version 150
+  in vec3 color_frag;
+  out vec4 outColor;
+  void main()
+  {
+    outColor = vec4(color_frag, 1.0);
+  }
+)";
 
   std::string overlay_point_fragment_shader_string =
-  "#version 150\n"
-  "in vec3 color_frag;"
-  "out vec4 outColor;"
-  "void main()"
-  "{"
-  "  if (length(gl_PointCoord - vec2(0.5)) > 0.5)"
-  "    discard;"
-  "  outColor = vec4(color_frag, 1.0);"
-  "}";
+R"(#version 150
+  in vec3 color_frag;
+  out vec4 outColor;
+  void main()
+  {
+    if (length(gl_PointCoord - vec2(0.5)) > 0.5)
+      discard;
+    outColor = vec4(color_frag, 1.0);
+  }
+)";
 
   init_buffers();
   create_shader_program(

+ 12 - 11
include/igl/opengl/ViewerData.cpp

@@ -528,7 +528,9 @@ IGL_INLINE void igl::opengl::ViewerData::updateGL(
 
       // Texture coordinates
       if (meshgl.dirty & MeshGL::DIRTY_UV)
+      {
         meshgl.V_uv_vbo = data.V_uv.cast<float>();
+      }
     }
     else
     {
@@ -541,36 +543,35 @@ IGL_INLINE void igl::opengl::ViewerData::updateGL(
 
       if (meshgl.dirty & MeshGL::DIRTY_AMBIENT)
       {
-        meshgl.V_ambient_vbo.resize(4,data.F.rows()*3);
+        meshgl.V_ambient_vbo.resize(data.F.rows()*3,4);
         for (unsigned i=0; i<data.F.rows();++i)
           for (unsigned j=0;j<3;++j)
-            meshgl.V_ambient_vbo.col (i*3+j) = data.V_material_ambient.row(data.F(i,j)).transpose().cast<float>();
+            meshgl.V_ambient_vbo.row(i*3+j) = data.V_material_ambient.row(data.F(i,j)).cast<float>();
       }
       if (meshgl.dirty & MeshGL::DIRTY_DIFFUSE)
       {
-        meshgl.V_diffuse_vbo.resize(4,data.F.rows()*3);
+        meshgl.V_diffuse_vbo.resize(data.F.rows()*3,4);
         for (unsigned i=0; i<data.F.rows();++i)
           for (unsigned j=0;j<3;++j)
-            meshgl.V_diffuse_vbo.col (i*3+j) = data.V_material_diffuse.row(data.F(i,j)).transpose().cast<float>();
+            meshgl.V_diffuse_vbo.row(i*3+j) = data.V_material_diffuse.row(data.F(i,j)).cast<float>();
       }
       if (meshgl.dirty & MeshGL::DIRTY_SPECULAR)
       {
-        meshgl.V_specular_vbo.resize(4,data.F.rows()*3);
+        meshgl.V_specular_vbo.resize(data.F.rows()*3,4);
         for (unsigned i=0; i<data.F.rows();++i)
           for (unsigned j=0;j<3;++j)
-            meshgl.V_specular_vbo.col(i*3+j) = data.V_material_specular.row(data.F(i,j)).transpose().cast<float>();
+            meshgl.V_specular_vbo.row(i*3+j) = data.V_material_specular.row(data.F(i,j)).cast<float>();
       }
 
       if (meshgl.dirty & MeshGL::DIRTY_NORMAL)
       {
-        meshgl.V_normals_vbo.resize(3,data.F.rows()*3);
+        meshgl.V_normals_vbo.resize(data.F.rows()*3,3);
         for (unsigned i=0; i<data.F.rows();++i)
           for (unsigned j=0;j<3;++j)
-
-            meshgl.V_normals_vbo.col (i*3+j) =
+            meshgl.V_normals_vbo.row(i*3+j) =
                          per_corner_normals ?
-               data.F_normals.row(i*3+j).transpose().cast<float>() :
-               data.V_normals.row(data.F(i,j)).transpose().cast<float>();
+               data.F_normals.row(i*3+j).cast<float>() :
+               data.V_normals.row(data.F(i,j)).cast<float>();
 
 
         if (invert_normals)

+ 3 - 1
include/igl/opengl/glfw/Viewer.cpp

@@ -172,8 +172,8 @@ namespace glfw
       printf("Failed to load OpenGL and its extensions\n");
       return(-1);
     }
-    printf("OpenGL Version %d.%d loaded\n", GLVersion.major, GLVersion.minor);
     #if defined(DEBUG) || defined(_DEBUG)
+      printf("OpenGL Version %d.%d loaded\n", GLVersion.major, GLVersion.minor);
       int major, minor, rev;
       major = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MAJOR);
       minor = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MINOR);
@@ -413,6 +413,8 @@ namespace glfw
     data().uniform_colors(Eigen::Vector3d(51.0/255.0,43.0/255.0,33.3/255.0),
                    Eigen::Vector3d(255.0/255.0,228.0/255.0,58.0/255.0),
                    Eigen::Vector3d(255.0/255.0,235.0/255.0,80.0/255.0));
+
+    // Alec: why?
     if (data().V_uv.rows() == 0)
     {
       data().grid_texture();

+ 2 - 2
include/igl/opengl/glfw/Viewer.h

@@ -142,8 +142,8 @@ namespace glfw
     std::function<bool(Viewer& viewer, float delta_y)> callback_mouse_scroll;
     std::function<bool(Viewer& viewer, unsigned int key, int modifiers)> callback_key_pressed;
     // THESE SHOULD BE DEPRECATED:
-    std::function<bool(Viewer& viewer, unsigned char key, int modifiers)> callback_key_down;
-    std::function<bool(Viewer& viewer, unsigned char key, int modifiers)> callback_key_up;
+    std::function<bool(Viewer& viewer, unsigned int key, int modifiers)> callback_key_down;
+    std::function<bool(Viewer& viewer, unsigned int key, int modifiers)> callback_key_up;
     // Pointers to per-callback data
     void* callback_init_data;
     void* callback_pre_draw_data;

+ 70 - 76
include/igl/principal_curvature.cpp

@@ -105,13 +105,12 @@ public:
     }
 
 
-    IGL_INLINE static Quadric fit(std::vector<Eigen::Vector3d> &VV, bool zeroDetCheck, bool svd)
+    IGL_INLINE static Quadric fit(const std::vector<Eigen::Vector3d> &VV)
     {
-      using namespace std;
       assert(VV.size() >= 5);
       if (VV.size() < 5)
       {
-        cerr << "ASSERT FAILED!" << endl;
+        std::cerr << "ASSERT FAILED! fit function requires at least 5 points: Only " << VV.size() << " were given." << std::endl;
         exit(0);
       }
 
@@ -160,8 +159,6 @@ public:
   bool localMode; /* Use local mode */
   bool projectionPlaneCheck; /* Check collected vertices on tangent plane */
   bool montecarlo;
-  bool svd; /* Use svd calculation instead of pseudoinverse */
-  bool zeroDetCheck; /* Check if the determinant is close to zero */
   unsigned int montecarloN;
 
   searchType st; /* Use either a sphere search or a k-ring search */
@@ -179,23 +176,23 @@ public:
   IGL_INLINE CurvatureCalculator();
   IGL_INLINE void init(const Eigen::MatrixXd& V, const Eigen::MatrixXi& F);
 
-  IGL_INLINE void finalEigenStuff (int, std::vector<Eigen::Vector3d>, Quadric );
-  IGL_INLINE void fitQuadric (Eigen::Vector3d, std::vector<Eigen::Vector3d> ref, const  std::vector<int>& , Quadric *);
-  IGL_INLINE void applyProjOnPlane(Eigen::Vector3d, std::vector<int>, std::vector<int>&);
+  IGL_INLINE void finalEigenStuff(int, const std::vector<Eigen::Vector3d>&, Quadric&);
+  IGL_INLINE void fitQuadric(const Eigen::Vector3d&, const std::vector<Eigen::Vector3d>& ref, const std::vector<int>& , Quadric *);
+  IGL_INLINE void applyProjOnPlane(const Eigen::Vector3d&, const std::vector<int>&, std::vector<int>&);
   IGL_INLINE void getSphere(const int, const double, std::vector<int>&, int min);
   IGL_INLINE void getKRing(const int, const double,std::vector<int>&);
-  IGL_INLINE Eigen::Vector3d project(Eigen::Vector3d, Eigen::Vector3d, Eigen::Vector3d);
-  IGL_INLINE void computeReferenceFrame(int, Eigen::Vector3d, std::vector<Eigen::Vector3d>&);
-  IGL_INLINE void getAverageNormal(int, std::vector<int>, Eigen::Vector3d&);
-  IGL_INLINE void getProjPlane(int, std::vector<int>, Eigen::Vector3d&);
-  IGL_INLINE void applyMontecarlo(std::vector<int>&,std::vector<int>*);
+  IGL_INLINE Eigen::Vector3d project(const Eigen::Vector3d&, const Eigen::Vector3d&, const Eigen::Vector3d&);
+  IGL_INLINE void computeReferenceFrame(int, const Eigen::Vector3d&, std::vector<Eigen::Vector3d>&);
+  IGL_INLINE void getAverageNormal(int, const std::vector<int>&, Eigen::Vector3d&);
+  IGL_INLINE void getProjPlane(int, const std::vector<int>&, Eigen::Vector3d&);
+  IGL_INLINE void applyMontecarlo(const std::vector<int>&,std::vector<int>*);
   IGL_INLINE void computeCurvature();
-  IGL_INLINE void printCurvature(std::string outpath);
+  IGL_INLINE void printCurvature(const std::string& outpath);
   IGL_INLINE double getAverageEdge();
 
-  IGL_INLINE static int rotateForward (float *v0, float *v1, float *v2)
+  IGL_INLINE static int rotateForward (double *v0, double *v1, double *v2)
   {
-    float t;
+    double t;
 
     if (std::abs(*v2) >= std::abs(*v1) && std::abs(*v2) >= std::abs(*v0))
       return 0;
@@ -208,9 +205,9 @@ public:
     return 1 + rotateForward (v0, v1, v2);
   }
 
-  IGL_INLINE static void rotateBackward (int nr, float *v0, float *v1, float *v2)
+  IGL_INLINE static void rotateBackward (int nr, double *v0, double *v1, double *v2)
   {
-    float t;
+    double t;
 
     if (nr == 0)
       return;
@@ -223,18 +220,18 @@ public:
     rotateBackward (nr - 1, v0, v1, v2);
   }
 
-  IGL_INLINE static Eigen::Vector3d chooseMax (Eigen::Vector3d n, Eigen::Vector3d abc, float ab)
+  IGL_INLINE static Eigen::Vector3d chooseMax (Eigen::Vector3d n, Eigen::Vector3d abc, double ab)
   {
-    int i, max_i;
-    float max_sp;
+    int max_i;
+    double max_sp;
     Eigen::Vector3d nt[8];
 
     n.normalize ();
     abc.normalize ();
 
-    max_sp = - std::numeric_limits<float>::max();
+    max_sp = - std::numeric_limits<double>::max();
 
-    for (i = 0; i < 4; i++)
+    for (int i = 0; i < 4; ++i)
     {
       nt[i] = n;
       if (ab > 0)
@@ -290,7 +287,6 @@ public:
         max_i = i;
       }
     }
-
     return nt[max_i];
   }
 
@@ -315,8 +311,6 @@ IGL_INLINE CurvatureCalculator::CurvatureCalculator()
   this->montecarlo=false;
   this->montecarloN=0;
   this->kRing=3;
-  this->svd=true;
-  this->zeroDetCheck=true;
   this->curvatureComputed=false;
   this->expStep=true;
 }
@@ -337,7 +331,7 @@ IGL_INLINE void CurvatureCalculator::init(const Eigen::MatrixXd& V, const Eigen:
   igl::per_vertex_normals(V, F, face_normals, vertex_normals);
 }
 
-IGL_INLINE void CurvatureCalculator::fitQuadric (Eigen::Vector3d v, std::vector<Eigen::Vector3d> ref, const std::vector<int>& vv, Quadric *q)
+IGL_INLINE void CurvatureCalculator::fitQuadric(const Eigen::Vector3d& v, const std::vector<Eigen::Vector3d>& ref, const std::vector<int>& vv, Quadric *q)
 {
   std::vector<Eigen::Vector3d> points;
   points.reserve (vv.size());
@@ -354,17 +348,25 @@ IGL_INLINE void CurvatureCalculator::fitQuadric (Eigen::Vector3d v, std::vector<
     double z = vTang.dot(ref[2]);
     points.push_back(Eigen::Vector3d (x,y,z));
   }
-  *q = Quadric::fit (points, zeroDetCheck, svd);
+  if (points.size() < 5)
+  {
+    std::cerr << "ASSERT FAILED! fit function requires at least 5 points: Only " << points.size() << " were given." << std::endl;
+    *q = Quadric(0,0,0,0,0);
+  }
+  else
+  {
+    *q = Quadric::fit (points);
+  }
 }
 
-IGL_INLINE void CurvatureCalculator::finalEigenStuff (int i, std::vector<Eigen::Vector3d> ref, Quadric q)
+IGL_INLINE void CurvatureCalculator::finalEigenStuff(int i, const std::vector<Eigen::Vector3d>& ref, Quadric& q)
 {
 
-  double a = q.a();
-  double b = q.b();
-  double c = q.c();
-  double d = q.d();
-  double e = q.e();
+  const double a = q.a();
+  const double b = q.b();
+  const double c = q.c();
+  const double d = q.d();
+  const double e = q.e();
 
 //  if (fabs(a) < 10e-8 || fabs(b) < 10e-8)
 //  {
@@ -457,7 +459,7 @@ IGL_INLINE void CurvatureCalculator::getKRing(const int start, const double r, s
     vv.push_back(toVisit);
     if (distance<(int)r)
     {
-      for (unsigned int i=0; i<vertex_to_vertices[toVisit].size(); i++)
+      for (unsigned int i=0; i<vertex_to_vertices[toVisit].size(); ++i)
       {
         int neighbor=vertex_to_vertices[toVisit][i];
         if (!visited[neighbor])
@@ -488,13 +490,13 @@ IGL_INLINE void CurvatureCalculator::getSphere(const int start, const double r,
     int toVisit=queue->front();
     queue->pop_front();
     vv.push_back(toVisit);
-    for (unsigned int i=0; i<vertex_to_vertices[toVisit].size(); i++)
+    for (unsigned int i=0; i<vertex_to_vertices[toVisit].size(); ++i)
     {
       int neighbor=vertex_to_vertices[toVisit][i];
       if (!visited[neighbor])
       {
         Eigen::Vector3d neigh=vertices.row(neighbor);
-        float distance=(me-neigh).norm();
+        double distance=(me-neigh).norm();
         if (distance<r)
           queue->push_back(neighbor);
         else if ((int)vv.size()<min)
@@ -508,13 +510,13 @@ IGL_INLINE void CurvatureCalculator::getSphere(const int start, const double r,
     std::pair<int, double> cand=extra_candidates->top();
     extra_candidates->pop();
     vv.push_back(cand.first);
-    for (unsigned int i=0; i<vertex_to_vertices[cand.first].size(); i++)
+    for (unsigned int i=0; i<vertex_to_vertices[cand.first].size(); ++i)
     {
       int neighbor=vertex_to_vertices[cand.first][i];
       if (!visited[neighbor])
       {
         Eigen::Vector3d neigh=vertices.row(neighbor);
-        float distance=(me-neigh).norm();
+        double distance=(me-neigh).norm();
         extra_candidates->push(std::pair<int,double>(neighbor,distance));
         visited[neighbor]=true;
       }
@@ -525,16 +527,15 @@ IGL_INLINE void CurvatureCalculator::getSphere(const int start, const double r,
   free(visited);
 }
 
-IGL_INLINE Eigen::Vector3d CurvatureCalculator::project(Eigen::Vector3d v, Eigen::Vector3d  vp, Eigen::Vector3d ppn)
+IGL_INLINE Eigen::Vector3d CurvatureCalculator::project(const Eigen::Vector3d& v, const Eigen::Vector3d& vp, const Eigen::Vector3d& ppn)
 {
   return (vp - (ppn * ((vp - v).dot(ppn))));
 }
 
-IGL_INLINE void CurvatureCalculator::computeReferenceFrame(int i, Eigen::Vector3d normal, std::vector<Eigen::Vector3d>& ref )
+IGL_INLINE void CurvatureCalculator::computeReferenceFrame(int i, const Eigen::Vector3d& normal, std::vector<Eigen::Vector3d>& ref )
 {
 
-  Eigen::Vector3d longest_v=Eigen::Vector3d::Zero();
-  longest_v=Eigen::Vector3d(vertices.row(vertex_to_vertices[i][0]));
+  Eigen::Vector3d longest_v=Eigen::Vector3d(vertices.row(vertex_to_vertices[i][0]));
 
   longest_v=(project(vertices.row(i),longest_v,normal)-Eigen::Vector3d(vertices.row(i))).normalized();
 
@@ -546,25 +547,25 @@ IGL_INLINE void CurvatureCalculator::computeReferenceFrame(int i, Eigen::Vector3
   ref[2]=normal;
 }
 
-IGL_INLINE void CurvatureCalculator::getAverageNormal(int j, std::vector<int> vv, Eigen::Vector3d& normal)
+IGL_INLINE void CurvatureCalculator::getAverageNormal(int j, const std::vector<int>& vv, Eigen::Vector3d& normal)
 {
   normal=(vertex_normals.row(j)).normalized();
   if (localMode)
     return;
 
-  for (unsigned int i=0; i<vv.size(); i++)
+  for (unsigned int i=0; i<vv.size(); ++i)
   {
     normal+=vertex_normals.row(vv[i]).normalized();
   }
   normal.normalize();
 }
 
-IGL_INLINE void CurvatureCalculator::getProjPlane(int j, std::vector<int> vv, Eigen::Vector3d& ppn)
+IGL_INLINE void CurvatureCalculator::getProjPlane(int j, const std::vector<int>& vv, Eigen::Vector3d& ppn)
 {
   int nr;
-  float a, b, c;
-  float nx, ny, nz;
-  float abcq;
+  double a, b, c;
+  double nx, ny, nz;
+  double abcq;
 
   a = b = c = 0;
 
@@ -605,9 +606,9 @@ IGL_INLINE double CurvatureCalculator::getAverageEdge()
   double sum = 0;
   int count = 0;
 
-  for (int i = 0; i<faces.rows(); i++)
+  for (int i = 0; i<faces.rows(); ++i)
   {
-    for (short unsigned j=0; j<3; j++)
+    for (short unsigned j=0; j<3; ++j)
     {
       Eigen::Vector3d p1=vertices.row(faces.row(i)[j]);
       Eigen::Vector3d p2=vertices.row(faces.row(i)[(j+1)%3]);
@@ -623,14 +624,14 @@ IGL_INLINE double CurvatureCalculator::getAverageEdge()
 }
 
 
-IGL_INLINE void CurvatureCalculator::applyProjOnPlane(Eigen::Vector3d ppn, std::vector<int> vin, std::vector<int> &vout)
+IGL_INLINE void CurvatureCalculator::applyProjOnPlane(const Eigen::Vector3d& ppn, const std::vector<int>& vin, std::vector<int> &vout)
 {
-  for (std::vector<int>::iterator vpi = vin.begin(); vpi != vin.end(); ++vpi)
-    if (vertex_normals.row(*vpi) * ppn > 0.0f)
-      vout.push_back (*vpi);
+  for (std::vector<int>::const_iterator vpi = vin.begin(); vpi != vin.end(); ++vpi)
+    if (vertex_normals.row(*vpi) * ppn > 0.0)
+      vout.push_back(*vpi);
 }
 
-IGL_INLINE void CurvatureCalculator::applyMontecarlo(std::vector<int>& vin, std::vector<int> *vout)
+IGL_INLINE void CurvatureCalculator::applyMontecarlo(const std::vector<int>& vin, std::vector<int> *vout)
 {
   if (montecarloN >= vin.size ())
   {
@@ -639,24 +640,22 @@ IGL_INLINE void CurvatureCalculator::applyMontecarlo(std::vector<int>& vin, std:
   }
 
   float p = ((float) montecarloN) / (float) vin.size();
-  for (std::vector<int>::iterator vpi = vin.begin(); vpi != vin.end(); ++vpi)
+  for (std::vector<int>::const_iterator vpi = vin.begin(); vpi != vin.end(); ++vpi)
   {
     float r;
     if ((r = ((float)rand () / RAND_MAX)) < p)
     {
-      vout->push_back (*vpi);
+      vout->push_back(*vpi);
     }
   }
 }
 
 IGL_INLINE void CurvatureCalculator::computeCurvature()
 {
-  using namespace std;
-
   //CHECK che esista la mesh
-  size_t vertices_count=vertices.rows() ;
+  const size_t vertices_count=vertices.rows();
 
-  if (vertices_count <=0)
+  if (vertices_count ==0)
     return;
 
   curvDir=std::vector< std::vector<Eigen::Vector3d> >(vertices_count);
@@ -691,10 +690,9 @@ IGL_INLINE void CurvatureCalculator::computeCurvature()
         return;
     }
 
-    std::vector<Eigen::Vector3d> ref(3);
     if (vv.size()<6)
     {
-      std::cerr << "Could not compute curvature of radius " << scaledRadius << endl;
+      std::cerr << "Could not compute curvature of radius " << scaledRadius << std::endl;
       return;
     }
 
@@ -704,8 +702,7 @@ IGL_INLINE void CurvatureCalculator::computeCurvature()
       vvtmp.reserve (vv.size ());
       applyProjOnPlane (vertex_normals.row(i), vv, vvtmp);
       if (vvtmp.size() >= 6 && vvtmp.size()<vv.size())
-	  vv = vvtmp;
-
+        vv = vvtmp;
     }
 
 
@@ -723,7 +720,7 @@ IGL_INLINE void CurvatureCalculator::computeCurvature()
     }
     if (vv.size()<6)
     {
-      std::cerr << "Could not compute curvature of radius " << scaledRadius << endl;
+      std::cerr << "Could not compute curvature of radius " << scaledRadius << std::endl;
       return;
     }
     if (montecarlo)
@@ -737,6 +734,7 @@ IGL_INLINE void CurvatureCalculator::computeCurvature()
 
     if (vv.size()<6)
       return;
+    std::vector<Eigen::Vector3d> ref(3);
     computeReferenceFrame(i,normal,ref);
 
     Quadric q;
@@ -748,7 +746,7 @@ IGL_INLINE void CurvatureCalculator::computeCurvature()
   curvatureComputed=true;
 }
 
-IGL_INLINE void CurvatureCalculator::printCurvature(std::string outpath)
+IGL_INLINE void CurvatureCalculator::printCurvature(const std::string& outpath)
 {
   using namespace std;
   if (!curvatureComputed)
@@ -765,7 +763,7 @@ IGL_INLINE void CurvatureCalculator::printCurvature(std::string outpath)
 
   int vertices_count=vertices.rows();
   of << vertices_count << endl;
-  for (int i=0; i<vertices_count; i++)
+  for (int i=0; i<vertices_count; ++i)
   {
     of << curv[i][0] << " " << curv[i][1] << " " << curvDir[i][0][0] << " " << curvDir[i][0][1] << " " << curvDir[i][0][2] << " " <<
     curvDir[i][1][0] << " " << curvDir[i][1][1] << " " << curvDir[i][1][2] << endl;
@@ -792,12 +790,10 @@ IGL_INLINE void igl::principal_curvature(
   unsigned radius,
   bool useKring)
 {
-  using namespace std;
-
   if (radius < 2)
   {
     radius = 2;
-    cout << "WARNING: igl::principal_curvature needs a radius >= 2, fixing it to 2." << endl;
+    std::cout << "WARNING: igl::principal_curvature needs a radius >= 2, fixing it to 2." << std::endl;
   }
 
   // Preallocate memory
@@ -823,10 +819,8 @@ IGL_INLINE void igl::principal_curvature(
   cc.computeCurvature();
 
   // Copy it back
-  for (unsigned i=0; i<V.rows(); i++)
+  for (unsigned i=0; i<V.rows(); ++i)
   {
-    Eigen::Vector3d d1;
-    Eigen::Vector3d d2;
     PD1.row(i) << cc.curvDir[i][0][0], cc.curvDir[i][0][1], cc.curvDir[i][0][2];
     PD2.row(i) << cc.curvDir[i][1][0], cc.curvDir[i][1][1], cc.curvDir[i][1][2];
     PD1.row(i).normalize();
@@ -843,7 +837,7 @@ IGL_INLINE void igl::principal_curvature(
 
     if (PD1.row(i) * PD2.row(i).transpose() > 10e-6)
     {
-      cerr << "PRINCIPAL_CURVATURE: Something is wrong with vertex: i" << endl;
+      std::cerr << "PRINCIPAL_CURVATURE: Something is wrong with vertex: " << i << std::endl;
       PD1.row(i) *= 0;
       PD2.row(i) *= 0;
     }

+ 5 - 3
include/igl/slice_cached.h

@@ -14,9 +14,11 @@
 namespace igl
 {  
 
-  // Act like the matlab X(row_indices,col_indices) operator, where
-  // row_indices, col_indices are non-negative integer indices. This is a fast version
-  // of igl::slice that can analyze and store the sparsity structure. It is slower at the // first evaluation (slice_cached_precompute), but faster on the subsequent ones.
+  // Act like the matlab X(row_indices,col_indices) operator, where row_indices,
+  // col_indices are non-negative integer indices. This is a fast version of
+  // igl::slice that can analyze and store the sparsity structure. It is slower
+  // at the irst evaluation (slice_cached_precompute), but faster on the
+  // subsequent ones.
   // 
   // Inputs:
   //   X  m by n matrix

+ 56 - 57
index.html

@@ -1,14 +1,11 @@
 <!DOCTYPE html>
-<html>
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
 <head>
 	<meta charset="utf-8"/>
 	<title>libigl</title>
 	<meta name="author" content="Alec Jacobson and Daniele Panozzo and others"/>
 	<link type="text/css" rel="stylesheet" href="tutorial/style.css"/>
-<script type='text/javascript' src='http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML'></script>
-<link rel='stylesheet' href='http://yandex.st/highlightjs/7.3/styles/default.min.css'>
-<script src='http://yandex.st/highlightjs/7.3/highlight.min.js'></script>
-<script>hljs.initHighlightingOnLoad();</script>
+<script type='text/javascript' src='http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML'></script> <link rel='stylesheet' href='http://yandex.st/highlightjs/7.3/styles/default.min.css'> <script src='http://yandex.st/highlightjs/7.3/highlight.min.js'></script> <script>hljs.initHighlightingOnLoad();</script>
 </head>
 <body>
 
@@ -22,10 +19,10 @@
 
 <blockquote>
 <p>Get started with:</p>
+</blockquote>
 
 <pre><code class="bash">git clone --recursive https://github.com/libigl/libigl.git
 </code></pre>
-</blockquote>
 
 <p>libigl is a simple C++ geometry processing library. We have a wide
 functionality including construction of sparse discrete differential geometry
@@ -39,7 +36,7 @@ like MATLAB.</p>
 just include igl headers (e.g. <code>#include &lt;igl/cotmatrix.h&gt;</code>) and run. Each
 header file contains a single function (e.g. <code>igl/cotmatrix.h</code> contains
 <code>igl::cotmatrix()</code>). Most are tailored to operate on a generic triangle mesh
-stored in an n-by&#8211;3 matrix of vertex positions <code>V</code> and an m-by&#8211;3 matrix of
+stored in an n-by-3 matrix of vertex positions <code>V</code> and an m-by-3 matrix of
 triangle indices <code>F</code>.</p>
 
 <p><em>Optionally</em> the library may also be <a href="optional/">pre-compiled</a> into a statically
@@ -121,14 +118,14 @@ libigl depends only on the <a href="http://eigen.tuxfamily.org">Eigen</a> librar
 <p>Libigl compartmentalizes its <strong>optional</strong> dependences via its directory
 organization in the <code>include/</code> folder. All header files located <em>directly</em> in
 the <code>include/igl/</code> folder have only stl and Eigen as dependencies. For example,
-all of the headers that depend on CGAL are located in <code>include/igl/cgal</code>. For a
-full list of <em>optional</em> dependencies check <code>optional/CMakeLists.txt</code>.</p>
+all of the headers that depend on CGAL are located in <code>include/igl/copyleft/cgal</code>.
+For a full list of <em>optional</em> dependencies check <code>optional/CMakeLists.txt</code>.</p>
 
 <h3 id="gccandtheoptionalcgaldependency">GCC and the Optional CGAL Dependency</h3>
 
-<p>The <code>include/igl/cgal/*.h</code> headers depend on CGAL. It has come to our attention
-that CGAL does not work properly with GCC 4.8. To the best of our knowledge,
-GCC 4.7 and clang will work correctly.</p>
+<p>The <code>include/igl/copyleft/cgal/*.h</code> headers depend on CGAL. It has come to
+our attention that CGAL does not work properly with GCC 4.8. To the best of
+our knowledge, GCC 4.7 and clang will work correctly.</p>
 
 <h3 id="openmpandwindows">OpenMP and Windows</h3>
 
@@ -210,7 +207,7 @@ BibTeX entry:</p>
   title = {{libigl}: A simple {C++} geometry processing library},
   author = {Alec Jacobson and Daniele Panozzo and others},
   note = {http://libigl.github.io/libigl/},
-  year = {2016},
+  year = {2017},
 }
 </code></pre>
 
@@ -221,56 +218,59 @@ Eurographics/ACM Symposium on Geometry Processing software award. Here are a
 few labs/companies/institutions using libigl:</p>
 
 <ul>
-<li><a href="http://www.activision.com">Activision</a></li>
-<li><a href="http://www.adobe.com/technology/">Adobe Research</a></li>
-<li><a href="http://www.ea.com">Electronic Arts, Inc</a></li>
-<li><a href="https://epicgames.com">Epic Games</a></li>
-<li><a href="https://research.google.com">Google Research</a></li>
-<li><a href="http://meshconsultants.ca/">Mesh</a>, consultants, Canada</li>
-<li><a href="http://graphics.pixar.com/research/">Pixar Research</a></li>
-<li><a href="http://esotericsoftware.com/">Spine by Esoteric Software</a> is an animation tool dedicated to 2D characters.</li>
-<li>Columbia University, <a href="http://www.cs.columbia.edu/cg/">Columbia Computer Graphics Group</a>, USA</li>
-<li><a href="http://www.graphics.cornell.edu/">Cornell University</a>, USA</li>
-<li><a href="http://dcgi.felk.cvut.cz/">Czech Technical University in Prague</a>, Czech</li>
-<li>EPF Lausanne, <a href="http://lgg.epfl.ch/people.php">Computer Graphics and Geometry Laboratory</a>, Switzerland</li>
-<li>ETH Zurich, <a href="http://igl.ethz.ch/">Interactive Geometry Lab</a> and <a href="http://ait.inf.ethz.ch/">Advanced Technologies Lab</a>, Swizterland</li>
-<li>George Mason University, <a href="http://cs.gmu.edu/~ygingold/">CraGL</a>, USA</li>
-<li><a href="http://www.ust.hk/">Hong Kong University of Science and Technology</a>, Hong Kong</li>
-<li><a href="https://www.inria.fr/centre/grenoble/">Inria, Université Grenoble Alpes</a>, France</li>
-<li><a href="http://english.jiangnan.edu.cn">Jiangnan university</a>, China</li>
-<li><a href="http://www.nii.ac.jp/en/">National Institute of Informatics</a>, Japan</li>
-<li>New York University, <a href="http://mrl.nyu.edu/">Media Research Lab</a>, USA</li>
-<li>NYUPoly, <a href="http://game.engineering.nyu.edu/">Game Innovation Lab</a>, USA</li>
-<li><a href="https://www.cg.tu-berlin.de">TU Berlin</a>, Germany</li>
-<li><a href="http://www.tudelft.nl/en/">TU Delft</a>, Netherlands</li>
-<li><a href="https://www.tuwien.ac.at/en/tuwien_home/">TU Wien</a>, Austria</li>
-<li><a href="http://www.telecom-paristech.fr/en/formation-et-innovation-dans-le-numerique.html">Telecom ParisTech</a>, Paris, France</li>
-<li><a href="http://www.staff.science.uu.nl/~vaxma001/">Utrecht University</a>, The Netherlands</li>
-<li><a href="http://mtm.ufsc.br/~leo/">Universidade Federal de Santa Catarina</a>, Brazil</li>
-<li><a href="http://vecg.cs.ucl.ac.uk/">University College London</a>, England</li>
-<li><a href="http://vis.berkeley.edu/">University of California Berkeley</a>, USA</li>
-<li><a href="http://www.cam.ac.uk/">University of Cambridge</a>, England</li>
-<li><a href="http://cg.cis.upenn.edu/">University of Pennsylvania</a>, USA</li>
-<li><a href="http://www.cs.utexas.edu/users/evouga/">University of Texas at Austin</a>, USA</li>
-<li><a href="http://dgp.toronto.edu">University of Toronto</a>, Canada</li>
-<li><a href="https://www.csc.uvic.ca/Research/graphics/">University of Victoria</a>, Canada</li>
-<li><a href="http://www.uwec.edu/computer-science/">University of Wisconsin-Eau Claire</a>, USA</li>
-<li><a href="http://www.usi.ch/en">Università della Svizzera Italiana</a>, Switzerland</li>
-<li><a href="http://www.univ-tlse3.fr/">Université Toulouse III Paul Sabatier</a>, France</li>
-<li><a href="http://www.math.zju.edu.cn/cagd/">Zhejiang University</a>, China</li>
+<li> <a href="http://www.activision.com">Activision</a></li>
+<li> <a href="http://www.adobe.com/technology/">Adobe Research</a></li>
+<li> <a href="http://www.ea.com">Electronic Arts, Inc</a></li>
+<li> <a href="https://epicgames.com">Epic Games</a></li>
+<li> <a href="https://research.google.com">Google Research</a></li>
+<li> <a href="http://ilm.com">Industrial Light and Magic</a></li>
+<li> <a href="http://meshconsultants.ca/">Mesh consultants</a>, Canada</li>
+<li> <a href="https://www.microsoft.com/en-us/research/">Microsoft Research</a></li>
+<li> <a href="http://graphics.pixar.com/research/">Pixar</a></li>
+<li> <a href="http://esotericsoftware.com/">Spine by Esoteric Software</a> is an animation tool dedicated to 2D characters.</li>
+<li> <a href="http://vvvv.org">vvvv toolkit</a> a multipurpose tookit</li>
+<li> Columbia University, <a href="http://www.cs.columbia.edu/cg/">Columbia Computer Graphics Group</a>, USA</li>
+<li> <a href="http://www.graphics.cornell.edu/">Cornell University</a>, USA</li>
+<li> <a href="http://dcgi.felk.cvut.cz/">Czech Technical University in Prague</a>, Czech</li>
+<li> EPF Lausanne, <a href="http://lgg.epfl.ch/people.php">Computer Graphics and Geometry Laboratory</a>, Switzerland</li>
+<li> ETH Zurich, <a href="http://igl.ethz.ch/">Interactive Geometry Lab</a> and <a href="http://ait.inf.ethz.ch/">Advanced Technologies Lab</a>, Swizterland</li>
+<li> George Mason University, <a href="http://cs.gmu.edu/~ygingold/">CraGL</a>, USA</li>
+<li> <a href="http://www.ust.hk/">Hong Kong University of Science and Technology</a>, Hong Kong</li>
+<li> <a href="https://www.inria.fr/centre/grenoble/">Inria, Université Grenoble Alpes</a>, France</li>
+<li> <a href="http://english.jiangnan.edu.cn">Jiangnan university</a>, China</li>
+<li> <a href="http://www.nii.ac.jp/en/">National Institute of Informatics</a>, Japan</li>
+<li> New York University, <a href="http://mrl.nyu.edu/">Media Research Lab</a>, USA</li>
+<li> NYUPoly, <a href="http://game.engineering.nyu.edu/">Game Innovation Lab</a>, USA</li>
+<li> <a href="https://www.cg.tu-berlin.de">TU Berlin</a>, Germany</li>
+<li> <a href="http://www.tudelft.nl/en/">TU Delft</a>, Netherlands</li>
+<li> <a href="https://www.tuwien.ac.at/en/tuwien_home/">TU Wien</a>, Austria</li>
+<li> <a href="http://www.telecom-paristech.fr/en/formation-et-innovation-dans-le-numerique.html">Telecom ParisTech</a>, Paris, France</li>
+<li> <a href="http://www.staff.science.uu.nl/~vaxma001/">Utrecht University</a>, The Netherlands</li>
+<li> <a href="http://mtm.ufsc.br/~leo/">Universidade Federal de Santa Catarina</a>, Brazil</li>
+<li> <a href="http://vecg.cs.ucl.ac.uk/">University College London</a>, England</li>
+<li> <a href="http://vis.berkeley.edu/">University of California Berkeley</a>, USA</li>
+<li> <a href="http://www.cam.ac.uk/">University of Cambridge</a>, England</li>
+<li> <a href="http://cg.cis.upenn.edu/">University of Pennsylvania</a>, USA</li>
+<li> <a href="http://www.cs.utexas.edu/users/evouga/">University of Texas at Austin</a>, USA</li>
+<li> <a href="http://dgp.toronto.edu">University of Toronto</a>, Canada</li>
+<li> <a href="https://www.csc.uvic.ca/Research/graphics/">University of Victoria</a>, Canada</li>
+<li> <a href="http://www.uwec.edu/computer-science/">University of Wisconsin-Eau Claire</a>, USA</li>
+<li> <a href="http://www.usi.ch/en">Università della Svizzera Italiana</a>, Switzerland</li>
+<li> <a href="http://www.univ-tlse3.fr/">Université Toulouse III Paul Sabatier</a>, France</li>
+<li> <a href="http://www.math.zju.edu.cn/cagd/">Zhejiang University</a>, China</li>
 </ul>
 
 <h2 id="contact">Contact</h2>
 
 <p>Libigl is a group endeavor led by <a href="http://www.cs.toronto.edu/~jacobson/">Alec
 Jacobson</a> and <a href="http://cs.nyu.edu/~panozzo/">Daniele
-Panozzo</a>. Please <a href="&#109;&#97;&#105;&#108;&#x74;&#111;&#x3a;&#x61;&#x6c;&#101;&#x63;&#x6a;&#x61;&#x63;&#111;&#98;&#115;&#111;&#110;&#64;&#103;&#109;&#x61;&#105;&#108;&#x2e;&#x63;&#x6f;&#x6d;&#44;&#x64;&#x61;&#110;&#105;&#101;&#x6c;&#101;&#x2e;&#x70;&#x61;&#110;&#x6f;&#122;&#x7a;&#x6f;&#64;&#x67;&#x6d;&#x61;&#x69;&#x6c;&#x2e;&#99;&#x6f;&#x6d;">&#99;&#x6f;&#x6e;&#116;&#x61;&#99;&#x74;
-&#117;&#115;</a> if you have
+Panozzo</a>. Please <a href="mailto:alecjacobson@gmail.com,daniele.panozzo@gmail.com">contact
+us</a> if you have
 questions or comments. For troubleshooting, please post an
 <a href="https://github.com/libigl/libigl/issues">issue</a> on github.</p>
 
-<p>If you&#8217;re using libigl in your projects, quickly <a href="&#x6d;&#x61;&#105;&#108;&#x74;&#x6f;&#58;&#97;&#x6c;&#101;&#99;&#106;&#x61;&#x63;&#111;&#x62;&#x73;&#x6f;&#110;&#64;&#103;&#x6d;&#x61;&#x69;&#x6c;&#46;&#99;&#x6f;&#x6d;&#x2c;&#100;&#x61;&#110;&#105;&#x65;&#108;&#x65;&#x2e;&#112;&#97;&#x6e;&#111;&#x7a;&#x7a;&#x6f;&#x40;&#103;&#109;&#x61;&#105;&#x6c;&#x2e;&#x63;&#111;&#109;">&#x64;&#x72;&#111;&#112; &#x75;&#x73; &#97;
-&#110;&#111;&#116;&#101;</a>. Tell us who you
+<p>If you&#8217;re using libigl in your projects, quickly <a href="mailto:alecjacobson@gmail.com,daniele.panozzo@gmail.com">drop us a
+note</a>. Tell us who you
 are and what you&#8217;re using it for. This helps us apply for funding and justify
 spending time maintaining this.</p>
 
@@ -279,11 +279,10 @@ page</a>.</p>
 
 <h2 id="copyright">Copyright</h2>
 
-<p>2017 Alec Jacobson, Daniele Panozzo, Christian Schüller, Olga Diamanti, Qingnan
-Zhou, Sebastian Koch, Amir Vaxman, Nico Pietroni, Stefan Brugger, Kenshi Takayama, Wenzel Jakob, Nikolas De
-Giorgis, Luigi Rocca, Leonardo Sacht, Kevin Walliman, Olga Sorkine-Hornung, and others.</p>
+<p>2017 Alec Jacobson, Daniele Panozzo, Christian Schüller, Olga Diamanti, Qingnan Zhou, Sebastian Koch, Jeremie Dumas, Amir Vaxman, Nico Pietroni, Stefan Brugger, Kenshi Takayama, Wenzel Jakob, Nikolas De Giorgis, Luigi Rocca, Leonardo Sacht, Kevin Walliman, Olga Sorkine-Hornung, and others.</p>
 
 <p>Please see individual files for appropriate copyright notices.</p>
 
 </body>
 </html>
+

+ 39 - 41
optional/index.html

@@ -1,14 +1,11 @@
 <!DOCTYPE html>
-<html>
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
 <head>
 	<meta charset="utf-8"/>
 	<title>libigl</title>
 	<meta name="author" content="Alec Jacobson and Daniele Panozzo and others"/>
 	<link type="text/css" rel="stylesheet" href="../tutorial/style.css"/>
-<script type='text/javascript' src='http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML'></script>
-<link rel='stylesheet' href='http://yandex.st/highlightjs/7.3/styles/default.min.css'>
-<script src='http://yandex.st/highlightjs/7.3/highlight.min.js'></script>
-<script>hljs.initHighlightingOnLoad();</script>
+<script type='text/javascript' src='http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML'></script> <link rel='stylesheet' href='http://yandex.st/highlightjs/7.3/styles/default.min.css'> <script src='http://yandex.st/highlightjs/7.3/highlight.min.js'></script> <script>hljs.initHighlightingOnLoad();</script>
 </head>
 <body>
 
@@ -24,7 +21,7 @@ improve your compilation times.</p>
 <p>Libigl is developed most often on Mac OS X, though has current users in Linux
 and Windows.</p>
 
-<h3 id="linuxmacosxcygwin">Linux/Mac OS X/Cygwin</h3>
+<h3 id="linuxmacosxcygwin">Linux/Mac OS X/Cygwin </h3>
 
 <p>Libigl may also be compiled to a static library. This is advantageous when
 building a project with libigl, since when used as an header-only library can
@@ -40,7 +37,7 @@ cmake -DCMAKE_BUILD_TYPE=Release ../optional
 make
 </code></pre>
 
-<h4 id="warnings">Warnings</h4>
+<h4 id="warnings">Warnings </h4>
 
 <p>You should expect to see a few linker warnings of the form:</p>
 
@@ -50,7 +47,7 @@ make
 <p>These are (admittedly unpopular) functions that have never been used by us
 statically so we haven&#8217;t explicit instantiations (yet).</p>
 
-<h4 id="external">External</h4>
+<h4 id="external">External </h4>
 
 <p>Finally there are a number of external libraries that we include in
 <code>./external/</code> because they are either difficult to obtain or they have been
@@ -58,7 +55,7 @@ patched for easier use with libigl. Please see the respective readmes in those
 directories or build the tutorial using cmake, which will recursively build all
 dependencies.</p>
 
-<h5 id="installingembree2.0">Installing Embree 2.0</h5>
+<h5 id="installingembree2.0">Installing Embree 2.0 </h5>
 
 <p>To build the embree library and executables on Mac OS X issue:</p>
 
@@ -74,72 +71,72 @@ make
 #sudo make install
 </code></pre>
 
-<h2 id="extras">Extras</h2>
+<h2 id="extras">Extras </h2>
 
-<h3 id="bbw">bbw</h3>
+<h3 id="bbw">bbw </h3>
 
 <p>This library extra contains functions for computing Bounded Biharmonic Weights, can
 be used with and without the <a href="#mosek">mosek</a> extra via the <code>IGL_NO_MOSEK</code>
 macro.</p>
 
-<h3 id="boolean">boolean</h3>
+<h3 id="boolean">boolean </h3>
 
 <p>This library extra contains functions for computing mesh-mesh booleans,
 depending on CGAL and optionally Cork.</p>
 
-<h3 id="cgal">cgal</h3>
+<h3 id="cgal">cgal </h3>
 
 <p>This library extra utilizes CGAL&#8217;s efficient and exact intersection and
 proximity queries.</p>
 
-<h3 id="embree">embree</h3>
+<h3 id="embree">embree </h3>
 
 <p>This library extra utilizes embree&#8217;s efficient ray tracing queries.</p>
 
-<h3 id="matlab">matlab</h3>
+<h3 id="matlab">matlab </h3>
 
 <p>This library extra provides support for reading and writing <code>.mat</code> workspace
 files, interfacing with Matlab at run time and compiling mex functions.</p>
 
-<h3 id="mosek">mosek</h3>
+<h3 id="mosek">mosek </h3>
 
 <p>This library extra utilizes mosek&#8217;s efficient interior-point solver for
 quadratic programs.</p>
 
-<h3 id="png">png</h3>
+<h3 id="png">png </h3>
 
 <p>This library extra uses <code>libpng</code> and <code>YImage</code> to read and write <code>.png</code> files.</p>
 
-<h3 id="tetgen">tetgen</h3>
+<h3 id="tetgen">tetgen </h3>
 
 <p>This library extra provides a simplified wrapper to the tetgen 3d tetrahedral
 meshing library.</p>
 
-<h3 id="triangle">Triangle</h3>
+<h3 id="triangle">Triangle </h3>
 
 <p>This library extra provides a simplified wrapper to the triangle 2d triangle
 meshing library.</p>
 
-<h3 id="viewer">viewer</h3>
+<h3 id="viewer">viewer </h3>
 
 <p>This library extra utilizes glfw and glew to open an opengl context and launch
 a simple mesh viewer.</p>
 
-<h3 id="xml">xml</h3>
+<h3 id="xml">xml </h3>
 
 <p>This library extra utilizes tinyxml2 to read and write serialized classes
 containing Eigen matrices and other standard simple data-structures.</p>
 
-<h2 id="development">Development</h2>
+<h2 id="development">Development </h2>
 
 <p>Further documentation for developers is listed in
 <a href="../style_guidelines.html">style_guidelines.html</a>.</p>
 
-<h2 id="license">License</h2>
+<h2 id="license">License </h2>
 
 <p>See <code>LICENSE.txt</code></p>
 
-<h2 id="zipping">Zipping</h2>
+<h2 id="zipping">Zipping </h2>
 
 <p>Zip this directory without .git litter and binaries using:</p>
 
@@ -275,28 +272,28 @@ exposing templated functions.</li>
 
 <ul>
 <li><strong>Easy incorporation</strong>: This can be easily incorporated
- into external projects.</li>
+into external projects.</li>
 </ul>
 
 <h3 id="drawbacksofcompressed.h.cpppair">Drawbacks of compressed .h/.cpp pair</h3>
 
 <ul>
 <li><p><strong>Hard to debug/edit</strong>: The compressed files are
- automatically generated. They&#8217;re huge and should not be edited. Thus
- debugging and editing are near impossible.</p></li>
+automatically generated. They&#8217;re huge and should not be edited. Thus
+debugging and editing are near impossible.</p></li>
 <li><p><strong>Compounded dependencies</strong>:
- An immediate disadvantage of this
- seems to be that even to use a single function (e.g.
- <code>cotmatrix</code>), compiling and linking against
- <code>igl.cpp</code> will require linking to all of <code>libigl</code>&#8217;s
- dependencies (<code>OpenGL</code>, <code>GLUT</code>,
- <code>AntTweakBar</code>, <code>BLAS</code>). However, because all
- dependencies other than Eigen should be encapsulated between
- <code>#ifndef</code> guards (e.g. <code>#ifndef IGL_NO_OPENGL</code>, it
- is possible to ignore certain functions that have such dependencies.</p></li>
+An immediate disadvantage of this
+seems to be that even to use a single function (e.g.
+<code>cotmatrix</code>), compiling and linking against
+<code>igl.cpp</code> will require linking to all of <code>libigl</code>&#8217;s
+dependencies (<code>OpenGL</code>, <code>GLUT</code>,
+<code>AntTweakBar</code>, <code>BLAS</code>). However, because all
+dependencies other than Eigen should be encapsulated between
+<code>#ifndef</code> guards (e.g. <code>#ifndef IGL_NO_OPENGL</code>, it
+is possible to ignore certain functions that have such dependencies.</p></li>
 <li><p><strong>Long compile</strong>:
- Compiling <code>igl.cpp</code> takes a long time and isn&#8217;t easily parallelized (no <code>make
-  -j12</code> equivalent).</p></li>
+Compiling <code>igl.cpp</code> takes a long time and isn&#8217;t easily parallelized (no <code>make
+-j12</code> equivalent).</p></li>
 </ul>
 
 <p>Here&#8217;s a tiny test example using <code>igl.h</code> and <code>igl.cpp</code>. Save the following in <code>test.cpp</code>:</p>
@@ -334,7 +331,7 @@ return (argc&gt;=2 &amp;&amp; igl::read_triangle_mesh(argv[1],V,F)?0:1);
 <pre><code>grep OpenGL `grep -L IGL_NO_OPENGL include/igl/*`
 </code></pre>
 
-<h3 id="optional">Optional</h3>
+<h3 id="optional">Optional </h3>
 
 <ul>
 <li>OpenGL (disable with <code>IGL_NO_OPENGL</code>)
@@ -343,7 +340,7 @@ return (argc&gt;=2 &amp;&amp; igl::read_triangle_mesh(argv[1],V,F)?0:1);
 <li>OpenGL &gt;= 4 (enable with <code>IGL_OPENGL_4</code>)</li>
 </ul></li>
 <li>AntTweakBar (disable with <code>IGL_NO_ANTTWEAKBAR</code>) Last tested 1.16 (see
- <code>libigl/external/AntTweakBar</code>)</li>
+<code>libigl/external/AntTweakBar</code>)</li>
 <li>GLEW Windows and Linux</li>
 <li>OpenMP</li>
 <li>libpng libiglpng extra only</li>
@@ -361,7 +358,7 @@ return (argc&gt;=2 &amp;&amp; igl::read_triangle_mesh(argv[1],V,F)?0:1);
 <li>CoMiSo libcomiso extra only</li>
 </ul>
 
-<h3 id="optionalincludedinexternal">Optional (included in external/)</h3>
+<h3 id="optionalincludedinexternal">Optional (included in external/) </h3>
 
 <ul>
 <li>TetGen libigltetgen extra only</li>
@@ -373,3 +370,4 @@ return (argc&gt;=2 &amp;&amp; igl::read_triangle_mesh(argv[1],V,F)?0:1);
 
 </body>
 </html>
+

+ 7 - 7
python/iglhelpers.py

@@ -11,15 +11,15 @@ import pyigl as igl
 
 def p2e(m):
     if isinstance(m, np.ndarray):
-        if not m.flags['C_CONTIGUOUS']:
-            raise TypeError("p2e only support C-contiguous order")
-        if m.dtype.type == np.int32:
-            return igl.eigen.MatrixXi(m)
-        elif m.dtype.type == np.float64:
-            return igl.eigen.MatrixXd(m)
+        if not (m.flags['C_CONTIGUOUS'] or m.flags['F_CONTIGUOUS']):
+            raise TypeError('p2e support either c-order or f-order')
+        if m.dtype.type in [np.int32, np.int64]:
+            return igl.eigen.MatrixXi(m.astype(np.int32))
+        elif m.dtype.type in [np.float64, np.float32]:
+            return igl.eigen.MatrixXd(m.astype(np.float64))
         elif m.dtype.type == np.bool:
             return igl.eigen.MatrixXb(m)
-        raise TypeError("p2e only support dtype float64, int32 and bool")
+        raise TypeError("p2e only support dtype float64/32, int64/32 and bool")
     if sparse.issparse(m):
         # convert in a dense matrix with triples
         coo = m.tocoo()

+ 47 - 0
python/py_doc.cpp

@@ -598,6 +598,23 @@ const char *__doc_igl_embree_reorient_facets_raycast = R"igl_Qu8mg5v7(// Orient
     // Outputs:
     //   I  #F list of whether face has been flipped
     //   C  #F list of patch ID (output of bfs_orient > manifold patches))igl_Qu8mg5v7";
+const char *__doc_igl_exact_geodesic = R"igl_Qu8mg5v7( 
+    // Exact geodesic algorithm for triangular mesh with the implementation from https://code.google.com/archive/p/geodesic/,  
+    // and the algorithm first described by Mitchell, Mount and Papadimitriou in 1987 
+    //  
+    // Inputs: 
+    //   V  #V by 3 list of 3D vertex positions 
+    //   F  #F by 3 list of mesh faces 
+    //   VS #VS by 1 vector specifying indices of source vertices 
+    //   FS #FS by 1 vector specifying indices of source faces 
+    //   VT #VT by 1 vector specifying indices of target vertices 
+    //   FT #FT by 1 vector specifying indices of target faces 
+    // Output: 
+    //   D  #VT+#FT by 1 vector of geodesic distances of each target w.r.t. the nearest one in the source set 
+    // 
+    // Note:  
+    //      Specifying a face as target/source means its center.  
+    //)igl_Qu8mg5v7";
 const char *__doc_igl_find_cross_field_singularities = R"igl_Qu8mg5v7(// Inputs:
   //   V                #V by 3 eigen Matrix of mesh vertex 3D positions
   //   F                #F by 3 eigen Matrix of face (quad) indices
@@ -1453,3 +1470,33 @@ const char *__doc_igl_readPLY= R"igl_Qu8mg5v7(// Read a mesh from an ascii ply f
   //   N  double matrix of corner normals #N by 3
   //   UV #V by 2 texture coordinates
   // Returns true on success, false on errors)igl_Qu8mg5v7";
+const char *__doc_igl_seam_edges=R"igl_Qu8mg5v7(// Finds all UV-space boundaries of a mesh.
+  //
+  // Inputs:
+  //   V  #V by dim list of positions of the input mesh.
+  //   TC  #TC by 2 list of 2D texture coordinates of the input mesh
+  //   F  #F by 3 list of triange indices into V representing a
+  //     manifold-with-boundary triangle mesh
+  //   FTC  #F by 3 list of indices into TC for each corner
+  // Outputs:
+  //   seams  Edges where the forwards and backwards directions have different
+  //     texture coordinates, as a #seams-by-4 matrix of indices. Each row is
+  //     organized as [ forward_face_index, forward_face_vertex_index,
+  //     backwards_face_index, backwards_face_vertex_index ] such that one side
+  //     of the seam is the edge:
+  //         F[ seams( i, 0 ), seams( i, 1 ) ], F[ seams( i, 0 ), (seams( i, 1 ) + 1) % 3 ]
+  //     and the other side is the edge:
+  //         F[ seams( i, 2 ), seams( i, 3 ) ], F[ seams( i, 2 ), (seams( i, 3 ) + 1) % 3 ]
+  //   boundaries  Edges with only one incident triangle, as a #boundaries-by-2
+  //     matrix of indices. Each row is organized as 
+  //         [ face_index, face_vertex_index ]
+  //     such that the edge is:
+  //         F[ boundaries( i, 0 ), boundaries( i, 1 ) ], F[ boundaries( i, 0 ), (boundaries( i, 1 ) + 1) % 3 ]
+  //   foldovers  Edges where the two incident triangles fold over each other
+  //     in UV-space, as a #foldovers-by-4 matrix of indices.
+  //     Each row is organized as [ forward_face_index, forward_face_vertex_index,
+  //     backwards_face_index, backwards_face_vertex_index ]
+  //     such that one side of the foldover is the edge:
+  //       F[ foldovers( i, 0 ), foldovers( i, 1 ) ], F[ foldovers( i, 0 ), (foldovers( i, 1 ) + 1) % 3 ]
+  //     and the other side is the edge:
+  //       F[ foldovers( i, 2 ), foldovers( i, 3 ) ], F[ foldovers( i, 2 ), (foldovers( i, 3 ) + 1) % 3 ])igl_Qu8mg5v7";

+ 3 - 1
python/py_doc.h

@@ -48,6 +48,7 @@ extern const char *__doc_igl_eigs;
 extern const char *__doc_igl_embree_ambient_occlusion;
 extern const char *__doc_igl_embree_line_mesh_intersection;
 extern const char *__doc_igl_embree_reorient_facets_raycast;
+extern const char *__doc_igl_exact_geodesic;
 extern const char *__doc_igl_find_cross_field_singularities;
 extern const char *__doc_igl_fit_rotations;
 extern const char *__doc_igl_fit_rotations_planar;
@@ -99,6 +100,7 @@ extern const char *__doc_igl_readTGF;
 extern const char *__doc_igl_read_triangle_mesh;
 extern const char *__doc_igl_remove_duplicate_vertices;
 extern const char *__doc_igl_rotate_vectors;
+extern const char *__doc_igl_seam_edges;
 extern const char *__doc_igl_setdiff;
 extern const char *__doc_igl_signed_distance;
 extern const char *__doc_igl_signed_distance_pseudonormal;
@@ -125,4 +127,4 @@ extern const char *__doc_igl_winding_number_2;
 extern const char *__doc_igl_writeMESH;
 extern const char *__doc_igl_writeOBJ;
 extern const char *__doc_igl_writePLY;
-extern const char *__doc_igl_readPLY;
+extern const char *__doc_igl_readPLY;

+ 4 - 0
python/py_igl.cpp

@@ -44,6 +44,7 @@
 #include <igl/edge_lengths.h>
 #include <igl/edge_topology.h>
 #include <igl/eigs.h>
+#include <igl/exact_geodesic.h>
 #include <igl/find_cross_field_singularities.h>
 #include <igl/fit_rotations.h>
 #include <igl/floor.h>
@@ -102,6 +103,7 @@
 #include <igl/writeOBJ.h>
 #include <igl/writePLY.h>
 #include <igl/readPLY.h>
+#include <igl/seam_edges.h>
 
 void python_export_igl(py::module &m)
 {
@@ -141,6 +143,7 @@ void python_export_igl(py::module &m)
 #include "py_igl/py_edge_lengths.cpp"
 #include "py_igl/py_edge_topology.cpp"
 #include "py_igl/py_eigs.cpp"
+#include "py_igl/py_exact_geodesic.cpp"
 #include "py_igl/py_find_cross_field_singularities.cpp"
 #include "py_igl/py_fit_rotations.cpp"
 #include "py_igl/py_floor.cpp"
@@ -199,4 +202,5 @@ void python_export_igl(py::module &m)
 #include "py_igl/py_writeOBJ.cpp"
 #include "py_igl/py_writePLY.cpp"
 #include "py_igl/py_readPLY.cpp"
+#include "py_igl/py_seam_edges.cpp"
 }

+ 24 - 0
python/py_igl/py_exact_geodesic.cpp

@@ -0,0 +1,24 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2018 Zhongshi Jiang <jiangzs@nyu.edu>
+//
+// 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/.
+
+
+m.def("exact_geodesic", []
+(
+    const Eigen::MatrixXd &V,
+    const Eigen::MatrixXi &F,
+    const Eigen::MatrixXi &VS,
+    const Eigen::MatrixXi &FS,
+    const Eigen::MatrixXi &VT,
+    const Eigen::MatrixXi &FT,
+    Eigen::MatrixXd &D
+)
+{
+  return igl::exact_geodesic(V, F, VS,FS,VT,FT, D);
+}, __doc_igl_exact_geodesic,
+py::arg("V"), py::arg("F"), py::arg("VS"), py::arg("FS"), py::arg("VT"), py::arg("FT"), py::arg("D"));
+

+ 21 - 0
python/py_igl/py_seam_edges.cpp

@@ -0,0 +1,21 @@
+m.def("seam_edges", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXd& TC,
+  const Eigen::MatrixXi& F,
+  const Eigen::MatrixXi& FTC,
+  Eigen::MatrixXi& seams,
+  Eigen::MatrixXi& boundaries,
+  Eigen::MatrixXi& foldovers
+)
+{
+return igl::seam_edges( V, TC, F, FTC, seams, boundaries, foldovers);
+}, __doc_igl_seam_edges,
+py::arg("V"),
+py::arg("TC"),
+py::arg("F"),
+py::arg("FTC"),
+py::arg("seams"),
+py::arg("boundaries"),
+py::arg("foldovers"));
+

+ 38 - 32
shared/cmake/libigl.cmake

@@ -1,24 +1,42 @@
 cmake_minimum_required(VERSION 3.1)
 
+### Find packages to populate default options ###
+#
+# COMPONENTS should match subsequent calls
+find_package(CGAL COMPONENTS Core) # --> CGAL_FOUND
+find_package(Boost 1.48 COMPONENTS thread system) # --> BOOST_FOUND
+if(CGAL_FOUND AND BOOST_FOUND)
+  set(CGAL_AND_BOOST_FOUND TRUE)
+endif()
+find_package(Matlab COMPONENTS MEX_COMPILER MX_LIBRARY ENG_LIBRARY) # --> Matlab_FOUND
+find_package(MOSEK) # --> MOSEK_FOUND
+find_package(OpenGL) # --> OPENGL_FOUND
+
 ### Available options ###
 option(LIBIGL_USE_STATIC_LIBRARY     "Use libigl as static library" OFF)
 option(LIBIGL_WITH_ANTTWEAKBAR       "Use AntTweakBar"    OFF)
-option(LIBIGL_WITH_CGAL              "Use CGAL"           ON)
+option(LIBIGL_WITH_CGAL              "Use CGAL"           "${CGAL_AND_BOOST_FOUND}")
 option(LIBIGL_WITH_COMISO            "Use CoMiso"         ON)
 option(LIBIGL_WITH_CORK              "Use Cork"           OFF)
 option(LIBIGL_WITH_EMBREE            "Use Embree"         OFF)
 option(LIBIGL_WITH_LIM               "Use LIM"            ON)
-option(LIBIGL_WITH_MATLAB            "Use Matlab"         ON)
-option(LIBIGL_WITH_MOSEK             "Use MOSEK"          ON)
-option(LIBIGL_WITH_OPENGL            "Use OpenGL"         ON)
-option(LIBIGL_WITH_OPENGL_GLFW       "Use GLFW"           ON)
-option(LIBIGL_WITH_OPENGL_GLFW_IMGUI "Use ImGui"          ON)
+option(LIBIGL_WITH_MATLAB            "Use Matlab"         "${Matlab_FOUND}")
+option(LIBIGL_WITH_MOSEK             "Use MOSEK"          "${MOSEK_FOUND}")
+option(LIBIGL_WITH_NANOGUI           "Use Nanogui menu"   OFF)
+option(LIBIGL_WITH_OPENGL            "Use OpenGL"         "${OPENGL_FOUND}")
+option(LIBIGL_WITH_OPENGL_GLFW       "Use GLFW"           "${OPENGL_FOUND}")
+option(LIBIGL_WITH_OPENGL_GLFW_IMGUI "Use IMGUI"          OFF)
 option(LIBIGL_WITH_PNG               "Use PNG"            ON)
 option(LIBIGL_WITH_TETGEN            "Use Tetgen"         ON)
 option(LIBIGL_WITH_TRIANGLE          "Use Triangle"       ON)
+option(LIBIGL_WITH_VIEWER            "Use OpenGL viewer"  "${OPENGL_FOUND}")
 option(LIBIGL_WITH_XML               "Use XML"            ON)
 option(LIBIGL_WITH_PYTHON            "Use Python"         OFF)
 
+if(LIBIGL_WITH_VIEWER AND (NOT LIBIGL_WITH_OPENGL_GLFW OR NOT LIBIGL_WITH_OPENGL) )
+  message(FATAL_ERROR "LIBIGL_WITH_VIEWER=ON requires LIBIGL_WITH_OPENGL_GLFW=ON and LIBIGL_WITH_OPENGL=ON")
+endif()
+
 ################################################################################
 
 ### Configuration
@@ -131,7 +149,7 @@ if(LIBIGL_WITH_CGAL)
   if(EXISTS ${LIBIGL_EXTERNAL}/boost)
     set(BOOST_ROOT "${LIBIGL_EXTERNAL}/boost")
   endif()
-  find_package(CGAL COMPONENTS Core)
+  find_package(CGAL REQUIRED COMPONENTS Core)
   if(CGAL_FOUND)
     compile_igl_module("cgal")
     if(WIN32)
@@ -144,6 +162,10 @@ if(LIBIGL_WITH_CGAL)
   else()
     set(LIBIGL_WITH_CGAL OFF CACHE BOOL "" FORCE)
   endif()
+  target_include_directories(igl_cgal ${IGL_SCOPE} "${GMP_INCLUDE_DIR}" "${MPFR_INCLUDE_DIR}")
+  find_package(Boost 1.48 REQUIRED thread system)
+  target_include_directories(igl_cgal ${IGL_SCOPE} ${CGAL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
+  target_link_libraries(igl_cgal ${IGL_SCOPE} CGAL::CGAL CGAL::CGAL_Core ${Boost_LIBRARIES})
 endif()
 
 # Helper function for `igl_copy_cgal_dll()`
@@ -251,28 +273,20 @@ endif()
 ################################################################################
 ### Compile the matlab part ###
 if(LIBIGL_WITH_MATLAB)
-  find_package(Matlab)
-  if(MATLAB_FOUND)
-    compile_igl_module("matlab")
-    target_link_libraries(igl_matlab ${IGL_SCOPE} ${MATLAB_LIBRARIES})
-    target_include_directories(igl_matlab ${IGL_SCOPE} ${MATLAB_INCLUDE_DIR})
-  else()
-    set(LIBIGL_WITH_MATLAB OFF CACHE BOOL "" FORCE)
-  endif()
+  find_package(Matlab REQUIRED COMPONENTS MEX_COMPILER MX_LIBRARY ENG_LIBRARY)
+  compile_igl_module("matlab")
+  target_link_libraries(igl_matlab ${IGL_SCOPE} ${Matlab_LIBRARIES})
+  target_include_directories(igl_matlab ${IGL_SCOPE} ${Matlab_INCLUDE_DIRS})
 endif()
 
 ################################################################################
 ### Compile the mosek part ###
 if(LIBIGL_WITH_MOSEK)
-  find_package(MOSEK)
-  if(MOSEK_FOUND)
-    compile_igl_module("mosek")
-    target_link_libraries(igl_mosek ${IGL_SCOPE} ${MOSEK_LIBRARIES})
-    target_include_directories(igl_mosek ${IGL_SCOPE} ${MOSEK_INCLUDE_DIRS})
-    target_compile_definitions(igl_mosek ${IGL_SCOPE} -DLIBIGL_WITH_MOSEK)
-  else()
-    set(LIBIGL_WITH_MOSEK OFF CACHE BOOL "" FORCE)
-  endif()
+  find_package(MOSEK REQUIRED)
+  compile_igl_module("mosek")
+  target_link_libraries(igl_mosek ${IGL_SCOPE} ${MOSEK_LIBRARIES})
+  target_include_directories(igl_mosek ${IGL_SCOPE} ${MOSEK_INCLUDE_DIRS})
+  target_compile_definitions(igl_mosek ${IGL_SCOPE} -DLIBIGL_WITH_MOSEK)
 endif()
 
 ################################################################################
@@ -307,9 +321,6 @@ if(LIBIGL_WITH_OPENGL_GLFW)
       add_subdirectory(${LIBIGL_EXTERNAL}/glfw glfw)
     endif()
     target_link_libraries(igl_opengl_glfw ${IGL_SCOPE} igl_opengl glfw)
-  else()
-    message(WARNING "GLFW module could not be compiled")
-    set(LIBIGL_WITH_OPENGL_GLFW OFF CACHE BOOL "" FORCE)
   endif()
 endif()
 
@@ -324,9 +335,6 @@ if(LIBIGL_WITH_OPENGL_GLFW_IMGUI)
       add_subdirectory(${LIBIGL_EXTERNAL}/imgui imgui)
     endif()
     target_link_libraries(igl_opengl_glfw_imgui ${IGL_SCOPE} igl_opengl_glfw imgui)
-  else()
-    message(WARNING "ImGui module could not be compiled")
-    set(LIBIGL_WITH_OPENGL_GLFW_IMGUI OFF CACHE BOOL "" FORCE)
   endif()
 endif()
 
@@ -342,8 +350,6 @@ if(LIBIGL_WITH_PNG)
     endif()
     compile_igl_module("png" "")
     target_link_libraries(igl_png ${IGL_SCOPE} igl_stb_image igl_opengl)
-  else()
-    set(LIBIGL_WITH_PNG OFF CACHE BOOL "" FORCE)
   endif()
 endif()
 

+ 14 - 16
style-guidelines.html

@@ -1,14 +1,11 @@
 <!DOCTYPE html>
-<html>
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
 <head>
 	<meta charset="utf-8"/>
 	<title>libigl</title>
 	<meta name="author" content="Alec Jacobson and Daniele Panozzo and others"/>
 	<link type="text/css" rel="stylesheet" href="tutorial/style.css"/>
-<script type='text/javascript' src='http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML'></script>
-<link rel='stylesheet' href='http://yandex.st/highlightjs/7.3/styles/default.min.css'>
-<script src='http://yandex.st/highlightjs/7.3/highlight.min.js'></script>
-<script>hljs.initHighlightingOnLoad();</script>
+<script type='text/javascript' src='http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML'></script> <link rel='stylesheet' href='http://yandex.st/highlightjs/7.3/styles/default.min.css'> <script src='http://yandex.st/highlightjs/7.3/highlight.min.js'></script> <script>hljs.initHighlightingOnLoad();</script>
 </head>
 <body>
 
@@ -18,7 +15,7 @@
 style guidelines for <em>developers</em> of the library, but also acts as
 best-practices for users.</p>
 
-<h2 id="filefunction">One function, one .h/.cpp pair</h2>
+<h2 id="filefunction">One function, one .h/.cpp pair </h2>
 
 <p>The structure of libigl is very flat and function-based. For every
 function/sub-routine, create a single .h and .cpp file. For example, if you have
@@ -61,7 +58,7 @@ namespace igl
 }
 
 #ifndef IGL_STATIC_LIBRARY
-#  include &quot;example_fun.cpp&quot;
+#include &quot;example_fun.cpp&quot;
 #endif
 
 #endif
@@ -185,21 +182,21 @@ Eigen::SparseMatrix&lt;Atype&gt; adjacency_matrix(const ... &amp; F);
 <h2 id="templatingwitheigen">Templating with Eigen</h2>
 
 <p>Functions taking Eigen dense matrices/arrays as inputs and outputs (but <strong>not</strong>
-return arguments), should template on top of <code>Eigen::PlainObjectBase</code>. <strong>Each
+return arguments), should template on top of <code>Eigen::MatrixBase</code>. <strong>Each
 parameter</strong> should be derived using its own template.</p>
 
 <p>For example,</p>
 
 <pre><code class="cpp">template &lt;typename DerivedV, typename DerivedF, typename DerivedBC&gt;
 void barycenter(
-  const Eigen::PlainObjectBase&lt;DerivedV&gt; &amp; V,
-  const Eigen::PlainObjectBase&lt;DerivedF&gt; &amp; F,
-  const Eigen::PlainObjectBase&lt;DerivedBC&gt; &amp; BC);
+  const Eigen::MatrixBase&lt;DerivedV&gt; &amp; V,
+  const Eigen::MatrixBase&lt;DerivedF&gt; &amp; F,
+  const Eigen::MatrixBase&lt;DerivedBC&gt; &amp; BC);
 </code></pre>
 
 <p>The <code>Derived*</code> template encodes the scalar type (e.g. <code>double</code>, <code>int</code>), the
 number of rows and cols at compile time, and the data storage (Row-major vs.
-column-major). </p>
+column-major).</p>
 
 <p>Returning Eigen types is discouraged. In cases where the size and scalar type
 are a fixed <strong>and matching</strong> function of an input <code>Derived*</code> template, then
@@ -219,7 +216,7 @@ output-argument version and call that. So a full implementation looks like:</p>
 
 <pre><code class="cpp">template &lt;typename DerivedV, typename DerivedW&gt;
 void fit_to_unit_cube(
-  const Eigen::PlainObjectBase&lt;DerivedV&gt; &amp; V,
+  const Eigen::MatrixBase&lt;DerivedV&gt; &amp; V,
   Eigen::PlainObjectBase&lt;DerivedW&gt; &amp; W);
 template &lt;typename DerivedV&gt;
 void DerivedV fit_to_unit_cube(const Eigen::PlainObjectBase&lt;DerivedV&gt; &amp; V);
@@ -229,7 +226,7 @@ void DerivedV fit_to_unit_cube(const Eigen::PlainObjectBase&lt;DerivedV&gt; &amp
 
 <pre><code>template &lt;typename DerivedV, typename DerivedW&gt;
 void fit_to_unit_cube(
-  const Eigen::PlainObjectBase&lt;DerivedV&gt; &amp; V,
+  const Eigen::MatrixBase&lt;DerivedV&gt; &amp; V,
   Eigen::PlainObjectBase&lt;DerivedW&gt; &amp; W)
 {
   W = (V.rowwise()-V.colwise().minCoeff()).array() /
@@ -237,7 +234,7 @@ void fit_to_unit_cube(
 }
 
 template &lt;typename DerivedV&gt;
-void DerivedV fit_to_unit_cube(const Eigen::PlainObjectBase&lt;DerivedV&gt; &amp; V)
+void DerivedV fit_to_unit_cube(const Eigen::MatrixBase&lt;DerivedV&gt; &amp; V)
 {
   DerivedV W;
   fit_to_unit_cube(V,W);
@@ -274,7 +271,7 @@ to mean a list of faces/triangles.</p>
 <p>Classes should be avoided. When naming a class use CamelCase (e.g.
 SortableRow.h).</p>
 
-<h2 id="enumnamingconvertion">Enum naming conversion</h2>
+<h2 id="enumnamingconversion">Enum naming conversion</h2>
 
 <p>Enums types should be placed in the appropriate <code>igl::</code> namespace and should be
 named in CamelCase (e.g. <code>igl::SolverStatus</code>) and instances should be named in
@@ -392,3 +389,4 @@ implementation so we&#8217;re keeping it as long as possible and profitable.</p>
 
 </body>
 </html>
+

+ 1 - 1
tutorial/107_MultipleMeshes/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(107_MultipleMeshes)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw igl::opengl_glfw_imgui tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 15 - 48
tutorial/107_MultipleMeshes/main.cpp

@@ -1,68 +1,35 @@
 #include "tutorial_shared_path.h"
 #include <igl/opengl/glfw/Viewer.h>
-#include <igl/opengl/glfw/imgui/ImGuiMenu.h>
-#include <igl/opengl/glfw/imgui/ImGuiHelpers.h>
+#include <GLFW/glfw3.h>
 #include <string>
-#include <map>
 #include <iostream>
 
-// Add custom data to a viewer mesh
-struct MeshData
-{
-  std::string name;
-  Eigen::RowVector3d color;
-};
-int last_colored_index = -1;
-
-// Set colors of each mesh
-void update_colors(igl::opengl::glfw::Viewer &viewer)
-{
-  for (auto &data : viewer.data_list)
-  {
-    data.set_colors(data.attr<MeshData>().color);
-  }
-  viewer.data_list[viewer.selected_data_index].set_colors(Eigen::RowVector3d(0.9,0.1,0.1));
-  last_colored_index = viewer.selected_data_index;
-}
-
 int main(int argc, char * argv[])
 {
   igl::opengl::glfw::Viewer viewer;
-  auto names = {"cube.obj","sphere.obj","xcylinder.obj","ycylinder.obj","zcylinder.obj"};
+  const auto names = 
+    {"cube.obj","sphere.obj","xcylinder.obj","ycylinder.obj","zcylinder.obj"};
   for(const auto & name : names)
   {
     viewer.load_mesh_from_file(std::string(TUTORIAL_SHARED_PATH) + "/" + name);
-    viewer.data().attr<MeshData>().name = name;
-    viewer.data().attr<MeshData>().color = Eigen::RowVector3d::Random();
   }
 
-  // Attach a custom menu
-  igl::opengl::glfw::imgui::ImGuiMenu menu;
-  viewer.plugins.push_back(&menu);
-
-  // Customize default menu
-  menu.draw_viewer_menu_func = [&]()
-  {
-    if (ImGui::Combo("Selected Mesh", (int *) &viewer.selected_data_index,
-          [&](int i) { return viewer.data_list[i].attr<MeshData>().name.c_str(); },
-          viewer.data_list.size())
-      || last_colored_index != viewer.selected_data_index)
-    {
-      update_colors(viewer);
-    }
-  };
-
-  // Color each mesh differently
-  update_colors(viewer);
-
-  viewer.callback_key_down =
+  // Set colors of each mesh by selecting its index first
+  viewer.selected_data_index = 0;
+  viewer.data().set_colors(Eigen::RowVector3d(0.8,0.47,0.22));
+  viewer.selected_data_index = 1;
+  viewer.data().set_colors(Eigen::RowVector3d(0.6,0.01,0.11));
+  viewer.selected_data_index = 2;
+  viewer.data().set_colors(Eigen::RowVector3d(0.37,0.06,0.25));
+  viewer.selected_data_index = 3;
+  viewer.data().set_colors(Eigen::RowVector3d(1,1,1));
+
+  viewer.callback_key_down = 
     [&](igl::opengl::glfw::Viewer &, unsigned int key, int mod)
   {
-    // Delete
-    if(key == '3')
+    if(key == GLFW_KEY_BACKSPACE)
     {
       viewer.erase_mesh(viewer.selected_data_index);
-      update_colors(viewer);
       return true;
     }
     return false;

+ 5 - 0
tutorial/206_GeodesicDistance/CMakeLists.txt

@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.8.12)
+project(206_GeodesicDistance)
+
+add_executable(${PROJECT_NAME}_bin main.cpp)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 74 - 0
tutorial/206_GeodesicDistance/main.cpp

@@ -0,0 +1,74 @@
+#include <igl/readOBJ.h>
+#include <igl/opengl/glfw/Viewer.h>
+#include <igl/exact_geodesic.h>
+#include <igl/colormap.h>
+#include <igl/unproject_onto_mesh.h>
+#include <iostream>
+#include "tutorial_shared_path.h"
+
+
+int main(int argc, char *argv[])
+{
+  using namespace Eigen;
+  using namespace std;
+  Eigen::MatrixXd V;
+  Eigen::MatrixXi F;
+  igl::opengl::glfw::Viewer viewer;
+  // Load a mesh in OFF format
+  igl::readOBJ(TUTORIAL_SHARED_PATH "/armadillo.obj", V, F);
+
+  const auto update_distance = [&](const int vid)
+  {
+    Eigen::VectorXi VS,FS,VT,FT;
+    // The selected vertex is the source
+    VS.resize(1);
+    VS << vid;
+    // All vertices are the targets
+    VT.setLinSpaced(V.rows(),0,V.rows()-1);
+    Eigen::VectorXd d;
+    std::cout<<"Computing geodesic distance to vertex "<<vid<<"..."<<std::endl;
+    igl::exact_geodesic(V,F,VS,FS,VT,FT,d);
+    const double strip_size = 0.05;
+    // The function should be 1 on each integer coordinate
+    d = (d/strip_size*M_PI).array().sin().abs().eval();
+    // Compute per-vertex colors
+    Eigen::MatrixXd C;
+    igl::colormap(igl::COLOR_MAP_TYPE_INFERNO,d,false,C);
+    // Plot the mesh
+    viewer.data().set_mesh(V, F);
+    viewer.data().set_colors(C);
+  };
+
+  // Plot a distance when a vertex is picked
+  viewer.callback_mouse_down =
+  [&](igl::opengl::glfw::Viewer& viewer, int, int)->bool
+  {
+    int fid;
+    Eigen::Vector3f bc;
+    // Cast a ray in the view direction starting from the mouse position
+    double x = viewer.current_mouse_x;
+    double y = viewer.core.viewport(3) - viewer.current_mouse_y;
+    if(igl::unproject_onto_mesh(
+      Eigen::Vector2f(x,y), 
+      viewer.core.view * viewer.core.model,
+      viewer.core.proj, 
+      viewer.core.viewport, 
+      V, 
+      F, 
+      fid, 
+      bc))
+    {
+      int max;
+      bc.maxCoeff(&max);
+      int vid = F(fid,max);
+      update_distance(vid);
+      return true;
+    }
+    return false;
+  };
+  viewer.data().set_mesh(V,F);
+
+  cout << "Click on mesh to define new source.\n" << std::endl;
+  update_distance(0);
+  return viewer.launch();
+}

+ 5 - 0
tutorial/306_EigenDecomposition/main.cpp

@@ -36,6 +36,7 @@ int main(int argc, char * argv[])
   {
     cout<<"failed."<<endl;
   }
+  // Normalize
   U = ((U.array()-U.minCoeff())/(U.maxCoeff()-U.minCoeff())).eval();
 
   igl::opengl::glfw::Viewer viewer;
@@ -67,5 +68,9 @@ int main(int argc, char * argv[])
   };
   viewer.callback_key_down(viewer,' ',0);
   viewer.data().show_lines = false;
+  std::cout<<
+R"(
+  [space] Cycle through eigen modes
+)";
   viewer.launch();
 }

+ 4 - 1
tutorial/CMakeLists.txt

@@ -53,7 +53,9 @@ if(TUTORIALS_CHAPTER1)
   add_subdirectory("103_Events")
   add_subdirectory("104_Colors")
   add_subdirectory("105_Overlays")
-  add_subdirectory("106_ViewerMenu")
+  if(LIBIGL_WITH_OPENGL_GLFW_IMGUI)
+    add_subdirectory("106_ViewerMenu")
+  endif()
   add_subdirectory("107_MultipleMeshes")
 endif()
 
@@ -64,6 +66,7 @@ if(TUTORIALS_CHAPTER2)
   add_subdirectory("203_CurvatureDirections")
   add_subdirectory("204_Gradient")
   add_subdirectory("205_Laplacian")
+  add_subdirectory("206_GeodesicDistance")
 endif()
 
 # Chapter 3

BIN
tutorial/images/geodesicdistance.jpg


+ 1 - 1
tutorial/tutorial.html.REMOVED.git-id

@@ -1 +1 @@
-1dcb725e3bc41af89154fbadfd4b1d57e254c3a2
+8f9d830ca895398a806d67d62fd7f4598bb9f21a

+ 1 - 1
tutorial/tutorial.md.REMOVED.git-id

@@ -1 +1 @@
-96b0c1c12294ce44a5b90bad2868b33da79766a2
+41fe9810ef010cff31200f3c415b9c005560c67f