瀏覽代碼

Merge branch 'dev' into multiple-views

Jérémie Dumas 6 年之前
父節點
當前提交
1d12983ce2
共有 100 個文件被更改,包括 2793 次插入993 次删除
  1. 12 5
      .appveyor.yml
  2. 1 1
      .travis.yml
  3. 4 0
      CMakeLists.txt
  4. 1 0
      cmake/DownloadProject.CMakeLists.cmake.in
  5. 15 15
      cmake/LibiglDownloadExternal.cmake
  6. 22 0
      cmake/LibiglWindows.cmake
  7. 9 27
      cmake/libigl.cmake
  8. 1 0
      include/igl/AABB.cpp
  9. 5 5
      include/igl/adjacency_list.cpp
  10. 1 1
      include/igl/adjacency_list.h
  11. 2 0
      include/igl/barycenter.cpp
  12. 5 0
      include/igl/bbw.cpp
  13. 8 8
      include/igl/boundary_facets.cpp
  14. 2 2
      include/igl/boundary_facets.h
  15. 4 4
      include/igl/boundary_loop.cpp
  16. 3 3
      include/igl/boundary_loop.h
  17. 4 6
      include/igl/circulation.cpp
  18. 1 6
      include/igl/circulation.h
  19. 3 3
      include/igl/collapse_edge.cpp
  20. 0 4
      include/igl/comb_frame_field.cpp
  21. 6 1
      include/igl/copyleft/cgal/delaunay_triangulation.cpp
  22. 1 1
      include/igl/copyleft/cgal/delaunay_triangulation.h
  23. 1 1
      include/igl/copyleft/cgal/hausdorff.cpp
  24. 6 0
      include/igl/copyleft/cgal/incircle.cpp
  25. 6 0
      include/igl/copyleft/cgal/orient2D.cpp
  26. 196 195
      include/igl/copyleft/comiso/miq.cpp
  27. 64 40
      include/igl/copyleft/comiso/miq.h
  28. 37 61
      include/igl/copyleft/comiso/nrosy.cpp
  29. 2 2
      include/igl/copyleft/progressive_hulls_cost_and_placement.cpp
  30. 40 3
      include/igl/cotmatrix_entries.cpp
  31. 12 0
      include/igl/cotmatrix_entries.h
  32. 67 0
      include/igl/cotmatrix_intrinsic.cpp
  33. 40 0
      include/igl/cotmatrix_intrinsic.h
  34. 132 0
      include/igl/cross_field_mismatch.cpp
  35. 43 0
      include/igl/cross_field_mismatch.h
  36. 0 142
      include/igl/cross_field_missmatch.cpp
  37. 76 0
      include/igl/cumprod.cpp
  38. 44 0
      include/igl/cumprod.h
  39. 4 0
      include/igl/cumsum.cpp
  40. 13 33
      include/igl/delaunay_triangulation.cpp
  41. 3 3
      include/igl/delaunay_triangulation.h
  42. 9 5
      include/igl/dihedral_angles.cpp
  43. 4 4
      include/igl/dihedral_angles.h
  44. 3 4
      include/igl/doublearea.cpp
  45. 1 1
      include/igl/edge_collapse_is_valid.cpp
  46. 96 0
      include/igl/edge_exists_near.cpp
  47. 47 0
      include/igl/edge_exists_near.h
  48. 9 9
      include/igl/edge_flaps.cpp
  49. 7 5
      include/igl/edge_flaps.h
  50. 2 0
      include/igl/edge_lengths.cpp
  51. 104 72
      include/igl/embree/EmbreeIntersector.h
  52. 7 8
      include/igl/find_cross_field_singularities.cpp
  53. 3 3
      include/igl/find_cross_field_singularities.h
  54. 16 1
      include/igl/flip_edge.cpp
  55. 56 67
      include/igl/grad.cpp
  56. 8 7
      include/igl/grad.h
  57. 69 0
      include/igl/grad_intrinsic.cpp
  58. 35 0
      include/igl/grad_intrinsic.h
  59. 22 12
      include/igl/grid.cpp
  60. 3 2
      include/igl/grid.h
  61. 159 0
      include/igl/heat_geodesics.cpp
  62. 69 0
      include/igl/heat_geodesics.h
  63. 54 0
      include/igl/intrinsic_delaunay_cotmatrix.cpp
  64. 51 0
      include/igl/intrinsic_delaunay_cotmatrix.h
  65. 199 0
      include/igl/intrinsic_delaunay_triangulation.cpp
  66. 79 0
      include/igl/intrinsic_delaunay_triangulation.h
  67. 14 7
      include/igl/is_border_vertex.cpp
  68. 7 4
      include/igl/is_border_vertex.h
  69. 105 0
      include/igl/is_delaunay.cpp
  70. 64 0
      include/igl/is_delaunay.h
  71. 147 0
      include/igl/is_intrinsic_delaunay.cpp
  72. 69 0
      include/igl/is_intrinsic_delaunay.h
  73. 3 3
      include/igl/lexicographic_triangulation.cpp
  74. 1 1
      include/igl/lexicographic_triangulation.h
  75. 14 14
      include/igl/line_field_mismatch.cpp
  76. 11 12
      include/igl/line_field_mismatch.h
  77. 0 42
      include/igl/line_field_missmatch.h
  78. 9 81
      include/igl/massmatrix.cpp
  79. 2 3
      include/igl/massmatrix.h
  80. 128 0
      include/igl/massmatrix_intrinsic.cpp
  81. 56 0
      include/igl/massmatrix_intrinsic.h
  82. 7 0
      include/igl/matlab_format.cpp
  83. 2 1
      include/igl/min_quad_with_fixed.cpp
  84. 1 1
      include/igl/next_filename.h
  85. 10 2
      include/igl/opengl/ViewerData.h
  86. 5 4
      include/igl/oriented_facets.h
  87. 3 0
      include/igl/per_face_normals.cpp
  88. 1 1
      include/igl/principal_curvature.cpp
  89. 3 3
      include/igl/project.cpp
  90. 1 1
      include/igl/project.h
  91. 1 0
      include/igl/remove_unreferenced.cpp
  92. 1 1
      include/igl/rotate_vectors.h
  93. 1 1
      include/igl/scaf.cpp
  94. 38 38
      include/igl/segment_segment_intersect.cpp
  95. 1 1
      include/igl/simplify_polyhedron.cpp
  96. 4 0
      include/igl/slice.cpp
  97. 2 0
      include/igl/sort.cpp
  98. 2 0
      include/igl/squared_edge_lengths.cpp
  99. 37 0
      include/igl/tan_half_angle.cpp
  100. 35 0
      include/igl/tan_half_angle.h

+ 12 - 5
.appveyor.yml

@@ -1,16 +1,20 @@
 version: 1.0.{build}
 os: Visual Studio 2017
-test: off
+platform: x64
 clone_folder: C:\projects\libigl
+shallow_clone: true
 branches:
   only:
     - master
     - dev
 environment:
-  BOOST_ROOT: C:/Libraries/boost_1_65_1
+  matrix:
+  - config: Debug
+    BOOST_ROOT: C:/Libraries/boost_1_65_1
 install:
-  - git submodule update --init --recursive
   - cinstall: python
+build:
+  parallel: true
 build_script:
   - cd c:\projects\libigl
   # External libraries (boost)
@@ -32,7 +36,10 @@ build_script:
   # Tutorials and tests
   - mkdir build
   - cd build
-  - cmake -DLIBIGL_BUILD_TESTS=OFF -DLIBIGL_BUILD_TUTORIALS=ON -DLIBIGL_BUILD_PYTHON=OFF -G "Visual Studio 15 2017 Win64" ../
+  - cmake -DCMAKE_BUILD_TYPE=%config% -DLIBIGL_WITH_COMISO=OFF -DLIBIGL_BUILD_PYTHON=OFF -G "Visual Studio 15 2017 Win64" ../
   - set MSBuildLogger="C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
-  - set MSBuildOptions=/v:m /p:Configuration=Debug /logger:%MSBuildLogger%
+  - set MSBuildOptions=/v:m /p:Configuration=%config% /logger:%MSBuildLogger%
   - msbuild %MSBuildOptions% libigl.sln
+
+test_script:
+  - ctest -C %config% --verbose --output-on-failure -j 2

+ 1 - 1
.travis.yml

@@ -60,7 +60,7 @@ script:
 # Tutorials and tests
 - mkdir build
 - cd build
-- cmake -DCMAKE_BUILD_TYPE=$CONFIG -DLIBIGL_BUILD_TESTS=ON -DLIBIGL_BUILD_TUTORIALS=ON ../
+- cmake -DCMAKE_BUILD_TYPE=$CONFIG -DLIBIGL_BUILD_TESTS=ON -DLIBIGL_BUILD_TUTORIALS=ON -DEMBREE_ISA_AVX=OFF -DEMBREE_ISA_AVX2=OFF -DEMBREE_ISA_AVX512SKX=OFF ../
 - make -j 2
 - ctest --verbose
 - ccache --show-stats

+ 4 - 0
CMakeLists.txt

@@ -40,6 +40,9 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
 ### conditionally compile certain modules depending on libraries found on the system
 list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake)
 
+### Set compiler flags for building the tests on Windows with Visual Studio
+include(LibiglWindows)
+
 ### Adding libIGL: choose the path to your local copy libIGL
 include(libigl)
 
@@ -48,6 +51,7 @@ if(LIBIGL_BUILD_TUTORIALS)
 endif()
 
 if(LIBIGL_BUILD_TESTS)
+	include(CTest)
 	enable_testing()
 	add_subdirectory(tests)
 endif()

+ 1 - 0
cmake/DownloadProject.CMakeLists.cmake.in

@@ -14,4 +14,5 @@ ExternalProject_Add(${DL_ARGS_PROJ}-download
                     BUILD_COMMAND       ""
                     INSTALL_COMMAND     ""
                     TEST_COMMAND        ""
+                    TLS_VERIFY          OFF
 )

+ 15 - 15
cmake/LibiglDownloadExternal.cmake

@@ -35,7 +35,7 @@ endfunction()
 function(igl_download_comiso)
 	igl_download_project(CoMISo
 		GIT_REPOSITORY https://github.com/libigl/CoMISo.git
-		GIT_TAG        fea3ee0ba7d42ee3eca202d484e4fad855e4d6aa
+		GIT_TAG        1f9618cf9b7bd77370d817976470d59091928606
 	)
 endfunction()
 
@@ -58,8 +58,8 @@ endfunction()
 ## Embree
 function(igl_download_embree)
 	igl_download_project(embree
-		URL            https://github.com/embree/embree/archive/v2.17.4.tar.gz
-		URL_MD5        2038f3216b1d626e87453aee72c470e5
+		URL            https://github.com/embree/embree/archive/v3.2.3.tar.gz
+		URL_MD5        1868cda1c97d83d7a0b67b0b64b18cef
 		# GIT_REPOSITORY https://github.com/embree/embree.git
 		# GIT_TAG        cb61322db3bb7082caed21913ad14869b436fe78
 	)
@@ -69,7 +69,7 @@ endfunction()
 function(igl_download_glad)
 	igl_download_project(glad
 		GIT_REPOSITORY https://github.com/libigl/libigl-glad.git
-		GIT_TAG        71e35fe685a0cc160068a2f2f971c40b82d14af0
+		GIT_TAG        09b4969c56779f7ddf8e6176ec1873184aec890f
 	)
 endfunction()
 
@@ -77,7 +77,7 @@ endfunction()
 function(igl_download_glfw)
 	igl_download_project(glfw
 		GIT_REPOSITORY https://github.com/glfw/glfw.git
-		GIT_TAG        58cc4b2c5c2c9a245e09451437dd6f5af4d60c84
+		GIT_TAG        53c8c72c676ca97c10aedfe3d0eb4271c5b23dba
 	)
 endfunction()
 
@@ -105,15 +105,15 @@ endfunction()
 function(igl_download_stb)
 	igl_download_project(stb
 		GIT_REPOSITORY https://github.com/libigl/libigl-stb.git
-		GIT_TAG        e671ceb3def5e7029a23de14c55dc16301ad4dab
+		GIT_TAG        edfa26e389060c21b9dd7812a0b19c00208b7224
 	)
 endfunction()
 
 ## TetGen
 function(igl_download_tetgen)
 	igl_download_project(tetgen
-		GIT_REPOSITORY https://github.com/libigl/tetgen.git
-		GIT_TAG        d2dcc33cb8551f16e302c8130ce12fa52992cd09
+		GIT_REPOSITORY https://github.com/jdumas/tetgen.git
+		GIT_TAG        63b4bdc5b947f9db75f01e0da36af54074ace5c9
 	)
 endfunction()
 
@@ -128,16 +128,16 @@ endfunction()
 ## Triangle
 function(igl_download_triangle)
 	igl_download_project(triangle
-		GIT_REPOSITORY https://github.com/libigl/triangle.git
-		GIT_TAG        d6761dd691e2e1318c83bf7773fea88d9437464a
+		GIT_REPOSITORY https://github.com/jdumas/triangle.git
+		GIT_TAG        2cd0672ff1f67f9f6bb8e556e84901293e637b76
 	)
 endfunction()
 
-## Google test
-function(igl_download_googletest)
-	igl_download_project(googletest
-		GIT_REPOSITORY https://github.com/google/googletest
-		GIT_TAG        release-1.8.1
+## Catch2
+function(igl_download_catch2)
+	igl_download_project(catch2
+		GIT_REPOSITORY https://github.com/catchorg/Catch2.git
+		GIT_TAG        03d122a35c3f5c398c43095a87bc82ed44642516
 	)
 endfunction()
 

+ 22 - 0
cmake/LibiglWindows.cmake

@@ -0,0 +1,22 @@
+if(MSVC)
+	if("${MSVC_RUNTIME}" STREQUAL "")
+		set(MSVC_RUNTIME "static")
+	endif()
+	if(${MSVC_RUNTIME} STREQUAL "static")
+		message(STATUS "MSVC -> forcing use of statically-linked runtime.")
+		foreach(config ${CMAKE_CONFIGURATION_TYPES})
+			string(TOUPPER ${config} config)
+			string(REPLACE /MD /MT CMAKE_C_FLAGS_${config} "${CMAKE_C_FLAGS_${config}}")
+			string(REPLACE /MD /MT CMAKE_CXX_FLAGS_${config} "${CMAKE_CXX_FLAGS_${config}}")
+		endforeach()
+		string(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
+	else()
+		message(STATUS "MSVC -> forcing use of dynamically-linked runtime.")
+		foreach(config ${CMAKE_CONFIGURATION_TYPES})
+			string(TOUPPER ${config} config)
+			string(REPLACE /MT /MD CMAKE_C_FLAGS_${config} "${CMAKE_C_FLAGS_${config}}")
+			string(REPLACE /MT /MD CMAKE_CXX_FLAGS_${config} "${CMAKE_CXX_FLAGS_${config}}")
+		endforeach()
+		string(REPLACE "/MTd" "/MDd" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
+	endif()
+endif()

+ 9 - 27
cmake/libigl.cmake

@@ -83,15 +83,8 @@ if(MSVC)
   endif()
 endif()
 
-if(BUILD_SHARED_LIBS)
-  # Generate position independent code
-  set_target_properties(igl_common PROPERTIES INTERFACE_POSITION_INDEPENDENT_CODE ON)
-endif()
-
-if(UNIX)
-  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
-  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
-endif()
+# Generate position independent code
+set_target_properties(igl_common PROPERTIES INTERFACE_POSITION_INDEPENDENT_CODE ON)
 
 # Eigen
 if(TARGET Eigen3::Eigen)
@@ -265,39 +258,28 @@ endif()
 if(LIBIGL_WITH_EMBREE)
   set(EMBREE_DIR "${LIBIGL_EXTERNAL}/embree")
 
+  set(EMBREE_TESTING_INTENSITY 0 CACHE INT "" FORCE)
   set(EMBREE_ISPC_SUPPORT OFF CACHE BOOL " " FORCE)
   set(EMBREE_TASKING_SYSTEM "INTERNAL" CACHE BOOL " " FORCE)
   set(EMBREE_TUTORIALS OFF CACHE BOOL " " FORCE)
   set(EMBREE_MAX_ISA NONE CACHE STRINGS " " FORCE)
-  set(BUILD_TESTING OFF CACHE BOOL " " FORCE)
-
-  # set(ENABLE_INSTALLER OFF CACHE BOOL " " FORCE)
+  set(EMBREE_STATIC_LIB ON CACHE BOOL " " FORCE)
   if(MSVC)
-    # set(EMBREE_STATIC_RUNTIME OFF CACHE BOOL " " FORCE)
-    set(EMBREE_STATIC_LIB OFF CACHE BOOL " " FORCE)
-  else()
-    set(EMBREE_STATIC_LIB ON CACHE BOOL " " FORCE)
+    set(EMBREE_STATIC_RUNTIME ON CACHE BOOL " " FORCE)
   endif()
 
   if(NOT TARGET embree)
+    # TODO: Should probably save/restore the CMAKE_CXX_FLAGS_*, since embree seems to be
+    # overriding them on Windows. But well... it works for now.
     igl_download_embree()
     add_subdirectory("${EMBREE_DIR}" "embree")
   endif()
 
-  if(MSVC)
-    add_custom_target(Copy-Embree-DLL ALL # Adds a post-build event
-        COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake - E
-        $<TARGET_FILE:embree> # <--this is in-file
-        "${CMAKE_BINARY_DIR}" # <--this is out-file path
-        DEPENDS embree) # Execute after embree target has been built
-  endif()
-
   compile_igl_module("embree")
   target_link_libraries(igl_embree ${IGL_SCOPE} embree)
   target_include_directories(igl_embree ${IGL_SCOPE} ${EMBREE_DIR}/include)
-  if(NOT MSVC)
-    target_compile_definitions(igl_embree ${IGL_SCOPE} -DENABLE_STATIC_LIB)
-  endif()
+  target_compile_definitions(igl_embree ${IGL_SCOPE} -DEMBREE_STATIC_LIB)
+
 endif()
 
 ################################################################################

+ 1 - 0
include/igl/AABB.cpp

@@ -1072,4 +1072,5 @@ template void igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 3>::init<Eigen
 template void igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 2>::init<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
 template double igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 3>::squared_distance<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<double, 1, 3, 1, 1, 3> const&, double, int&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&) const;
 template bool igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 3>::intersect_ray<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<double, 1, 3, 1, 1, 3> const&, Eigen::Matrix<double, 1, 3, 1, 1, 3> const&, igl::Hit&) const;
+template void igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 3>::squared_distance<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 2, 3, 0, 2, 3>, Eigen::Matrix<double, 2, 1, 0, 2, 1>, Eigen::Matrix<int, 2, 1, 0, 2, 1>, Eigen::Matrix<double, 2, 3, 0, 2, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 2, 3, 0, 2, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 2, 1, 0, 2, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, 2, 1, 0, 2, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 2, 3, 0, 2, 3> >&) const;
 #endif

+ 5 - 5
include/igl/adjacency_list.cpp

@@ -12,7 +12,7 @@
 
 template <typename Index, typename IndexVector>
 IGL_INLINE void igl::adjacency_list(
-    const Eigen::PlainObjectBase<Index>  & F,
+    const Eigen::MatrixBase<Index>  & F,
     std::vector<std::vector<IndexVector> >& A,
     bool sorted)
 {
@@ -161,9 +161,9 @@ IGL_INLINE void igl::adjacency_list(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
 // generated by autoexplicit.sh
-template void igl::adjacency_list<Eigen::Matrix<int, -1, 2, 0, -1, 2>, int>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, bool);
+template void igl::adjacency_list<Eigen::Matrix<int, -1, 2, 0, -1, 2>, int>(Eigen::MatrixBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, bool);
 // generated by autoexplicit.sh
-template void igl::adjacency_list<Eigen::Matrix<int, -1, -1, 0, -1, -1>, int>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, bool);
-template void igl::adjacency_list<Eigen::Matrix<int, -1, 3, 0, -1, 3>, int>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, bool);
-template void igl::adjacency_list<class Eigen::Matrix<int, -1, -1, 0, -1, -1>, unsigned int>(class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1> > const &, class std::vector<class std::vector<unsigned int, class std::allocator<unsigned int> >, class std::allocator<class std::vector<unsigned int, class std::allocator<unsigned int> > > > &, bool);
+template void igl::adjacency_list<Eigen::Matrix<int, -1, -1, 0, -1, -1>, int>(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, bool);
+template void igl::adjacency_list<Eigen::Matrix<int, -1, 3, 0, -1, 3>, int>(Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, bool);
+template void igl::adjacency_list<class Eigen::Matrix<int, -1, -1, 0, -1, -1>, unsigned int>(class Eigen::MatrixBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1> > const &, class std::vector<class std::vector<unsigned int, class std::allocator<unsigned int> >, class std::allocator<class std::vector<unsigned int, class std::allocator<unsigned int> > > > &, bool);
 #endif

+ 1 - 1
include/igl/adjacency_list.h

@@ -31,7 +31,7 @@ namespace igl
   // See also: edges, cotmatrix, diag
   template <typename Index, typename IndexVector>
   IGL_INLINE void adjacency_list(
-    const Eigen::PlainObjectBase<Index> & F, 
+    const Eigen::MatrixBase<Index> & F, 
     std::vector<std::vector<IndexVector> >& A,
     bool sorted = false);
 

+ 2 - 0
include/igl/barycenter.cpp

@@ -54,4 +54,6 @@ template void igl::barycenter<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::M
 template void igl::barycenter<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::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
 template void igl::barycenter<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 template void igl::barycenter<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 2, 0, -1, 2> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&);
+template void igl::barycenter<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 2, 3, 0, 2, 3>, Eigen::Matrix<double, 2, 3, 0, 2, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 2, 3, 0, 2, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 2, 3, 0, 2, 3> >&);
+template void igl::barycenter<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, 2, 3, 0, 2, 3>, Eigen::Matrix<double, 2, 3, 0, 2, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, 2, 3, 0, 2, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 2, 3, 0, 2, 3> >&);
 #endif

+ 5 - 0
include/igl/bbw.cpp

@@ -118,7 +118,12 @@ IGL_INLINE bool igl::bbw(
     }
     W.col(i) = Wi;
   };
+#ifdef WIN32
+  for (int i = 0; i < m; ++i)
+    optimize_weight(i);
+#else
   parallel_for(m,optimize_weight,2);
+#endif
   if(error)
   {
     return false;

+ 8 - 8
include/igl/boundary_facets.cpp

@@ -103,7 +103,7 @@ IGL_INLINE void igl::boundary_facets(
 
 template <typename DerivedT, typename DerivedF>
 IGL_INLINE void igl::boundary_facets(
-  const Eigen::PlainObjectBase<DerivedT>& T,
+  const Eigen::MatrixBase<DerivedT>& T,
   Eigen::PlainObjectBase<DerivedF>& F)
 {
   assert(T.cols() == 0 || T.cols() == 4 || T.cols() == 3);
@@ -119,7 +119,7 @@ IGL_INLINE void igl::boundary_facets(
 
 template <typename DerivedT, typename Ret>
 Ret igl::boundary_facets(
-  const Eigen::PlainObjectBase<DerivedT>& T)
+  const Eigen::MatrixBase<DerivedT>& T)
 {
   Ret F;
   igl::boundary_facets(T,F);
@@ -130,12 +130,12 @@ Ret igl::boundary_facets(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
 // generated by autoexplicit.sh
-template void igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >&);
+template void igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >&);
 // generated by autoexplicit.sh
-template void igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
-template void igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template void igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
+template void igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::boundary_facets<int, int>(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&);
-//template Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > igl::boundary_facets(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
-template Eigen::Matrix<int, -1, -1, 0, -1, -1> igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
-template void igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
+//template Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > igl::boundary_facets(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
+template Eigen::Matrix<int, -1, -1, 0, -1, -1> igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
+template void igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
 #endif

+ 2 - 2
include/igl/boundary_facets.h

@@ -37,12 +37,12 @@ namespace igl
   //   DerivedF  integer-value: i.e. from MatrixXi
   template <typename DerivedT, typename DerivedF>
   IGL_INLINE void boundary_facets(
-    const Eigen::PlainObjectBase<DerivedT>& T,
+    const Eigen::MatrixBase<DerivedT>& T,
     Eigen::PlainObjectBase<DerivedF>& F);
   // Same as above but returns F
   template <typename DerivedT, typename Ret>
   Ret boundary_facets(
-    const Eigen::PlainObjectBase<DerivedT>& T);
+    const Eigen::MatrixBase<DerivedT>& T);
 }
 
 #ifndef IGL_STATIC_LIBRARY

+ 4 - 4
include/igl/boundary_loop.cpp

@@ -14,7 +14,7 @@
 
 template <typename DerivedF, typename Index>
 IGL_INLINE void igl::boundary_loop(
-    const Eigen::PlainObjectBase<DerivedF> & F,
+    const Eigen::MatrixBase<DerivedF> & F,
     std::vector<std::vector<Index> >& L)
 {
   using namespace std;
@@ -91,7 +91,7 @@ IGL_INLINE void igl::boundary_loop(
 
 template <typename DerivedF, typename Index>
 IGL_INLINE void igl::boundary_loop(
-  const Eigen::PlainObjectBase<DerivedF>& F,
+  const Eigen::MatrixBase<DerivedF>& F,
   std::vector<Index>& L)
 {
   using namespace Eigen;
@@ -130,7 +130,7 @@ IGL_INLINE void igl::boundary_loop(
 
 template <typename DerivedF, typename DerivedL>
 IGL_INLINE void igl::boundary_loop(
-  const Eigen::PlainObjectBase<DerivedF>& F,
+  const Eigen::MatrixBase<DerivedF>& F,
   Eigen::PlainObjectBase<DerivedL>& L)
 {
   using namespace Eigen;
@@ -149,5 +149,5 @@ IGL_INLINE void igl::boundary_loop(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
-template void igl::boundary_loop<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+template void igl::boundary_loop<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 #endif

+ 3 - 3
include/igl/boundary_loop.h

@@ -25,7 +25,7 @@ namespace igl
   //
   template <typename DerivedF, typename Index>
   IGL_INLINE void boundary_loop(
-    const Eigen::PlainObjectBase<DerivedF>& F, 
+    const Eigen::MatrixBase<DerivedF>& F, 
     std::vector<std::vector<Index> >& L);
 
 
@@ -41,7 +41,7 @@ namespace igl
   //
   template <typename DerivedF, typename Index>
   IGL_INLINE void boundary_loop(
-    const Eigen::PlainObjectBase<DerivedF>& F, 
+    const Eigen::MatrixBase<DerivedF>& F, 
     std::vector<Index>& L);
 
   // Compute ordered boundary loops for a manifold mesh and return the 
@@ -56,7 +56,7 @@ namespace igl
   //
   template <typename DerivedF, typename DerivedL>
   IGL_INLINE void boundary_loop(
-    const Eigen::PlainObjectBase<DerivedF>& F, 
+    const Eigen::MatrixBase<DerivedF>& F, 
     Eigen::PlainObjectBase<DerivedL>& L);
 }
 

+ 4 - 6
include/igl/circulation.cpp

@@ -7,12 +7,11 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "circulation.h"
 #include "list_to_matrix.h"
+#include <cassert>
 
 IGL_INLINE std::vector<int> igl::circulation(
   const int e,
   const bool ccw,
-  const Eigen::MatrixXi & F,
-  const Eigen::MatrixXi & E,
   const Eigen::VectorXi & EMAP,
   const Eigen::MatrixXi & EF,
   const Eigen::MatrixXi & EI)
@@ -20,7 +19,8 @@ IGL_INLINE std::vector<int> igl::circulation(
   // prepare output
   std::vector<int> N;
   N.reserve(6);
-  const int m = F.rows();
+  const int m = EMAP.size()/3;
+  assert(m*3 == EMAP.size());
   const auto & step = [&](
     const int e, 
     const int ff,
@@ -59,13 +59,11 @@ IGL_INLINE std::vector<int> igl::circulation(
 IGL_INLINE void igl::circulation(
   const int e,
   const bool ccw,
-  const Eigen::MatrixXi & F,
-  const Eigen::MatrixXi & E,
   const Eigen::VectorXi & EMAP,
   const Eigen::MatrixXi & EF,
   const Eigen::MatrixXi & EI,
   Eigen::VectorXi & vN)
 {
-  std::vector<int> N = circulation(e,ccw,F,E,EMAP,EF,EI);
+  std::vector<int> N = circulation(e,ccw,EMAP,EF,EI);
   igl::list_to_matrix(N,vN);
 }

+ 1 - 6
include/igl/circulation.h

@@ -20,8 +20,6 @@ namespace igl
   //   e  index into E of edge to circulate
   //   ccw  whether to _continue_ in ccw direction of edge (circulate around
   //     E(e,1))
-  //   F  #F by 3 list of face indices
-  //   E  #E by 2 list of edge indices
   //   EMAP #F*3 list of indices into E, mapping each directed edge to unique
   //     unique edge in E
   //   EF  #E by 2 list of edge flaps, EF(e,0)=f means e=(i-->j) is the edge of
@@ -30,11 +28,10 @@ namespace igl
   //   EI  #E by 2 list of edge flap corners (see above).
   // Returns list of faces touched by circulation (in cyclically order).
   //   
+  // See also: edge_flaps
   IGL_INLINE std::vector<int> circulation(
     const int e,
     const bool ccw,
-    const Eigen::MatrixXi & F,
-    const Eigen::MatrixXi & E,
     const Eigen::VectorXi & EMAP,
     const Eigen::MatrixXi & EF,
     const Eigen::MatrixXi & EI);
@@ -42,8 +39,6 @@ namespace igl
   IGL_INLINE void circulation(
     const int e,
     const bool ccw,
-    const Eigen::MatrixXi & F,
-    const Eigen::MatrixXi & E,
     const Eigen::VectorXi & EMAP,
     const Eigen::MatrixXi & EF,
     const Eigen::MatrixXi & EI,

+ 3 - 3
include/igl/collapse_edge.cpp

@@ -40,7 +40,7 @@ IGL_INLINE bool igl::collapse_edge(
   }
 
   // Important to grab neighbors of d before monkeying with edges
-  const std::vector<int> nV2Fd = circulation(e,!eflip,F,E,EMAP,EF,EI);
+  const std::vector<int> nV2Fd = circulation(e,!eflip,EMAP,EF,EI);
 
   // The following implementation strongly relies on s<d
   assert(s<d && "s should be less than d");
@@ -339,8 +339,8 @@ IGL_INLINE bool igl::collapse_edge(
   Q.erase(Q.begin());
   e = p.second;
   Qit[e] = Q.end();
-  std::vector<int> N  = circulation(e, true,F,E,EMAP,EF,EI);
-  std::vector<int> Nd = circulation(e,false,F,E,EMAP,EF,EI);
+  std::vector<int> N  = circulation(e, true,EMAP,EF,EI);
+  std::vector<int> Nd = circulation(e,false,EMAP,EF,EI);
   N.insert(N.begin(),Nd.begin(),Nd.end());
   bool collapsed = true;
   if(pre_collapse(V,F,E,EMAP,EF,EI,Q,Qit,C,e))

+ 0 - 4
include/igl/comb_frame_field.cpp

@@ -69,10 +69,6 @@ IGL_INLINE void igl::comb_frame_field(const Eigen::PlainObjectBase<DerivedV> &V,
     PD2_combed.row(i) = DIRs.row(M);
 
   }
-
-
-  //    PD1_combed = BIS1_combed;
-  //    PD2_combed = BIS2_combed;
 }
 
 #ifdef IGL_STATIC_LIBRARY

+ 6 - 1
include/igl/copyleft/cgal/delaunay_triangulation.cpp

@@ -16,7 +16,7 @@ template<
   typename DerivedV,
   typename DerivedF>
 IGL_INLINE void igl::copyleft::cgal::delaunay_triangulation(
-    const Eigen::PlainObjectBase<DerivedV>& V,
+    const Eigen::MatrixBase<DerivedV>& V,
     Eigen::PlainObjectBase<DerivedF>& F)
 {
   typedef typename DerivedV::Scalar Scalar;
@@ -60,3 +60,8 @@ IGL_INLINE void igl::copyleft::cgal::delaunay_triangulation(
 //  };
 }
 
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template instantiation
+// generated by autoexplicit.sh
+template void igl::copyleft::cgal::delaunay_triangulation<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+#endif

+ 1 - 1
include/igl/copyleft/cgal/delaunay_triangulation.h

@@ -32,7 +32,7 @@ namespace igl
         typename DerivedF
         >
       IGL_INLINE void delaunay_triangulation(
-          const Eigen::PlainObjectBase<DerivedV>& V,
+          const Eigen::MatrixBase<DerivedV>& V,
           Eigen::PlainObjectBase<DerivedF>& F);
     }
   }

+ 1 - 1
include/igl/copyleft/cgal/hausdorff.cpp

@@ -41,4 +41,4 @@ IGL_INLINE void igl::copyleft::cgal::hausdorff(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
 template void igl::copyleft::cgal::hausdorff<Eigen::Matrix<double, -1, -1, 0, -1, -1>, CGAL::Simple_cartesian<double>, double>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, CGAL::AABB_tree<CGAL::AABB_traits<CGAL::Simple_cartesian<double>, CGAL::AABB_triangle_primitive<CGAL::Simple_cartesian<double>, std::vector<CGAL::Triangle_3<CGAL::Simple_cartesian<double> >, std::allocator<CGAL::Triangle_3<CGAL::Simple_cartesian<double> > > >::iterator, CGAL::Boolean_tag<false> >, CGAL::Default> > const&, std::vector<CGAL::Triangle_3<CGAL::Simple_cartesian<double> >, std::allocator<CGAL::Triangle_3<CGAL::Simple_cartesian<double> > > > const&, double&, double&);
-#endif
+#endif

+ 6 - 0
include/igl/copyleft/cgal/incircle.cpp

@@ -37,3 +37,9 @@ IGL_INLINE short igl::copyleft::cgal::incircle(
       throw "Invalid incircle result";
   }
 }
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template instantiation
+// generated by autoexplicit.sh
+template short igl::copyleft::cgal::incircle<double>(double const*, double const*, double const*, double const*);
+#endif

+ 6 - 0
include/igl/copyleft/cgal/orient2D.cpp

@@ -35,3 +35,9 @@ IGL_INLINE short igl::copyleft::cgal::orient2D(
       throw "Invalid orientation";
   }
 }
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template instantiation
+// generated by autoexplicit.sh
+template short igl::copyleft::cgal::orient2D<double>(double const*, double const*, double const*);
+#endif

+ 196 - 195
include/igl/copyleft/comiso/miq.cpp

@@ -28,7 +28,7 @@
 #include <CoMISo/Solver/GMM_Tools.hh>
 
 //
-#include "../../cross_field_missmatch.h"
+#include "igl/cross_field_mismatch.h"
 #include "../../comb_frame_field.h"
 #include "../../comb_cross_field.h"
 #include "../../cut_mesh_from_singularities.h"
@@ -69,7 +69,7 @@ namespace comiso {
     ///num of integer for cuts
     int num_integer_cuts;
     ///this are used for drawing purposes
-    std::vector<SeamInfo> EdgeSeamInfo;
+    std::vector<SeamInfo> edgeSeamInfo;
   };
 
 
@@ -85,13 +85,13 @@ namespace comiso {
     const Eigen::PlainObjectBase<DerivedF> &TT;
     const Eigen::PlainObjectBase<DerivedF> &TTi;
 
-    const Eigen::Matrix<int, Eigen::Dynamic, 3> &Handle_MMatch;
-    const Eigen::Matrix<int, Eigen::Dynamic, 1> &Handle_Singular; // bool
-    const Eigen::Matrix<int, Eigen::Dynamic, 3> &Handle_Seams; // 3 bool
+    const Eigen::Matrix<int, Eigen::Dynamic, 3> &mismatch;
+    const Eigen::Matrix<int, Eigen::Dynamic, 1> &singular; // bool
+    const Eigen::Matrix<int, Eigen::Dynamic, 3> &seams; // 3 bool
 
 
     ///this handle for mesh TODO: move with the other global variables
-    MeshSystemInfo Handle_SystemInfo;
+    MeshSystemInfo systemInfo;
 
     IGL_INLINE VertexIndexing(const Eigen::PlainObjectBase<DerivedV> &_V,
                               const Eigen::PlainObjectBase<DerivedF> &_F,
@@ -99,13 +99,13 @@ namespace comiso {
                               const Eigen::PlainObjectBase<DerivedF> &_Fcut,
                               const Eigen::PlainObjectBase<DerivedF> &_TT,
                               const Eigen::PlainObjectBase<DerivedF> &_TTi,
-                              const Eigen::Matrix<int, Eigen::Dynamic, 3> &_Handle_MMatch,
-                              const Eigen::Matrix<int, Eigen::Dynamic, 1> &_Handle_Singular,
-                              const Eigen::Matrix<int, Eigen::Dynamic, 3> &_Handle_Seams
+                              const Eigen::Matrix<int, Eigen::Dynamic, 3> &_mismatch,
+                              const Eigen::Matrix<int, Eigen::Dynamic, 1> &_singular,
+                              const Eigen::Matrix<int, Eigen::Dynamic, 3> &_seams
                               );
 
     // provide information about every vertex per seam
-    IGL_INLINE void InitSeamInfo();
+    IGL_INLINE void initSeamInfo();
 
 
   private:
@@ -120,14 +120,14 @@ namespace comiso {
       }
     };
 
-    IGL_INLINE void GetSeamInfo(const int f0,
+    IGL_INLINE void getSeamInfo(const int f0,
                                 const int f1,
                                 const int indexE,
-                                int &v0,int &v1,
-                                int &v0p,int &v1p,
-                                unsigned char &_MMatch);
+                                int &v0, int &v1,
+                                int &v0p, int &v1p,
+                                unsigned char &_mismatch);
 
-    IGL_INLINE std::vector<std::vector<VertexInfo> > GetVerticesPerSeam();
+    IGL_INLINE std::vector<std::vector<VertexInfo> > getVerticesPerSeam();
   };
 
 
@@ -136,13 +136,13 @@ namespace comiso {
   {
 
   public:
-    IGL_INLINE void SolvePoisson(Eigen::VectorXd Stiffness,
-                                 double vector_field_scale=0.1f,
-                                 double grid_res=1.f,
-                                 bool direct_round=true,
-                                 int localIter=0,
-                                 bool _integer_rounding=true,
-                                 bool _singularity_rounding=true,
+    IGL_INLINE void solvePoisson(Eigen::VectorXd Stiffness,
+                                 double gredientSize = 0.1,
+                                 double grid_res = 1.,
+                                 bool direct_round = true,
+                                 int localIter = 0,
+                                 bool _doRound = true,
+                                 bool _singularity_rounding = true,
                                  std::vector<int> roundVertices = std::vector<int>(),
                                  std::vector<std::vector<int> > hardFeatures = std::vector<std::vector<int> >());
 
@@ -166,9 +166,9 @@ namespace comiso {
     const Eigen::PlainObjectBase<DerivedF> &TTi;
     const Eigen::PlainObjectBase<DerivedV> &PD1;
     const Eigen::PlainObjectBase<DerivedV> &PD2;
-    const Eigen::Matrix<int, Eigen::Dynamic, 1> &Handle_Singular; // bool
+    const Eigen::Matrix<int, Eigen::Dynamic, 1> &singular; // bool
 
-    const MeshSystemInfo &Handle_SystemInfo;
+    const MeshSystemInfo &systemInfo;
 
     // Internal:
     Eigen::VectorXd Handle_Stiffness;
@@ -229,62 +229,62 @@ namespace comiso {
 
     ///START COMMON MATH FUNCTIONS
     ///return the complex encoding the rotation
-    ///for a given missmatch interval
-    IGL_INLINE std::complex<double> GetRotationComplex(int interval);
+    ///for a given mismatch interval
+    IGL_INLINE std::complex<double> getRotationComplex(int interval);
     ///END COMMON MATH FUNCTIONS
 
     ///START FIXING VERTICES
     ///set a given vertex as fixed
-    IGL_INLINE void AddFixedVertex(int v);
+    IGL_INLINE void addFixedVertex(int v);
 
     ///find vertex to fix in case we're using
     ///a vector field NB: multiple components not handled
-    IGL_INLINE void FindFixedVertField();
+    IGL_INLINE void findFixedVertField();
 
     ///find hard constraint depending if using or not
     ///a vector field
-    IGL_INLINE void FindFixedVert();
+    IGL_INLINE void findFixedVert();
 
-    IGL_INLINE int GetFirstVertexIndex(int v);
+    IGL_INLINE int getFirstVertexIndex(int v);
 
     ///fix the vertices which are flagged as fixed
-    IGL_INLINE void FixBlockedVertex();
+    IGL_INLINE void fixBlockedVertex();
     ///END FIXING VERTICES
 
     ///HANDLING SINGULARITY
     //set the singularity round to integer location
-    IGL_INLINE void AddSingularityRound();
+    IGL_INLINE void addSingularityRound();
 
-    IGL_INLINE void AddToRoundVertices(std::vector<int> ids);
+    IGL_INLINE void addToRoundVertices(std::vector<int> ids);
 
     ///START GENERIC SYSTEM FUNCTIONS
-    //build the laplacian matrix cyclyng over all rangemaps
+    //build the Laplacian matrix cycling over all range maps
     //and over all faces
-    IGL_INLINE void BuildLaplacianMatrix(double vfscale=1);
+    IGL_INLINE void buildLaplacianMatrix(double vfscale = 1);
 
     ///find different sized of the system
-    IGL_INLINE void FindSizes();
+    IGL_INLINE void findSizes();
 
-    IGL_INLINE void AllocateSystem();
+    IGL_INLINE void allocateSystem();
 
     ///intitialize the whole matrix
-    IGL_INLINE void InitMatrix();
+    IGL_INLINE void initMatrix();
 
     ///map back coordinates after that
     ///the system has been solved
-    IGL_INLINE void MapCoords();
+    IGL_INLINE void mapCoords();
     ///END GENERIC SYSTEM FUNCTIONS
 
     ///set the constraints for the inter-range cuts
-    IGL_INLINE void BuildSeamConstraintsExplicitTranslation();
+    IGL_INLINE void buildSeamConstraintsExplicitTranslation();
 
     ///set the constraints for the inter-range cuts
-    IGL_INLINE void BuildUserDefinedConstraints();
+    IGL_INLINE void buildUserDefinedConstraints();
 
     ///call of the mixed integer solver
-    IGL_INLINE void MixedIntegerSolve(double cone_grid_res=1,
-                                      bool direct_round=true,
-                                      int localIter=0);
+    IGL_INLINE void mixedIntegerSolve(double cone_grid_res = 1,
+                                      bool direct_round = true,
+                                      int localIter = 0);
 
     IGL_INLINE void clearUserConstraint();
 
@@ -327,7 +327,7 @@ namespace comiso {
                          int iter = 5,
                          int localIter = 5,
                          bool DoRound = true,
-                         bool SingularityRound=true,
+                         bool SingularityRound = true,
                          std::vector<int> roundVertices = std::vector<int>(),
                          std::vector<std::vector<int> > hardFeatures = std::vector<std::vector<int> >());
 
@@ -392,25 +392,25 @@ Vcut(_Vcut),
 Fcut(_Fcut),
 TT(_TT),
 TTi(_TTi),
-Handle_MMatch(_Handle_MMatch),
-Handle_Singular(_Handle_Singular),
-Handle_Seams(_Handle_Seams)
+mismatch(_Handle_MMatch),
+singular(_Handle_Singular),
+seams(_Handle_Seams)
 {
   #ifdef DEBUG_PRINT
   cerr<<igl::matlab_format(Handle_Seams,"Handle_Seams");
 #endif
 
-  Handle_SystemInfo.num_vert_variables=Vcut.rows();
-  Handle_SystemInfo.num_integer_cuts=0;
+  systemInfo.num_vert_variables=Vcut.rows();
+  systemInfo.num_integer_cuts=0;
 }
 
 template <typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::copyleft::comiso::VertexIndexing<DerivedV, DerivedF>::GetSeamInfo(const int f0,
-                                                                     const int f1,
-                                                                     const int indexE,
-                                                                     int &v0,int &v1,
-                                                                     int &v0p,int &v1p,
-                                                                     unsigned char &_MMatch)
+IGL_INLINE void igl::copyleft::comiso::VertexIndexing<DerivedV, DerivedF>::getSeamInfo(const int f0,
+                                                                                       const int f1,
+                                                                                       const int indexE,
+                                                                                       int &v0, int &v1,
+                                                                                       int &v0p, int &v1p,
+                                                                                       unsigned char &_mismatch)
 {
   int edgef0 = indexE;
   v0 = Fcut(f0,edgef0);
@@ -421,13 +421,13 @@ IGL_INLINE void igl::copyleft::comiso::VertexIndexing<DerivedV, DerivedF>::GetSe
   v1p = Fcut(f1,edgef1);
   v0p = Fcut(f1,(edgef1+1)%3);
 
-  _MMatch = Handle_MMatch(f0,edgef0);
+  _mismatch = mismatch(f0,edgef0);
   assert(F(f0,edgef0)         == F(f1,((edgef1+1)%3)));
   assert(F(f0,((edgef0+1)%3)) == F(f1,edgef1));
 }
 
 template <typename DerivedV, typename DerivedF>
-IGL_INLINE std::vector<std::vector<typename igl::copyleft::comiso::VertexIndexing<DerivedV, DerivedF>::VertexInfo> > igl::copyleft::comiso::VertexIndexing<DerivedV, DerivedF>::GetVerticesPerSeam()
+IGL_INLINE std::vector<std::vector<typename igl::copyleft::comiso::VertexIndexing<DerivedV, DerivedF>::VertexInfo> > igl::copyleft::comiso::VertexIndexing<DerivedV, DerivedF>::getVerticesPerSeam()
 {
   // Return value
   std::vector<std::vector<VertexInfo> >verticesPerSeam;
@@ -444,7 +444,7 @@ IGL_INLINE std::vector<std::vector<typename igl::copyleft::comiso::VertexIndexin
       if(f1 == -1)
         continue;
 
-      bool seam = Handle_Seams(f0,k0);
+      bool seam = seams(f0,k0);
       if (seam && F_hit(f0,k0) == 0)
       {
         int v0 = F(f0, k0);
@@ -465,7 +465,7 @@ IGL_INLINE std::vector<std::vector<typename igl::copyleft::comiso::VertexIndexin
   {
     isStartVertex[i] = false;
     // vertices with two neighbors are regular vertices, unless the vertex is a singularity, in which case it qualifies as a start vertex
-    if (VVSeam[i].size() > 0 && VVSeam[i].size() != 2 || Handle_Singular(i) == true)
+    if (VVSeam[i].size() > 0 && VVSeam[i].size() != 2 || singular(i) == true)
     {
       startVertexIndices.push_back(i);
       isStartVertex[i] = true;
@@ -527,10 +527,10 @@ IGL_INLINE std::vector<std::vector<typename igl::copyleft::comiso::VertexIndexin
 }
 
 template <typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::copyleft::comiso::VertexIndexing<DerivedV, DerivedF>::InitSeamInfo()
+IGL_INLINE void igl::copyleft::comiso::VertexIndexing<DerivedV, DerivedF>::initSeamInfo()
 {
-  auto verticesPerSeam = GetVerticesPerSeam();
-  Handle_SystemInfo.EdgeSeamInfo.clear();
+  auto verticesPerSeam = getVerticesPerSeam();
+  systemInfo.edgeSeamInfo.clear();
   int integerVar = 0;
   // Loop over each seam
   for(auto seam : verticesPerSeam){
@@ -569,44 +569,44 @@ IGL_INLINE void igl::copyleft::comiso::VertexIndexing<DerivedV, DerivedF>::InitS
 
       int vtx0,vtx0p,vtx1,vtx1p;
       unsigned char MM;
-      GetSeamInfo(f,ff,k,vtx0,vtx1,vtx0p,vtx1p,MM);
-      Handle_SystemInfo.EdgeSeamInfo.push_back(SeamInfo(vtx0,vtx0p,MM,integerVar));
+      getSeamInfo(f, ff, k, vtx0, vtx1, vtx0p, vtx1p, MM);
+      systemInfo.edgeSeamInfo.push_back(SeamInfo(vtx0,vtx0p,MM,integerVar));
       if(it == seam.end() -1){
-        Handle_SystemInfo.EdgeSeamInfo.push_back(SeamInfo(vtx1,vtx1p,MM,integerVar));
+        systemInfo.edgeSeamInfo.push_back(SeamInfo(vtx1,vtx1p,MM,integerVar));
       }
       priorVertexIdx = vtx1;
     }
     // use the same integer for each seam
     integerVar++;
   }
-  Handle_SystemInfo.num_integer_cuts = integerVar;
+  systemInfo.num_integer_cuts = integerVar;
 
 #ifndef NDEBUG
   int totalNVerticesOnSeams = 0;
   for(auto seam : verticesPerSeam){
     totalNVerticesOnSeams += seam.size();
   }
-  assert(Handle_SystemInfo.EdgeSeamInfo.size() == totalNVerticesOnSeams);
+  assert(systemInfo.edgeSeamInfo.size() == totalNVerticesOnSeams);
 #endif
 }
 
 
 
 template <typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::SolvePoisson(Eigen::VectorXd Stiffness,
-                                                                     double vector_field_scale,
-                                                                     double grid_res,
-                                                                     bool direct_round,
+IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::solvePoisson(Eigen::VectorXd Stiffness,
+                                                                     double gradientSize,
+                                                                     double gridResolution,
+                                                                     bool directRound,
                                                                      int localIter,
-                                                                     bool _integer_rounding,
-                                                                     bool _singularity_rounding,
+                                                                     bool doRound,
+                                                                     bool singularityRound,
                                                                      std::vector<int> roundVertices,
                                                                      std::vector<std::vector<int> > hardFeatures)
 {
   Handle_Stiffness = Stiffness;
 
   //initialization of flags and data structures
-  integer_rounding=_integer_rounding;
+  integer_rounding=doRound;
 
   ids_to_round.clear();
 
@@ -618,48 +618,47 @@ IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::SolveP
   }
 
   ///Initializing Matrix
-
-  int t0=clock();
+  clock_t t0 = clock();
 
   ///initialize the matrix ALLOCATING SPACE
-  InitMatrix();
+  initMatrix();
   if (DEBUGPRINT)
     printf("\n ALLOCATED THE MATRIX \n");
 
-  ///build the laplacian system
-  BuildLaplacianMatrix(vector_field_scale);
+  ///build the Laplacian system
+  buildLaplacianMatrix(gradientSize);
 
   // add seam constraints
-  BuildSeamConstraintsExplicitTranslation();
+  buildSeamConstraintsExplicitTranslation();
 
   // add user defined constraints
-  BuildUserDefinedConstraints();
+  buildUserDefinedConstraints();
 
-  ////add the lagrange multiplier
-  FixBlockedVertex();
+  ////add the Lagrange multiplier
+  fixBlockedVertex();
 
   if (DEBUGPRINT)
     printf("\n BUILT THE MATRIX \n");
 
   if (integer_rounding)
-    AddToRoundVertices(roundVertices);
+    addToRoundVertices(roundVertices);
 
-  if (_singularity_rounding)
-    AddSingularityRound();
+  if (singularityRound)
+    addSingularityRound();
 
-  int t1=clock();
+  clock_t t1 = clock();
   if (DEBUGPRINT) printf("\n time:%d \n",t1-t0);
   if (DEBUGPRINT) printf("\n SOLVING \n");
 
-  MixedIntegerSolve(grid_res,direct_round,localIter);
+  mixedIntegerSolve(gridResolution, directRound, localIter);
 
-  int t2=clock();
+  clock_t t2 = clock();
   if (DEBUGPRINT) printf("\n time:%d \n",t2-t1);
   if (DEBUGPRINT) printf("\n ASSIGNING COORDS \n");
 
-  MapCoords();
+  mapCoords();
 
-  int t3=clock();
+  clock_t t3 = clock();
   if (DEBUGPRINT) printf("\n time:%d \n",t3-t2);
   if (DEBUGPRINT) printf("\n FINISHED \n");
 }
@@ -674,8 +673,8 @@ IGL_INLINE igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>
                 const Eigen::PlainObjectBase<DerivedF> &_TTi,
                 const Eigen::PlainObjectBase<DerivedV> &_PD1,
                 const Eigen::PlainObjectBase<DerivedV> &_PD2,
-                const Eigen::Matrix<int, Eigen::Dynamic, 1>&_Handle_Singular,
-                const MeshSystemInfo &_Handle_SystemInfo
+                const Eigen::Matrix<int, Eigen::Dynamic, 1>&_singular,
+                const MeshSystemInfo &_systemInfo
 ):
 V(_V),
 F(_F),
@@ -685,8 +684,8 @@ TT(_TT),
 TTi(_TTi),
 PD1(_PD1),
 PD2(_PD2),
-Handle_Singular(_Handle_Singular),
-Handle_SystemInfo(_Handle_SystemInfo)
+singular(_singular),
+systemInfo(_systemInfo)
 {
   UV        = Eigen::MatrixXd(V.rows(),2);
   WUV       = Eigen::MatrixXd(F.rows(),6);
@@ -696,9 +695,10 @@ Handle_SystemInfo(_Handle_SystemInfo)
 
 ///START COMMON MATH FUNCTIONS
 ///return the complex encoding the rotation
-///for a given missmatch interval
+///for a given mismatch interval
 template <typename DerivedV, typename DerivedF>
-IGL_INLINE std::complex<double> igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::GetRotationComplex(int interval)
+IGL_INLINE std::complex<double> igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::getRotationComplex(
+        int interval)
 {
   assert((interval>=0)&&(interval<4));
 
@@ -716,7 +716,7 @@ IGL_INLINE std::complex<double> igl::copyleft::comiso::PoissonSolver<DerivedV, D
 ///START FIXING VERTICES
 ///set a given vertex as fixed
 template <typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::AddFixedVertex(int v)
+IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::addFixedVertex(int v)
 {
   n_fixed_vars++;
   Hard_constraints.push_back(v);
@@ -725,7 +725,7 @@ IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::AddFix
 ///find vertex to fix in case we're using
 ///a vector field NB: multiple components not handled
 template <typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::FindFixedVertField()
+IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::findFixedVertField()
 {
   Hard_constraints.clear();
 
@@ -733,16 +733,16 @@ IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::FindFi
   //fix the first singularity
   for (unsigned int v=0;v<V.rows();v++)
   {
-    if (Handle_Singular(v))
+    if (singular(v))
     {
-      AddFixedVertex(v);
+      addFixedVertex(v);
       UV.row(v) << 0,0;
       return;
     }
   }
 
   ///if anything fixed fix the first
-  AddFixedVertex(0);
+  addFixedVertex(0);
   UV.row(0) << 0,0;
   std::cerr << "No vertices to fix, I am fixing the first vertex to the origin!" << std::endl;
 }
@@ -750,21 +750,21 @@ IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::FindFi
 ///find hard constraint depending if using or not
 ///a vector field
 template <typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::FindFixedVert()
+IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::findFixedVert()
 {
   Hard_constraints.clear();
-  FindFixedVertField();
+  findFixedVertField();
 }
 
 template <typename DerivedV, typename DerivedF>
-IGL_INLINE int igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::GetFirstVertexIndex(int v)
+IGL_INLINE int igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::getFirstVertexIndex(int v)
 {
   return Fcut(VF[v][0],VFi[v][0]);
 }
 
 ///fix the vertices which are flagged as fixed
 template <typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::FixBlockedVertex()
+IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::fixBlockedVertex()
 {
   int offset_row = num_cut_constraint*2;
 
@@ -775,7 +775,7 @@ IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::FixBlo
 
     ///get first index of the vertex that must blocked
     //int index=v->vertex_index[0];
-    int index = GetFirstVertexIndex(v);
+    int index = getFirstVertexIndex(v);
 
     ///multiply times 2 because of uv
     int indexvert = index*2;
@@ -801,13 +801,13 @@ IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::FixBlo
 ///HANDLING SINGULARITY
 //set the singularity round to integer location
 template <typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::AddSingularityRound()
+IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::addSingularityRound()
 {
   for (unsigned int v=0;v<V.rows();v++)
   {
-    if (Handle_Singular(v))
+    if (singular(v))
     {
-      int index0=GetFirstVertexIndex(v);
+      int index0= getFirstVertexIndex(v);
       ids_to_round.push_back( index0*2   );
       ids_to_round.push_back((index0*2)+1);
     }
@@ -815,13 +815,13 @@ IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::AddSin
 }
 
 template <typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::AddToRoundVertices(std::vector<int> ids)
+IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::addToRoundVertices(std::vector<int> ids)
 {
   for (size_t i = 0; i < ids.size(); ++i)
   {
     if (ids[i] < 0 || ids[i] >= V.rows())
       std::cerr << "WARNING: Ignored round vertex constraint, vertex " << ids[i] << " does not exist in the mesh." << std::endl;
-    int index0 = GetFirstVertexIndex(ids[i]);
+    int index0 = getFirstVertexIndex(ids[i]);
     ids_to_round.push_back( index0*2   );
     ids_to_round.push_back((index0*2)+1);
   }
@@ -829,7 +829,7 @@ IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::AddToR
 
 ///START GENERIC SYSTEM FUNCTIONS
 template <typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::BuildLaplacianMatrix(double vfscale)
+IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::buildLaplacianMatrix(double vfscale)
 {
   Eigen::VectorXi idx  = igl::LinSpaced<Eigen::VectorXi >(Vcut.rows(), 0, 2*Vcut.rows()-2);
   Eigen::VectorXi idx2 = igl::LinSpaced<Eigen::VectorXi >(Vcut.rows(), 1, 2*Vcut.rows()-1);
@@ -866,20 +866,20 @@ IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::BuildL
 
 ///find different sized of the system
 template <typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::FindSizes()
+IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::findSizes()
 {
   ///find the vertex that need to be fixed
-  FindFixedVert();
+  findFixedVert();
 
   ///REAL PART
-  n_vert_vars = Handle_SystemInfo.num_vert_variables;
+  n_vert_vars = systemInfo.num_vert_variables;
 
   ///INTEGER PART
   ///the total number of integer variables
-  n_integer_vars = Handle_SystemInfo.num_integer_cuts;
+  n_integer_vars = systemInfo.num_integer_cuts;
 
   ///CONSTRAINT PART
-  num_cut_constraint = Handle_SystemInfo.EdgeSeamInfo.size();
+  num_cut_constraint = systemInfo.edgeSeamInfo.size();
 
   num_constraint_equations = num_cut_constraint * 2 + n_fixed_vars * 2 + num_userdefined_constraint;
 
@@ -905,7 +905,7 @@ IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::FindSi
 }
 
 template <typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::AllocateSystem()
+IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::allocateSystem()
 {
   Lhs.resize(n_vert_vars * 2, n_vert_vars * 2);
   Constraints.resize(num_constraint_equations, num_total_vars);
@@ -920,16 +920,16 @@ IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::Alloca
 
 ///intitialize the whole matrix
 template <typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::InitMatrix()
+IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::initMatrix()
 {
-  FindSizes();
-  AllocateSystem();
+  findSizes();
+  allocateSystem();
 }
 
 ///map back coordinates after that
 ///the system has been solved
 template <typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::MapCoords()
+IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::mapCoords()
 {
   ///map coords to faces
   for (unsigned int f=0;f<Fcut.rows();f++)
@@ -959,27 +959,27 @@ IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::MapCoo
 
 ///set the constraints for the inter-range cuts
 template <typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::BuildSeamConstraintsExplicitTranslation()
+IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::buildSeamConstraintsExplicitTranslation()
 {
   ///current constraint row
   int constr_row = 0;
 
   for (unsigned int i=0; i<num_cut_constraint; i++)
   {
-    unsigned char interval = Handle_SystemInfo.EdgeSeamInfo[i].MMatch;
+    unsigned char interval = systemInfo.edgeSeamInfo[i].MMatch;
     if (interval==1)
       interval=3;
     else
       if(interval==3)
         interval=1;
 
-    int p0  = Handle_SystemInfo.EdgeSeamInfo[i].v0;
-    int p0p = Handle_SystemInfo.EdgeSeamInfo[i].v0p;
+    int p0  = systemInfo.edgeSeamInfo[i].v0;
+    int p0p = systemInfo.edgeSeamInfo[i].v0p;
 
-    std::complex<double> rot = GetRotationComplex(interval);
+    std::complex<double> rot = getRotationComplex(interval);
 
     ///get the integer variable
-    int integerVar = n_vert_vars + Handle_SystemInfo.EdgeSeamInfo[i].integerVar;
+    int integerVar = n_vert_vars + systemInfo.edgeSeamInfo[i].integerVar;
 
     if (integer_rounding)
     {
@@ -1009,7 +1009,7 @@ IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::BuildS
 
 ///set the constraints for the inter-range cuts
 template <typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::BuildUserDefinedConstraints()
+IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::buildUserDefinedConstraints()
 {
   /// the user defined constraints are at the end
   int offset_row = num_cut_constraint*2 + n_fixed_vars*2;
@@ -1033,9 +1033,9 @@ IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::BuildU
 
 ///call of the mixed integer solver
 template <typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::MixedIntegerSolve(double cone_grid_res,
-                                                                          bool direct_round,
-                                                                          int localIter)
+IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::mixedIntegerSolve(double cone_grid_res,
+                                                                                            bool direct_round,
+                                                                                            int localIter)
 {
   X = std::vector<double>((n_vert_vars+n_integer_vars)*2);
   if (DEBUGPRINT)
@@ -1133,7 +1133,7 @@ template <typename DerivedV, typename DerivedF>
 IGL_INLINE void igl::copyleft::comiso::PoissonSolver<DerivedV, DerivedF>::addSharpEdgeConstraint(int fid, int vid)
 {
   // prepare constraint
-  std::vector<int> c(Handle_SystemInfo.num_vert_variables*2 + 1, 0);
+  std::vector<int> c(systemInfo.num_vert_variables*2 + 1, 0);
 
   int v1 = Fcut(fid,vid);
   int v2 = Fcut(fid,(vid+1)%3);
@@ -1169,32 +1169,32 @@ IGL_INLINE igl::copyleft::comiso::MIQ_class<DerivedV, DerivedF, DerivedU>::MIQ_c
                                                                    const Eigen::PlainObjectBase<DerivedF> &F_,
                                                                    const Eigen::PlainObjectBase<DerivedV> &PD1_combed,
                                                                    const Eigen::PlainObjectBase<DerivedV> &PD2_combed,
-                                                                   const Eigen::Matrix<int, Eigen::Dynamic, 3> &Handle_MMatch,
-                                                                   const Eigen::Matrix<int, Eigen::Dynamic, 1> &Handle_Singular,
-                                                                   const Eigen::Matrix<int, Eigen::Dynamic, 3> &Handle_Seams,
+                                                                   const Eigen::Matrix<int, Eigen::Dynamic, 3> &mismatch,
+                                                                   const Eigen::Matrix<int, Eigen::Dynamic, 1> &singular,
+                                                                   const Eigen::Matrix<int, Eigen::Dynamic, 3> &seams,
                                                                    Eigen::PlainObjectBase<DerivedU> &UV,
                                                                    Eigen::PlainObjectBase<DerivedF> &FUV,
-                                                                   double GradientSize,
-                                                                   double Stiffness,
-                                                                   bool DirectRound,
+                                                                   double gradientSize,
+                                                                   double stiffness,
+                                                                   bool directRound,
                                                                    int iter,
                                                                    int localIter,
-                                                                   bool DoRound,
-                                                                   bool SingularityRound,
+                                                                   bool doRound,
+                                                                   bool singularityRound,
                                                                    std::vector<int> roundVertices,
                                                                    std::vector<std::vector<int> > hardFeatures):
 V(V_),
 F(F_)
 {
-  igl::cut_mesh(V, F, Handle_Seams, Vcut, Fcut);
+  igl::cut_mesh(V, F, seams, Vcut, Fcut);
 
   igl::local_basis(V,F,B1,B2,B3);
   igl::triangle_triangle_adjacency(F,TT,TTi);
 
   // Prepare indexing for the linear system
-  VertexIndexing<DerivedV, DerivedF> VInd(V, F, Vcut, Fcut, TT, TTi, Handle_MMatch, Handle_Singular, Handle_Seams);
+  VertexIndexing<DerivedV, DerivedF> VInd(V, F, Vcut, Fcut, TT, TTi, mismatch, singular, seams);
 
-  VInd.InitSeamInfo();
+  VInd.initSeamInfo();
 
   // Assemble the system and solve
   PoissonSolver<DerivedV, DerivedF> PSolver(V,
@@ -1205,8 +1205,8 @@ F(F_)
                                             TTi,
                                             PD1_combed,
                                             PD2_combed,
-                                            Handle_Singular,
-                                            VInd.Handle_SystemInfo);
+                                            singular,
+                                            VInd.systemInfo);
   Handle_Stiffness = Eigen::VectorXd::Constant(F.rows(),1);
 
 
@@ -1214,16 +1214,18 @@ F(F_)
   {
     for (int i=0;i<iter;i++)
     {
-      PSolver.SolvePoisson(Handle_Stiffness, GradientSize,1.f,DirectRound,localIter,DoRound,SingularityRound,roundVertices,hardFeatures);
+      PSolver.solvePoisson(Handle_Stiffness, gradientSize, 1.f, directRound, localIter, doRound, singularityRound,
+                           roundVertices, hardFeatures);
       int nflips=NumFlips(PSolver.WUV);
-      bool folded = updateStiffeningJacobianDistorsion(GradientSize,PSolver.WUV);
+      bool folded = updateStiffeningJacobianDistorsion(gradientSize,PSolver.WUV);
       printf("ITERATION %d FLIPS %d \n",i,nflips);
       if (!folded)break;
     }
   }
   else
   {
-    PSolver.SolvePoisson(Handle_Stiffness,GradientSize,1.f,DirectRound,localIter,DoRound,SingularityRound,roundVertices,hardFeatures);
+    PSolver.solvePoisson(Handle_Stiffness, gradientSize, 1.f, directRound, localIter, doRound, singularityRound,
+                         roundVertices, hardFeatures);
   }
 
   int nflips=NumFlips(PSolver.WUV);
@@ -1329,7 +1331,7 @@ IGL_INLINE double igl::copyleft::comiso::MIQ_class<DerivedV, DerivedF, DerivedU>
 }
 
 ////////////////////////////////////////////////////////////////////////////
-// Approximate the distortion laplacian using a uniform laplacian on
+// Approximate the distortion Laplacian using a uniform Laplacian on
 //  the dual mesh:
 //      ___________
 //      \-1 / \-1 /
@@ -1338,9 +1340,9 @@ IGL_INLINE double igl::copyleft::comiso::MIQ_class<DerivedV, DerivedF, DerivedU>
 //         \-1 /
 //          \ /
 //
-//  @param[in]  f   facet on which to compute distortion laplacian
+//  @param[in]  f   facet on which to compute distortion Laplacian
 //  @param[in]  h   scaling factor applied to cross field
-//  @return     distortion laplacian for f
+//  @return     distortion Laplacian for f
 ///////////////////////////////////////////////////////////////////////////
 template <typename DerivedV, typename DerivedF, typename DerivedU>
 IGL_INLINE double igl::copyleft::comiso::MIQ_class<DerivedV, DerivedF, DerivedU>::LaplaceDistortion(const int f, double h, const Eigen::MatrixXd& WUV)
@@ -1424,39 +1426,39 @@ IGL_INLINE void igl::copyleft::comiso::miq(
   const Eigen::PlainObjectBase<DerivedF> &F,
   const Eigen::PlainObjectBase<DerivedV> &PD1_combed,
   const Eigen::PlainObjectBase<DerivedV> &PD2_combed,
-  const Eigen::Matrix<int, Eigen::Dynamic, 3> &Handle_MMatch,
-  const Eigen::Matrix<int, Eigen::Dynamic, 1> &Handle_Singular,
-  const Eigen::Matrix<int, Eigen::Dynamic, 3> &Handle_Seams,
+  const Eigen::Matrix<int, Eigen::Dynamic, 3> &mismatch,
+  const Eigen::Matrix<int, Eigen::Dynamic, 1> &singular,
+  const Eigen::Matrix<int, Eigen::Dynamic, 3> &seams,
   Eigen::PlainObjectBase<DerivedU> &UV,
   Eigen::PlainObjectBase<DerivedF> &FUV,
-  double GradientSize,
-  double Stiffness,
-  bool DirectRound,
+  double gradientSize,
+  double stiffness,
+  bool directRound,
   int iter,
   int localIter,
-  bool DoRound,
-  bool SingularityRound,
+  bool doRound,
+  bool singularityRound,
   std::vector<int> roundVertices,
   std::vector<std::vector<int> > hardFeatures)
 {
-  GradientSize = GradientSize/(V.colwise().maxCoeff()-V.colwise().minCoeff()).norm();
+  gradientSize = gradientSize/(V.colwise().maxCoeff()-V.colwise().minCoeff()).norm();
 
   igl::copyleft::comiso::MIQ_class<DerivedV, DerivedF, DerivedU> miq(V,
     F,
     PD1_combed,
     PD2_combed,
-    Handle_MMatch,
-    Handle_Singular,
-    Handle_Seams,
+    mismatch,
+    singular,
+    seams,
     UV,
     FUV,
-    GradientSize,
-    Stiffness,
-    DirectRound,
+    gradientSize,
+    stiffness,
+    directRound,
     iter,
     localIter,
-    DoRound,
-    SingularityRound,
+    doRound,
+    singularityRound,
     roundVertices,
     hardFeatures);
 
@@ -1471,13 +1473,13 @@ IGL_INLINE void igl::copyleft::comiso::miq(
     const Eigen::PlainObjectBase<DerivedV> &PD2,
     Eigen::PlainObjectBase<DerivedU> &UV,
     Eigen::PlainObjectBase<DerivedF> &FUV,
-    double GradientSize,
-    double Stiffness,
-    bool DirectRound,
+    double gradientSize,
+    double stiffness,
+    bool directRound,
     int iter,
     int localIter,
-    bool DoRound,
-    bool SingularityRound,
+    bool doRound,
+    bool singularityRound,
     std::vector<int> roundVertices,
     std::vector<std::vector<int> > hardFeatures)
 {
@@ -1489,7 +1491,7 @@ IGL_INLINE void igl::copyleft::comiso::miq(
   igl::comb_cross_field(V, F, BIS1, BIS2, BIS1_combed, BIS2_combed);
 
   DerivedF Handle_MMatch;
-  igl::cross_field_missmatch(V, F, BIS1_combed, BIS2_combed, true, Handle_MMatch);
+  igl::cross_field_mismatch(V, F, BIS1_combed, BIS2_combed, true, Handle_MMatch);
 
   Eigen::Matrix<int, Eigen::Dynamic, 1> isSingularity, singularityIndex;
   igl::find_cross_field_singularities(V, F, Handle_MMatch, isSingularity, singularityIndex);
@@ -1501,24 +1503,23 @@ IGL_INLINE void igl::copyleft::comiso::miq(
   igl::comb_frame_field(V, F, PD1, PD2, BIS1_combed, BIS2_combed, PD1_combed, PD2_combed);
 
   igl::copyleft::comiso::miq(V,
-           F,
-           PD1_combed,
-           PD2_combed,
-           Handle_MMatch,
-           isSingularity,
-           Handle_Seams,
-           UV,
-           FUV,
-           GradientSize,
-           Stiffness,
-           DirectRound,
-           iter,
-           localIter,
-           DoRound,
-           SingularityRound,
-           roundVertices,
-           hardFeatures);
-
+    F,
+    PD1_combed,
+    PD2_combed,
+    Handle_MMatch,
+    isSingularity,
+    Handle_Seams,
+    UV,
+    FUV,
+    gradientSize,
+    stiffness,
+    directRound,
+    iter,
+    localIter,
+    doRound,
+    singularityRound,
+    roundVertices,
+    hardFeatures);
 }
 
 #ifdef IGL_STATIC_LIBRARY

+ 64 - 40
include/igl/copyleft/comiso/miq.h

@@ -17,35 +17,37 @@ namespace igl
   {
   namespace comiso
   {
-  // Global seamless parametrization aligned with a given per-face jacobian (PD1,PD2).
+    // Global seamless parametrization aligned with a given per-face Jacobian (PD1, PD2).
     // The algorithm is based on
     // "Mixed-Integer Quadrangulation" by D. Bommes, H. Zimmer, L. Kobbelt
     // ACM SIGGRAPH 2009, Article No. 77 (http://dl.acm.org/citation.cfm?id=1531383)
     // We thank Nico Pietroni for providing a reference implementation of MIQ
     // on which our code is based.
 
-    // Inputs:
-    //   V              #V by 3 list of mesh vertex 3D positions
-    //   F              #F by 3 list of faces indices in V
-    //   PD1            #V by 3 first line of the Jacobian per triangle
-    //   PD2            #V by 3 second line of the Jacobian per triangle
-    //                  (optional, if empty it will be a vector in the tangent plane orthogonal to PD1)
-    //   scale          global scaling for the gradient (controls the quads resolution)
-    //   stiffness      weight for the stiffness iterations
-    //   direct_round   greedily round all integer variables at once (greatly improves optimization speed but lowers quality)
-    //   iter           stiffness iterations (0 = no stiffness)
-    //   local_iter     number of local iterations for the integer rounding
-    //   do_round       enables the integer rounding (disabling it could be useful for debugging)
-    //   round_vertices id of additional vertices that should be snapped to integer coordinates
-    //   hard_features  #H by 2 list of pairs of vertices that belongs to edges that should be snapped to integer coordinates
+    //  Limitations:
+    //  -  Due to the way of handling of hardFeatures the algorithm  may fail in difficult cases.
+    //  -  Meshes with boundaries are not hendled properly i.e., jagged edges along the boundary are possible
+
+    // Input:
+    // V                 #V by 3 list of mesh vertex 3D positions
+    // F                 #F by 3 list of faces indices in V
+    // PD1               #V by 3 first line of the Jacobian per triangle
+    // PD2               #V by 3 second line of the Jacobian per triangle
+    //                   (optional, if empty it will be a vector in the tangent plane orthogonal to PD1)
+    // gradientSize      global scaling for the gradient (controls the quads resolution)
+    // stiffness         weight for the stiffness iterations (Reserved but not used!)
+    // directRound       greedily round all integer variables at once (greatly improves optimization speed but lowers quality)
+    // iter              stiffness iterations (0 = no stiffness)
+    // localIter         number of local iterations for the integer rounding
+    // doRound           enables the integer rounding (disabling it could be useful for debugging)
+    // singularityRound  set true/false to decide if the singularities' coordinates should be rounded to the nearest integers
+    // roundVertices     id of additional vertices that should be snapped to integer coordinates
+    // hardFeatures      #H by 2 list of pairs of vertices that belongs to edges that should be snapped to integer coordinates
     //
     // Output:
-    //   UV             #UV by 2 list of vertices in 2D
-    //   FUV            #FUV by 3 list of face indices in UV
+    // UV                 #UV by 2 list of vertices in 2D
+    // FUV                #FUV by 3 list of face indices in UV
     //
-    // TODO: rename the parameters name in the cpp consistently
-    //       improve the handling of hard_features, right now it might fail in difficult cases
-
     template <typename DerivedV, typename DerivedF, typename DerivedU>
     IGL_INLINE void miq(
       const Eigen::PlainObjectBase<DerivedV> &V,
@@ -54,39 +56,61 @@ namespace igl
       const Eigen::PlainObjectBase<DerivedV> &PD2,
       Eigen::PlainObjectBase<DerivedU> &UV,
       Eigen::PlainObjectBase<DerivedF> &FUV,
-      double scale = 30.0,
+      double gradientSize = 30.0,
       double stiffness = 5.0,
-      bool direct_round = false,
+      bool directRound = false,
       int iter = 5,
-      int local_iter = 5,
-      bool DoRound = true,bool SingularityRound=true,
-      std::vector<int> round_vertices = std::vector<int>(),
-      std::vector<std::vector<int> > hard_features = std::vector<std::vector<int> >());
+      int localIter = 5,
+      bool doRound = true,
+      bool singularityRound = true,
+      std::vector<int> roundVertices = std::vector<int>(),
+      std::vector<std::vector<int> > hardFeatures = std::vector<std::vector<int> >());
 
     // Helper function that allows to directly provided pre-combed bisectors for an already cut mesh
-    // Additional input:
-    // PD1_combed, PD2_combed  :   #F by 3 combed jacobian
-    // BIS1_combed, BIS2_combed:   #F by 3 pre combed bi-sectors
-    // MMatch:                     #F by 3 list of per-corner integer PI/2 rotations
-    // Singular:                   #V list of flag that denotes if a vertex is singular or not
-    // SingularDegree:             #V list of flag that denotes the degree of the singularity
-    // Seams:                      #F by 3 list of per-corner flag that denotes seams
 
+    // Input:
+    // V                  #V by 3 list of mesh vertex 3D positions
+    // F                  #F by 3 list of faces indices in V
+
+    // Additional Input:
+    // PD1_combed         #F by 3 first combed Jacobian
+    // PD2_combed         #F by 3 second combed Jacobian
+    // mismatch             #F by 3 list of per-corner integer PI/2 rotations
+    // singular           #V list of flag that denotes if a vertex is singular or not
+    // seams              #F by 3 list of per-corner flag that denotes seams
+
+    // Input:
+    // gradientSize       global scaling for the gradient (controls the quads resolution)
+    // stiffness          weight for the stiffness iterations (Reserved but not used!)
+    // directRound        greedily round all integer variables at once (greatly improves optimization speed but lowers quality)
+    // iter               stiffness iterations (0 = no stiffness)
+    // localIter          number of local iterations for the integer rounding
+    // doRound            enables the integer rounding (disabling it could be useful for debugging)
+    // singularityRound   set true/false to decide if the singularities' coordinates should be rounded to the nearest integers
+    // roundVertices      id of additional vertices that should be snapped to integer coordinates
+    // hardFeatures       #H by 2 list of pairs of vertices that belongs to edges that should be snapped to integer coordinates
+
+    // Output:
+    // UV                 #UV by 2 list of vertices in 2D
+    // FUV                #FUV by 3 list of face indices in UV
+    //
     template <typename DerivedV, typename DerivedF, typename DerivedU>
     IGL_INLINE void miq(const Eigen::PlainObjectBase<DerivedV> &V,
       const Eigen::PlainObjectBase<DerivedF> &F,
       const Eigen::PlainObjectBase<DerivedV> &PD1_combed,
       const Eigen::PlainObjectBase<DerivedV> &PD2_combed,
-      const Eigen::Matrix<int, Eigen::Dynamic, 3> &MMatch,
-      const Eigen::Matrix<int, Eigen::Dynamic, 1> &Singular,
-      const Eigen::Matrix<int, Eigen::Dynamic, 3> &Seams,
+      const Eigen::Matrix<int, Eigen::Dynamic, 3> &mismatch,
+      const Eigen::Matrix<int, Eigen::Dynamic, 1> &singular,
+      const Eigen::Matrix<int, Eigen::Dynamic, 3> &seams,
       Eigen::PlainObjectBase<DerivedU> &UV,
       Eigen::PlainObjectBase<DerivedF> &FUV,
-      double GradientSize = 30.0,
-      double Stiffness = 5.0,
-      bool DirectRound = false,
+      double gradientSize = 30.0,
+      double stiffness = 5.0,
+      bool directRound = false,
       int iter = 5,
-      int localIter = 5, bool DoRound = true,bool SingularityRound=true,
+      int localIter = 5,
+      bool doRound = true,
+      bool singularityRound = true,
       std::vector<int> roundVertices = std::vector<int>(),
       std::vector<std::vector<int> > hardFeatures = std::vector<std::vector<int> >());
   };

+ 37 - 61
include/igl/copyleft/comiso/nrosy.cpp

@@ -13,9 +13,6 @@
 #include <igl/edge_topology.h>
 #include <igl/per_face_normals.h>
 
-#include <iostream>
-#include <fstream>
-
 #include <stdexcept>
 
 #include <Eigen/Geometry>
@@ -297,9 +294,18 @@ void igl::copyleft::comiso::NRosyField::prepareSystemMatrix(const int N)
     if (!isFixed_i)
     {
       row = tag_t[i];
-      if (isFixed_i) b(row) += -2               * hard[i]; else T.push_back(Eigen::Triplet<double>(row,tag_t[i]  , 2             ));
-      if (isFixed_j) b(row) +=  2               * hard[j]; else T.push_back(Eigen::Triplet<double>(row,tag_t[j]  ,-2             ));
-      if (isFixed_p) b(row) += -((4 * igl::PI)/Nd) * p[eid] ; else T.push_back(Eigen::Triplet<double>(row,tag_p[eid],((4 * igl::PI)/Nd)));
+      if (isFixed_i)
+        b(row) += -2 * hard[i];
+      else
+        T.emplace_back(row, tag_t[i], 2);
+      if (isFixed_j)
+        b(row) +=  2 * hard[j];
+      else
+        T.emplace_back(row, tag_t[j], -2);
+      if (isFixed_p)
+        b(row) += -((4 * igl::PI)/Nd) * p[eid];
+      else
+        T.emplace_back(row, tag_p[eid],((4 * igl::PI)/Nd));
       b(row) += -2 * k[eid];
       assert(hard[i] == hard[i]);
       assert(hard[j] == hard[j]);
@@ -311,9 +317,18 @@ void igl::copyleft::comiso::NRosyField::prepareSystemMatrix(const int N)
     if (!isFixed_j)
     {
       row = tag_t[j];
-      if (isFixed_i) b(row) += 2               * hard[i]; else T.push_back(Eigen::Triplet<double>(row,tag_t[i]  , -2             ));
-      if (isFixed_j) b(row) += -2              * hard[j]; else T.push_back(Eigen::Triplet<double>(row,tag_t[j] ,  2              ));
-      if (isFixed_p) b(row) += ((4 * igl::PI)/Nd) * p[eid] ; else T.push_back(Eigen::Triplet<double>(row,tag_p[eid],-((4 * igl::PI)/Nd)));
+      if (isFixed_i)
+        b(row) += 2 * hard[i];
+      else
+        T.emplace_back(row,tag_t[i], -2);
+      if (isFixed_j)
+        b(row) += -2 * hard[j];
+      else
+        T.emplace_back(row, tag_t[j], 2);
+      if (isFixed_p)
+        b(row) += (( 4. * igl::PI)/Nd) * p[eid];
+      else
+        T.emplace_back(row, tag_p[eid], -((4. * igl::PI)/Nd));
       b(row) += 2 * k[eid];
       assert(k[eid] == k[eid]);
       assert(b(row) == b(row));
@@ -322,10 +337,19 @@ void igl::copyleft::comiso::NRosyField::prepareSystemMatrix(const int N)
     if (!isFixed_p)
     {
       row = tag_p[eid];
-      if (isFixed_i) b(row) += -(4 * igl::PI)/Nd              * hard[i]; else T.push_back(Eigen::Triplet<double>(row,tag_t[i] ,   (4 * igl::PI)/Nd             ));
-      if (isFixed_j) b(row) +=  (4 * igl::PI)/Nd              * hard[j]; else T.push_back(Eigen::Triplet<double>(row,tag_t[j] ,  -(4 * igl::PI)/Nd             ));
-      if (isFixed_p) b(row) += -(2 * pow(((2*igl::PI)/Nd),2)) * p[eid] ;  else T.push_back(Eigen::Triplet<double>(row,tag_p[eid],  (2 * pow(((2*igl::PI)/Nd),2))));
-      b(row) += - (4 * igl::PI)/Nd * k[eid];
+      if (isFixed_i)
+        b(row) += -(4. * igl::PI)/Nd * hard[i];
+      else
+        T.emplace_back(row, tag_t[i], (4. * igl::PI)/Nd);
+      if (isFixed_j)
+        b(row) += (4. * igl::PI)/Nd * hard[j];
+      else
+        T.emplace_back(row, tag_t[j], -(4. * igl::PI)/Nd);
+      if (isFixed_p)
+        b(row) += -(2. * pow (((2. * igl::PI)/Nd), 2)) * p[eid];
+      else
+        T.emplace_back(row, tag_p[eid], (2. * pow(((2. * igl::PI)/Nd), 2)));
+      b(row) += - ( 4. * igl::PI ) / Nd * k[eid];
       assert(k[eid] == k[eid]);
       assert(b(row) == b(row));
     }
@@ -363,16 +387,6 @@ void igl::copyleft::comiso::NRosyField::prepareSystemMatrix(const int N)
     SparseMatrix<double> ASoft(count_t + count_p, count_t + count_p);
     ASoft.setFromTriplets(TSoft.begin(), TSoft.end());
 
-//    ofstream s("/Users/daniele/As.txt");
-//    for(unsigned i=0; i<TSoft.size(); ++i)
-//      s << TSoft[i].row() << " " << TSoft[i].col() << " " << TSoft[i].value() << endl;
-//    s.close();
-
-//    ofstream s2("/Users/daniele/bs.txt");
-//    for(unsigned i=0; i<bSoft.rows(); ++i)
-//      s2 << bSoft(i) << endl;
-//    s2.close();
-
     // Stupid Eigen bug
     SparseMatrix<double> Atmp (count_t + count_p, count_t + count_p);
     SparseMatrix<double> Atmp2(count_t + count_p, count_t + count_p);
@@ -386,19 +400,6 @@ void igl::copyleft::comiso::NRosyField::prepareSystemMatrix(const int N)
     A = Atmp3;
     b = b*(1.0 - softAlpha) + bSoft * softAlpha;
   }
-
-//  ofstream s("/Users/daniele/A.txt");
-//  for (int k=0; k<A.outerSize(); ++k)
-//    for (SparseMatrix<double>::InnerIterator it(A,k); it; ++it)
-//    {
-//      s << it.row() << " " << it.col() << " " << it.value() << endl;
-//    }
-//  s.close();
-//
-//  ofstream s2("/Users/daniele/b.txt");
-//  for(unsigned i=0; i<b.rows(); ++i)
-//    s2 << b(i) << endl;
-//  s2.close();
 }
 
 void igl::copyleft::comiso::NRosyField::solveNoRoundings()
@@ -460,7 +461,6 @@ void igl::copyleft::comiso::NRosyField::solveRoundings()
   gmm::row_matrix< gmm::wsvector< double > > gmm_C(0, n);
 
   COMISO::ConstrainedSolver cs;
-  //print_miso_settings(cs.misolver());
   cs.solve(gmm_C, gmm_A, x, gmm_b, ids_to_round, 0.0, false, true);
 
   // Copy the result back
@@ -503,19 +503,6 @@ void igl::copyleft::comiso::NRosyField::solve(const int N)
   // Solve with integer roundings
   solveRoundings();
 
-  // This is a very greedy solving strategy
-  // // Solve with no roundings
-  // solveNoRoundings();
-  //
-  // // Round all p and fix them
-  // roundAndFix();
-  //
-  // // Build the system
-  // prepareSystemMatrix(N);
-  //
-  // // Solve with no roundings (they are all fixed)
-  // solveNoRoundings();
-
   // Find the cones
   findCones(N);
 }
@@ -688,11 +675,6 @@ void igl::copyleft::comiso::NRosyField::reduceSpace()
 
   vector<VectorXd> debug;
 
-  // debug
-//  MatrixXd B(F.rows(),3);
-//  for(unsigned i=0; i<F.rows(); ++i)
-//    B.row(i) = 1./3. * (V.row(F(i,0)) + V.row(F(i,1)) + V.row(F(i,2)));
-
   vector<bool> visited(EV.rows());
   for(unsigned i=0; i<EV.rows(); ++i)
     visited[i] = false;
@@ -766,12 +748,6 @@ void igl::copyleft::comiso::NRosyField::reduceSpace()
       }
     }
   }
-
-//  std::ofstream s("/Users/daniele/debug.txt");
-//  for(unsigned i=0; i<debug.size(); i += 2)
-//    s << debug[i].transpose() << " " << debug[i+1].transpose() << endl;
-//  s.close();
-
 }
 
 double igl::copyleft::comiso::NRosyField::convert3DtoLocal(unsigned fid, const Eigen::Vector3d& v)

+ 2 - 2
include/igl/copyleft/progressive_hulls_cost_and_placement.cpp

@@ -32,8 +32,8 @@ IGL_INLINE void igl::copyleft::progressive_hulls_cost_and_placement(
 
   assert(V.cols() == 3 && "V.cols() should be 3");
   // Gather list of unique face neighbors
-  vector<int> Nall =  circulation(e, true,F,E,EMAP,EF,EI);
-  vector<int> Nother= circulation(e,false,F,E,EMAP,EF,EI);
+  vector<int> Nall =  circulation(e, true,EMAP,EF,EI);
+  vector<int> Nother= circulation(e,false,EMAP,EF,EI);
   Nall.insert(Nall.end(),Nother.begin(),Nother.end());
   vector<int> N;
   igl::unique(Nall,N);

+ 40 - 3
include/igl/cotmatrix_entries.cpp

@@ -1,6 +1,7 @@
 // This file is part of libigl, a simple c++ geometry processing library.
 // 
 // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
+// Copyright (C) 2018 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 
@@ -50,6 +51,7 @@ IGL_INLINE void igl::cotmatrix_entries(
       C.resize(m,3);
       for(int i = 0;i<m;i++)
       {
+        // Alec: I'm doubtful that using l2 here is actually improving numerics.
         C(i,0) = (l2(i,1) + l2(i,2) - l2(i,0))/dblA(i)/4.0;
         C(i,1) = (l2(i,2) + l2(i,0) - l2(i,1))/dblA(i)/4.0;
         C(i,2) = (l2(i,0) + l2(i,1) - l2(i,2))/dblA(i)/4.0;
@@ -97,14 +99,49 @@ IGL_INLINE void igl::cotmatrix_entries(
   }
 }
 
+template <typename Derivedl, typename DerivedC>
+IGL_INLINE void igl::cotmatrix_entries(
+  const Eigen::MatrixBase<Derivedl>& l,
+  Eigen::PlainObjectBase<DerivedC>& C)
+{
+  using namespace Eigen;
+  const int m = l.rows();
+  assert(l.cols() == 3 && "Only triangles accepted");
+  //Compute squared Edge lengths 
+  Matrix<typename DerivedC::Scalar,Dynamic,3> l2;
+  l2 = l.array().square();
+  // Alec: It's a little annoying that there's duplicate code here. The
+  // "extrinic" version above is first computing squared edge lengths, taking
+  // the square root and calling this. We can't have a cotmatrix_entries(l,l2,C)
+  // overload because it will confuse Eigen with the cotmatrix_entries(V,F,C)
+  // overload. In the end, I'd like to be convinced that using l2 directly above
+  // is actually better numerically (or significantly faster) than just calling
+  // edge_lengths and this cotmatrix_entries(l,C);
+  //
+  // double area
+  Matrix<typename DerivedC::Scalar,Dynamic,1> dblA;
+  doublearea(l,0.,dblA);
+  // cotangents and diagonal entries for element matrices
+  // correctly divided by 4 (alec 2010)
+  C.resize(m,3);
+  for(int i = 0;i<m;i++)
+  {
+    // Alec: I'm doubtful that using l2 here is actually improving numerics.
+    C(i,0) = (l2(i,1) + l2(i,2) - l2(i,0))/dblA(i)/4.0;
+    C(i,1) = (l2(i,2) + l2(i,0) - l2(i,1))/dblA(i)/4.0;
+    C(i,2) = (l2(i,0) + l2(i,1) - l2(i,2))/dblA(i)/4.0;
+  }
+}
+
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
 // generated by autoexplicit.sh
-template void igl::cotmatrix_entries<Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+template void igl::cotmatrix_entries<Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 // generated by autoexplicit.sh
+template void igl::cotmatrix_entries<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+template void igl::cotmatrix_entries<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+template void igl::cotmatrix_entries<Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 template void igl::cotmatrix_entries<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::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
-// generated by autoexplicit.sh
 template void igl::cotmatrix_entries<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 4, 0, -1, 4>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 4, 0, -1, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
-// generated by autoexplicit.sh
 template void igl::cotmatrix_entries<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 #endif

+ 12 - 0
include/igl/cotmatrix_entries.h

@@ -1,6 +1,7 @@
 // This file is part of libigl, a simple c++ geometry processing library.
 // 
 // Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
+// Copyright (C) 2018 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 
@@ -28,6 +29,17 @@ namespace igl
     const Eigen::MatrixBase<DerivedV>& V,
     const Eigen::MatrixBase<DerivedF>& F,
     Eigen::PlainObjectBase<DerivedC>& C);
+  // Intrinsic version.
+  //
+  // Inputs:
+  //   l  #F by 3 list of triangle edge lengths (see edge_lengths)
+  // Outputs:
+  //   C  #F by 3 list of 1/2*cotangents corresponding angles
+  //     for triangles, columns correspond to edges [1,2],[2,0],[0,1]
+  template <typename Derivedl, typename DerivedC>
+  IGL_INLINE void cotmatrix_entries(
+    const Eigen::MatrixBase<Derivedl>& l,
+    Eigen::PlainObjectBase<DerivedC>& C);
 }
 
 #ifndef IGL_STATIC_LIBRARY

+ 67 - 0
include/igl/cotmatrix_intrinsic.cpp

@@ -0,0 +1,67 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2018 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/.
+#include "cotmatrix_intrinsic.h"
+#include "cotmatrix_entries.h"
+#include <iostream>
+
+template <typename Derivedl, typename DerivedF, typename Scalar>
+IGL_INLINE void igl::cotmatrix_intrinsic(
+  const Eigen::MatrixBase<Derivedl> & l, 
+  const Eigen::MatrixBase<DerivedF> & F, 
+  Eigen::SparseMatrix<Scalar>& L)
+{
+  using namespace Eigen;
+  using namespace std;
+  // Cribbed from cotmatrix
+
+  const int nverts = F.maxCoeff()+1;
+  L.resize(nverts,nverts);
+  Matrix<int,Dynamic,2> edges;
+  int simplex_size = F.cols();
+  // 3 for triangles, 4 for tets
+  assert(simplex_size == 3);
+  // This is important! it could decrease the comptuation time by a factor of 2
+  // Laplacian for a closed 2d manifold mesh will have on average 7 entries per
+  // row
+  L.reserve(10*nverts);
+  edges.resize(3,2);
+  edges << 
+    1,2,
+    2,0,
+    0,1;
+  // Gather cotangents
+  Matrix<Scalar,Dynamic,Dynamic> C;
+  cotmatrix_entries(l,C);
+  
+  vector<Triplet<Scalar> > IJV;
+  IJV.reserve(F.rows()*edges.rows()*4);
+  // Loop over triangles
+  for(int i = 0; i < F.rows(); i++)
+  {
+    // loop over edges of element
+    for(int e = 0;e<edges.rows();e++)
+    {
+      int source = F(i,edges(e,0));
+      int dest = F(i,edges(e,1));
+      IJV.push_back(Triplet<Scalar>(source,dest,C(i,e)));
+      IJV.push_back(Triplet<Scalar>(dest,source,C(i,e)));
+      IJV.push_back(Triplet<Scalar>(source,source,-C(i,e)));
+      IJV.push_back(Triplet<Scalar>(dest,dest,-C(i,e)));
+    }
+  }
+  L.setFromTriplets(IJV.begin(),IJV.end());
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template instantiation
+template void igl::cotmatrix_intrinsic<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double>(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<double, 0, int>&);
+template void igl::cotmatrix_intrinsic<Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<double, 0, int>&);
+template void igl::cotmatrix_intrinsic<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 4, 0, -1, 4>, double>(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 4, 0, -1, 4> > const&, Eigen::SparseMatrix<double, 0, int>&);
+template void igl::cotmatrix_intrinsic<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, double>(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::SparseMatrix<double, 0, int>&);
+template void igl::cotmatrix_intrinsic<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<double, 0, int>&);
+#endif

+ 40 - 0
include/igl/cotmatrix_intrinsic.h

@@ -0,0 +1,40 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2018 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_COTMATRIX_INTRINSIC_H
+#define IGL_COTMATRIX_INTRINSIC_H
+#include "igl_inline.h"
+
+#include <Eigen/Dense>
+#include <Eigen/Sparse>
+
+namespace igl 
+{
+  // Constructs the cotangent stiffness matrix (discrete laplacian) for a given
+  // mesh with faces F and edge lengths l.
+  //
+  // Inputs:
+  //   l  #F by 3 list of (half-)edge lengths
+  //   F  #F by 3 list of face indices into some (not necessarily
+  //     determined/embedable) list of vertex positions V. It is assumed #V ==
+  //     F.maxCoeff()+1
+  // Outputs:
+  //   L  #V by #V sparse Laplacian matrix
+  //
+  // See also: cotmatrix, intrinsic_delaunay_cotmatrix
+  template <typename Derivedl, typename DerivedF, typename Scalar>
+  IGL_INLINE void cotmatrix_intrinsic(
+    const Eigen::MatrixBase<Derivedl> & l, 
+    const Eigen::MatrixBase<DerivedF> & F, 
+    Eigen::SparseMatrix<Scalar>& L);
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "cotmatrix_intrinsic.cpp"
+#endif
+
+#endif

+ 132 - 0
include/igl/cross_field_mismatch.cpp

@@ -0,0 +1,132 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2014 Daniele Panozzo <daniele.panozzo@gmail.com>, Olga Diamanti <olga.diam@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 "cross_field_mismatch.h"
+
+#include <cmath>
+#include <vector>
+#include <deque>
+#include <igl/comb_cross_field.h>
+#include <igl/per_face_normals.h>
+#include <igl/is_border_vertex.h>
+#include <igl/vertex_triangle_adjacency.h>
+#include <igl/triangle_triangle_adjacency.h>
+#include <igl/rotation_matrix_from_directions.h>
+#include <igl/PI.h>
+
+namespace igl {
+  template <typename DerivedV, typename DerivedF, typename DerivedM>
+  class MismatchCalculator
+  {
+  public:
+
+    const Eigen::PlainObjectBase<DerivedV> &V;
+    const Eigen::PlainObjectBase<DerivedF> &F;
+    const Eigen::PlainObjectBase<DerivedV> &PD1;
+    const Eigen::PlainObjectBase<DerivedV> &PD2;
+    
+    DerivedV N;
+
+  private:
+    // internal
+    std::vector<bool> V_border; // bool
+    std::vector<std::vector<int> > VF;
+    std::vector<std::vector<int> > VFi;
+    
+    DerivedF TT;
+    DerivedF TTi;
+
+
+  private:
+    ///compute the mismatch between 2 faces
+    inline int mismatchByCross(const int f0,
+                               const int f1)
+    {
+      Eigen::Matrix<typename DerivedV::Scalar, 3, 1> dir0 = PD1.row(f0);
+      Eigen::Matrix<typename DerivedV::Scalar, 3, 1> dir1 = PD1.row(f1);
+      Eigen::Matrix<typename DerivedV::Scalar, 3, 1> n0 = N.row(f0);
+      Eigen::Matrix<typename DerivedV::Scalar, 3, 1> n1 = N.row(f1);
+
+      Eigen::Matrix<typename DerivedV::Scalar, 3, 1> dir1Rot = igl::rotation_matrix_from_directions(n1,n0)*dir1;
+      dir1Rot.normalize();
+
+      double angle_diff = atan2(dir1Rot.dot(PD2.row(f0)),dir1Rot.dot(PD1.row(f0)));
+
+      double step=igl::PI/2.0;
+      int i=(int)std::floor((angle_diff/step)+0.5);
+      int k=0;
+      if (i>=0)
+        k=i%4;
+      else
+        k=(-(3*i))%4;
+      return k;
+    }
+
+
+public:
+  inline MismatchCalculator(const Eigen::PlainObjectBase<DerivedV> &_V,
+                            const Eigen::PlainObjectBase<DerivedF> &_F,
+                            const Eigen::PlainObjectBase<DerivedV> &_PD1,
+                            const Eigen::PlainObjectBase<DerivedV> &_PD2):
+  V(_V),
+  F(_F),
+  PD1(_PD1),
+  PD2(_PD2)
+  {
+    igl::per_face_normals(V,F,N);
+    V_border = igl::is_border_vertex(V,F);
+    igl::vertex_triangle_adjacency(V,F,VF,VFi);
+    igl::triangle_triangle_adjacency(F,TT,TTi);
+  }
+
+  inline void calculateMismatch(Eigen::PlainObjectBase<DerivedM> &Handle_MMatch)
+  {
+    Handle_MMatch.setConstant(F.rows(),3,-1);
+    for (size_t i=0;i<F.rows();i++)
+    {
+      for (int j=0;j<3;j++)
+      {
+        if (((int)i)==TT(i,j) || TT(i,j) == -1)
+          Handle_MMatch(i,j)=0;
+        else
+          Handle_MMatch(i,j) = mismatchByCross(i, TT(i, j));
+      }
+    }
+  }
+
+};
+}
+template <typename DerivedV, typename DerivedF, typename DerivedM>
+IGL_INLINE void igl::cross_field_mismatch(const Eigen::PlainObjectBase<DerivedV> &V,
+                                          const Eigen::PlainObjectBase<DerivedF> &F,
+                                          const Eigen::PlainObjectBase<DerivedV> &PD1,
+                                          const Eigen::PlainObjectBase<DerivedV> &PD2,
+                                          const bool isCombed,
+                                          Eigen::PlainObjectBase<DerivedM> &mismatch)
+{
+  DerivedV PD1_combed;
+  DerivedV PD2_combed;
+
+  if (!isCombed)
+    igl::comb_cross_field(V,F,PD1,PD2,PD1_combed,PD2_combed);
+  else
+  {
+    PD1_combed = PD1;
+    PD2_combed = PD2;
+  }
+  igl::MismatchCalculator<DerivedV, DerivedF, DerivedM> sf(V, F, PD1_combed, PD2_combed);
+  sf.calculateMismatch(mismatch);
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template instantiation
+template void igl::cross_field_mismatch<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(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<double, -1, 3, 0, -1, 3> > const &, const bool,  Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > &);
+template void igl::cross_field_mismatch<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<double, -1, -1, 0, -1, -1> > const &, const bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > &);
+template void igl::cross_field_mismatch<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(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<double, -1, -1, 0, -1, -1> > const &, const bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > &);
+
+#endif

+ 43 - 0
include/igl/cross_field_mismatch.h

@@ -0,0 +1,43 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2014 Daniele Panozzo <daniele.panozzo@gmail.com>, Olga Diamanti <olga.diam@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_CROSS_FIELD_MISMATCH_H
+#define IGL_CROSS_FIELD_MISMATCH_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+namespace igl
+{
+  // Calculates the mismatch (integer), at each face edge, of a cross field defined on the mesh faces.
+  // The integer mismatch is a multiple of pi/2 that transforms the cross on one side of the edge to
+  // the cross on the other side. It represents the deviation from a Lie connection across the edge.
+
+  // Inputs:
+  //   V         #V by 3 eigen Matrix of mesh vertex 3D positions
+  //   F         #F by 3 eigen Matrix of face (quad) indices
+  //   PD1       #F by 3 eigen Matrix of the first per face cross field vector
+  //   PD2       #F by 3 eigen Matrix of the second per face cross field vector
+  //   isCombed  boolean, specifying whether the field is combed (i.e. matching has been precomputed.
+  //             If not, the field is combed first.
+  // Output:
+  //   mismatch  #F by 3 eigen Matrix containing the integer mismatch of the cross field
+  //             across all face edges
+  //
+
+  template <typename DerivedV, typename DerivedF, typename DerivedM>
+  IGL_INLINE void cross_field_mismatch(const Eigen::PlainObjectBase<DerivedV> &V,
+                                       const Eigen::PlainObjectBase<DerivedF> &F,
+                                       const Eigen::PlainObjectBase<DerivedV> &PD1,
+                                       const Eigen::PlainObjectBase<DerivedV> &PD2,
+                                       const bool isCombed,
+                                       Eigen::PlainObjectBase<DerivedM> &mismatch);
+}
+#ifndef IGL_STATIC_LIBRARY
+#include "cross_field_mismatch.cpp"
+#endif
+
+#endif

+ 0 - 142
include/igl/cross_field_missmatch.cpp

@@ -1,142 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2014 Daniele Panozzo <daniele.panozzo@gmail.com>, Olga Diamanti <olga.diam@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 "cross_field_missmatch.h"
-
-#include <cmath>
-#include <vector>
-#include <deque>
-#include <igl/comb_cross_field.h>
-#include <igl/per_face_normals.h>
-#include <igl/is_border_vertex.h>
-#include <igl/vertex_triangle_adjacency.h>
-#include <igl/triangle_triangle_adjacency.h>
-#include <igl/rotation_matrix_from_directions.h>
-#include <igl/PI.h>
-
-namespace igl {
-  template <typename DerivedV, typename DerivedF, typename DerivedM>
-  class MissMatchCalculator
-  {
-  public:
-
-    const Eigen::PlainObjectBase<DerivedV> &V;
-    const Eigen::PlainObjectBase<DerivedF> &F;
-    const Eigen::PlainObjectBase<DerivedV> &PD1;
-    const Eigen::PlainObjectBase<DerivedV> &PD2;
-    
-    DerivedV N;
-
-  private:
-    // internal
-    std::vector<bool> V_border; // bool
-    std::vector<std::vector<int> > VF;
-    std::vector<std::vector<int> > VFi;
-    
-    DerivedF TT;
-    DerivedF TTi;
-
-
-  private:
-    ///compute the mismatch between 2 faces
-    inline int MissMatchByCross(const int f0,
-                         const int f1)
-    {
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 1> dir0 = PD1.row(f0);
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 1> dir1 = PD1.row(f1);
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 1> n0 = N.row(f0);
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 1> n1 = N.row(f1);
-
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 1> dir1Rot = igl::rotation_matrix_from_directions(n1,n0)*dir1;
-      dir1Rot.normalize();
-
-      // TODO: this should be equivalent to the other code below, to check!
-      // Compute the angle between the two vectors
-      //    double a0 = atan2(dir0.dot(B2.row(f0)),dir0.dot(B1.row(f0)));
-      //    double a1 = atan2(dir1Rot.dot(B2.row(f0)),dir1Rot.dot(B1.row(f0)));
-      //
-      //    double angle_diff = a1-a0;   //VectToAngle(f0,dir1Rot);
-
-      double angle_diff = atan2(dir1Rot.dot(PD2.row(f0)),dir1Rot.dot(PD1.row(f0)));
-
-      //    std::cerr << "Dani: " << dir0(0) << " " << dir0(1) << " " << dir0(2) << " " << dir1Rot(0) << " " << dir1Rot(1) << " " << dir1Rot(2) << " " << angle_diff << std::endl;
-
-      double step=igl::PI/2.0;
-      int i=(int)std::floor((angle_diff/step)+0.5);
-      int k=0;
-      if (i>=0)
-        k=i%4;
-      else
-        k=(-(3*i))%4;
-      return k;
-    }
-
-
-public:
-  inline MissMatchCalculator(const Eigen::PlainObjectBase<DerivedV> &_V,
-                      const Eigen::PlainObjectBase<DerivedF> &_F,
-                      const Eigen::PlainObjectBase<DerivedV> &_PD1,
-                      const Eigen::PlainObjectBase<DerivedV> &_PD2
-                      ):
-  V(_V),
-  F(_F),
-  PD1(_PD1),
-  PD2(_PD2)
-  {
-    igl::per_face_normals(V,F,N);
-    V_border = igl::is_border_vertex(V,F);
-    igl::vertex_triangle_adjacency(V,F,VF,VFi);
-    igl::triangle_triangle_adjacency(F,TT,TTi);
-  }
-
-  inline void calculateMissmatch(Eigen::PlainObjectBase<DerivedM> &Handle_MMatch)
-  {
-    Handle_MMatch.setConstant(F.rows(),3,-1);
-    for (size_t i=0;i<F.rows();i++)
-    {
-      for (int j=0;j<3;j++)
-      {
-        if (((int)i)==TT(i,j) || TT(i,j) == -1)
-          Handle_MMatch(i,j)=0;
-        else
-          Handle_MMatch(i,j) = MissMatchByCross(i,TT(i,j));
-      }
-    }
-  }
-
-};
-}
-template <typename DerivedV, typename DerivedF, typename DerivedM>
-IGL_INLINE void igl::cross_field_missmatch(const Eigen::PlainObjectBase<DerivedV> &V,
-                                           const Eigen::PlainObjectBase<DerivedF> &F,
-                                           const Eigen::PlainObjectBase<DerivedV> &PD1,
-                                           const Eigen::PlainObjectBase<DerivedV> &PD2,
-                                           const bool isCombed,
-                                           Eigen::PlainObjectBase<DerivedM> &missmatch)
-{
-  DerivedV PD1_combed;
-  DerivedV PD2_combed;
-
-  if (!isCombed)
-    igl::comb_cross_field(V,F,PD1,PD2,PD1_combed,PD2_combed);
-  else
-  {
-    PD1_combed = PD1;
-    PD2_combed = PD2;
-  }
-  igl::MissMatchCalculator<DerivedV, DerivedF, DerivedM> sf(V, F, PD1_combed, PD2_combed);
-  sf.calculateMissmatch(missmatch);
-}
-
-#ifdef IGL_STATIC_LIBRARY
-// Explicit template instantiation
-template void igl::cross_field_missmatch<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(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<double, -1, 3, 0, -1, 3> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
-template void igl::cross_field_missmatch<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<double, -1, -1, 0, -1, -1> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
-template void igl::cross_field_missmatch<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(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<double, -1, -1, 0, -1, -1> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
-
-#endif

+ 76 - 0
include/igl/cumprod.cpp

@@ -0,0 +1,76 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2018 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/.
+#include "cumprod.h"
+#include <numeric>
+#include <iostream>
+
+template <typename DerivedX, typename DerivedY>
+IGL_INLINE void igl::cumprod(
+  const Eigen::MatrixBase<DerivedX > & X,
+  const int dim,
+  Eigen::PlainObjectBase<DerivedY > & Y)
+{
+  using namespace Eigen;
+  using namespace std;
+  Y.resizeLike(X);
+  // get number of columns (or rows)
+  int num_outer = (dim == 1 ? X.cols() : X.rows() );
+  // get number of rows (or columns)
+  int num_inner = (dim == 1 ? X.rows() : X.cols() );
+  // This has been optimized so that dim = 1 or 2 is roughly the same cost.
+  // (Optimizations assume ColMajor order)
+  if(dim == 1)
+  {
+#pragma omp parallel for
+    for(int o = 0;o<num_outer;o++)
+    {
+      typename DerivedX::Scalar prod = 1;
+      for(int i = 0;i<num_inner;i++)
+      {
+        prod *= X(i,o);
+        Y(i,o) = prod;
+      }
+    }
+  }else
+  {
+    for(int i = 0;i<num_inner;i++)
+    {
+      // Notice that it is *not* OK to put this above the inner loop
+      // Though here it doesn't seem to pay off...
+//#pragma omp parallel for
+      for(int o = 0;o<num_outer;o++)
+      {
+        if(i == 0)
+        {
+          Y(o,i) = X(o,i);
+        }else
+        {
+          Y(o,i) = Y(o,i-1) * X(o,i);
+        }
+      }
+    }
+  }
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template instantiation
+// generated by autoexplicit.sh
+template void igl::cumprod<Eigen::Matrix<double, 4, 1, 0, 4, 1>, Eigen::Matrix<double, 4, 1, 0, 4, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, 4, 1, 0, 4, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, 4, 1, 0, 4, 1> >&);
+// generated by autoexplicit.sh
+template void igl::cumprod<Eigen::Matrix<double, 1, 4, 1, 1, 4>, Eigen::Matrix<double, 1, 4, 1, 1, 4> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 4, 1, 1, 4> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 4, 1, 1, 4> >&);
+template void igl::cumprod<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+template void igl::cumprod<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
+template void igl::cumprod<Eigen::Matrix<double, 3, 1, 0, 3, 1>, Eigen::Matrix<double, 3, 1, 0, 3, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >&);
+template void igl::cumprod<Eigen::Matrix<unsigned long, 2, 1, 0, 2, 1>, Eigen::Matrix<unsigned long, 2, 1, 0, 2, 1> >(Eigen::MatrixBase<Eigen::Matrix<unsigned long, 2, 1, 0, 2, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<unsigned long, 2, 1, 0, 2, 1> >&);
+template void igl::cumprod<Eigen::Matrix<unsigned long, -1, 1, 0, -1, 1>, Eigen::Matrix<unsigned long, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<unsigned long, -1, 1, 0, -1, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<unsigned long, -1, 1, 0, -1, 1> >&);
+template void igl::cumprod<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+#ifdef WIN32
+template void igl::cumprod<class Eigen::Matrix<unsigned __int64, -1, 1, 0, -1, 1>, class Eigen::Matrix<unsigned __int64, -1, 1, 0, -1, 1>>(class Eigen::MatrixBase<class Eigen::Matrix<unsigned __int64, -1, 1, 0, -1, 1>> const &, int, class Eigen::PlainObjectBase<class Eigen::Matrix<unsigned __int64, -1, 1, 0, -1, 1>> &);
+template void igl::cumprod<class Eigen::Matrix<unsigned __int64, 2, 1, 0, 2, 1>, class Eigen::Matrix<unsigned __int64, 2, 1, 0, 2, 1>>(class Eigen::MatrixBase<class Eigen::Matrix<unsigned __int64, 2, 1, 0, 2, 1>> const &, int, class Eigen::PlainObjectBase<class Eigen::Matrix<unsigned __int64, 2, 1, 0, 2, 1>> &);
+#endif
+#endif

+ 44 - 0
include/igl/cumprod.h

@@ -0,0 +1,44 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2018 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_CUMPROD_H
+#define IGL_CUMPROD_H
+
+#include "igl_inline.h"
+#include <Eigen/Core>
+
+namespace igl
+{
+  // Computes a cumulative product of the columns of X, like matlab's `cumprod`.
+  //
+  // Templates:
+  //   DerivedX  Type of matrix X
+  //   DerivedY  Type of matrix Y
+  // Inputs:
+  //   X  m by n Matrix to be cumulatively multiplied.
+  //   dim  dimension to take cumulative product (1 or 2)
+  // Output:
+  //   Y  m by n Matrix containing cumulative product.
+  //
+  template <typename DerivedX, typename DerivedY>
+  IGL_INLINE void cumprod(
+    const Eigen::MatrixBase<DerivedX > & X,
+    const int dim,
+    Eigen::PlainObjectBase<DerivedY > & Y);
+  //template <typename DerivedX, typename DerivedY>
+  //IGL_INLINE void cumprod(
+  //  const Eigen::MatrixBase<DerivedX > & X,
+  //  Eigen::PlainObjectBase<DerivedY > & Y);
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "cumprod.cpp"
+#endif
+
+#endif
+
+

+ 4 - 0
include/igl/cumsum.cpp

@@ -59,6 +59,10 @@ IGL_INLINE void igl::cumsum(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
+// generated by autoexplicit.sh
+template void igl::cumsum<Eigen::Matrix<double, 4, 1, 0, 4, 1>, Eigen::Matrix<double, 4, 1, 0, 4, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, 4, 1, 0, 4, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, 4, 1, 0, 4, 1> >&);
+// generated by autoexplicit.sh
+template void igl::cumsum<Eigen::Matrix<double, 1, 4, 1, 1, 4>, Eigen::Matrix<double, 1, 4, 1, 1, 4> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 4, 1, 1, 4> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 4, 1, 1, 4> >&);
 template void igl::cumsum<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 template void igl::cumsum<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 template void igl::cumsum<Eigen::Matrix<double, 3, 1, 0, 3, 1>, Eigen::Matrix<double, 3, 1, 0, 3, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >&);

+ 13 - 33
include/igl/delaunay_triangulation.cpp

@@ -10,6 +10,7 @@
 #include "flip_edge.h"
 #include "lexicographic_triangulation.h"
 #include "unique_edge_map.h"
+#include "is_delaunay.h"
 
 #include <vector>
 #include <sstream>
@@ -20,9 +21,9 @@ template<
   typename InCircle,
   typename DerivedF>
 IGL_INLINE void igl::delaunay_triangulation(
-    const Eigen::PlainObjectBase<DerivedV>& V,
-    Orient2D orient2D,
-    InCircle incircle,
+    const Eigen::MatrixBase<DerivedV>& V,
+    const Orient2D orient2D,
+    const InCircle incircle,
     Eigen::PlainObjectBase<DerivedF>& F)
 {
   assert(V.cols() == 2);
@@ -36,43 +37,18 @@ IGL_INLINE void igl::delaunay_triangulation(
   }
   assert(F.cols() == 3);
 
-  Eigen::MatrixXi E;
-  Eigen::MatrixXi uE;
+  typedef Eigen::Matrix<typename DerivedF::Scalar,Eigen::Dynamic,2> MatrixX2I;
+  MatrixX2I E,uE;
   Eigen::VectorXi EMAP;
   std::vector<std::vector<Index> > uE2E;
   igl::unique_edge_map(F, E, uE, EMAP, uE2E);
 
-  auto is_delaunay = [&V,&F,&uE2E,num_faces,&incircle](size_t uei) {
-    auto& half_edges = uE2E[uei];
-    if (half_edges.size() != 2) {
-      throw "Cannot flip non-manifold or boundary edge";
-    }
-
-    const size_t f1 = half_edges[0] % num_faces;
-    const size_t f2 = half_edges[1] % num_faces;
-    const size_t c1 = half_edges[0] / num_faces;
-    const size_t c2 = half_edges[1] / num_faces;
-    assert(c1 < 3);
-    assert(c2 < 3);
-    assert(f1 != f2);
-    const size_t v1 = F(f1, (c1+1)%3);
-    const size_t v2 = F(f1, (c1+2)%3);
-    const size_t v4 = F(f1, c1);
-    const size_t v3 = F(f2, c2);
-    const Scalar p1[] = {V(v1, 0), V(v1, 1)};
-    const Scalar p2[] = {V(v2, 0), V(v2, 1)};
-    const Scalar p3[] = {V(v3, 0), V(v3, 1)};
-    const Scalar p4[] = {V(v4, 0), V(v4, 1)};
-    auto orientation = incircle(p1, p2, p4, p3);
-    return orientation <= 0;
-  };
-
   bool all_delaunay = false;
   while(!all_delaunay) {
     all_delaunay = true;
     for (size_t i=0; i<uE2E.size(); i++) {
       if (uE2E[i].size() == 2) {
-        if (!is_delaunay(i)) {
+        if (!is_delaunay(V,F,uE2E,incircle,i)) {
           all_delaunay = false;
           flip_edge(F, E, uE, EMAP, uE2E, i);
         }
@@ -82,5 +58,9 @@ IGL_INLINE void igl::delaunay_triangulation(
 }
 
 #ifdef IGL_STATIC_LIBRARY
-template void igl::delaunay_triangulation<Eigen::Matrix<double, -1, -1, 0, -1, -1>, short (*)(double const*, double const*, double const*), short (*)(double const*, double const*, double const*, double const*), Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, short (*)(double const*, double const*, double const*), short (*)(double const*, double const*, double const*, double const*), Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
-#endif
+// Explicit template instantiation
+template void igl::delaunay_triangulation<Eigen::Matrix<double, -1, -1, 0, -1, -1>, short (*)(double const*, double const*, double const*), short (*)(double const*, double const*, double const*, double const*), Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, short (*)(double const*, double const*, double const*), short (*)(double const*, double const*, double const*, double const*), Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+#ifdef WIN32
+template void igl::delaunay_triangulation<Eigen::Matrix<double, -1, -1, 0, -1, -1>, short (*)(double const * const, double const * const, double const * const), short(*)(double const * const, double const * const, double const * const, double const * const), Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const &, short(*)(double const * const, double const * const, double const * const), short(*)(double const * const, double const * const, double const * const, double const * const), Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > &);
+#endif
+#endif

+ 3 - 3
include/igl/delaunay_triangulation.h

@@ -37,9 +37,9 @@ namespace igl
     typename DerivedF
     >
   IGL_INLINE void delaunay_triangulation(
-      const Eigen::PlainObjectBase<DerivedV>& V,
-      Orient2D orient2D,
-      InCircle incircle,
+      const Eigen::MatrixBase<DerivedV>& V,
+      const Orient2D orient2D,
+      const InCircle incircle,
       Eigen::PlainObjectBase<DerivedF>& F);
 }
 

+ 9 - 5
include/igl/dihedral_angles.cpp

@@ -6,6 +6,9 @@
 // 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 "dihedral_angles.h"
+#include "edge_lengths.h"
+#include "face_areas.h"
+
 #include <cassert>
 
 template <
@@ -14,8 +17,8 @@ template <
   typename Derivedtheta,
   typename Derivedcos_theta>
 IGL_INLINE void igl::dihedral_angles(
-  Eigen::PlainObjectBase<DerivedV>& V,
-  Eigen::PlainObjectBase<DerivedT>& T,
+  const Eigen::PlainObjectBase<DerivedV>& V,
+  const Eigen::PlainObjectBase<DerivedT>& T,
   Eigen::PlainObjectBase<Derivedtheta>& theta,
   Eigen::PlainObjectBase<Derivedcos_theta>& cos_theta)
 {
@@ -34,8 +37,8 @@ template <
   typename Derivedtheta,
   typename Derivedcos_theta>
 IGL_INLINE void igl::dihedral_angles_intrinsic(
-  Eigen::PlainObjectBase<DerivedL>& L,
-  Eigen::PlainObjectBase<DerivedA>& A,
+  const Eigen::PlainObjectBase<DerivedL>& L,
+  const Eigen::PlainObjectBase<DerivedA>& A,
   Eigen::PlainObjectBase<Derivedtheta>& theta,
   Eigen::PlainObjectBase<Derivedcos_theta>& cos_theta)
 {
@@ -90,5 +93,6 @@ IGL_INLINE void igl::dihedral_angles_intrinsic(
 }
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
-template void igl::dihedral_angles_intrinsic<Eigen::Matrix<double, -1, 6, 0, -1, 6>, Eigen::Matrix<double, -1, 4, 0, -1, 4>, Eigen::Matrix<double, -1, 6, 0, -1, 6>, Eigen::Matrix<double, -1, 6, 0, -1, 6> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 6, 0, -1, 6> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 4, 0, -1, 4> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 6, 0, -1, 6> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 6, 0, -1, 6> >&);
+template void igl::dihedral_angles_intrinsic< Eigen::Matrix<double, -1, 6, 0, -1, 6>, Eigen::Matrix<double, -1, 4, 0, -1, 4>, Eigen::Matrix<double, -1, 6, 0, -1, 6>, Eigen::Matrix<double, -1, 6, 0, -1, 6> >(const Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 6, 0, -1, 6> >&, const Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 4, 0, -1, 4> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 6, 0, -1, 6> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 6, 0, -1, 6> >&);
+template void igl::dihedral_angles<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<double, -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> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 #endif

+ 4 - 4
include/igl/dihedral_angles.h

@@ -30,8 +30,8 @@ namespace igl
     typename Derivedtheta,
     typename Derivedcos_theta>
   IGL_INLINE void dihedral_angles(
-    Eigen::PlainObjectBase<DerivedV>& V,
-    Eigen::PlainObjectBase<DerivedT>& T,
+    const Eigen::PlainObjectBase<DerivedV>& V,
+    const Eigen::PlainObjectBase<DerivedT>& T,
     Eigen::PlainObjectBase<Derivedtheta>& theta,
     Eigen::PlainObjectBase<Derivedcos_theta>& cos_theta);
   template <
@@ -40,8 +40,8 @@ namespace igl
     typename Derivedtheta,
     typename Derivedcos_theta>
   IGL_INLINE void dihedral_angles_intrinsic(
-    Eigen::PlainObjectBase<DerivedL>& L,
-    Eigen::PlainObjectBase<DerivedA>& A,
+    const Eigen::PlainObjectBase<DerivedL>& L,
+    const Eigen::PlainObjectBase<DerivedA>& A,
     Eigen::PlainObjectBase<Derivedtheta>& theta,
     Eigen::PlainObjectBase<Derivedcos_theta>& cos_theta);
 

+ 3 - 4
include/igl/doublearea.cpp

@@ -231,13 +231,12 @@ IGL_INLINE void igl::doublearea_quad(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
-// generated by autoexplicit.sh
+template void igl::doublearea<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<double, -1, -1, 0, -1, -1>::Scalar, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
+template void igl::doublearea<Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
+template void igl::doublearea<Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> > const&, Eigen::Matrix<double, -1, -1, 1, -1, -1>::Scalar, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 template void igl::doublearea<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<float, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 1, 0, -1, 1> >&);
-// generated by autoexplicit.sh
 template void igl::doublearea<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
-// generated by autoexplicit.sh
 template void igl::doublearea<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 1, 0, -1, 1> >&);
-// generated by autoexplicit.sh
 template void igl::doublearea<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3>, Eigen::Matrix<float, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 1, 0, -1, 1> >&);
 template void igl::doublearea<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 template void igl::doublearea<Eigen::Matrix<float, 1, 3, 1, 1, 3>, Eigen::Matrix<float, 1, 3, 1, 1, 3>, Eigen::Matrix<float, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 1, 0, 1, 1> >(Eigen::MatrixBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&);

+ 1 - 1
include/igl/edge_collapse_is_valid.cpp

@@ -49,7 +49,7 @@ IGL_INLINE bool igl::edge_collapse_is_valid(
       const Eigen::MatrixXi & EI) 
     {
       vector<int> N,uN;
-      vector<int> V2Fe = circulation(e, ccw,F,E,EMAP,EF,EI);
+      vector<int> V2Fe = circulation(e, ccw,EMAP,EF,EI);
       for(auto f : V2Fe)
       {
         N.push_back(F(f,0));

+ 96 - 0
include/igl/edge_exists_near.cpp

@@ -0,0 +1,96 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2018 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/.
+#include "edge_exists_near.h"
+
+template <
+  typename DeriveduE,
+  typename DerivedEMAP,
+  typename uE2EType,
+  typename Index>
+IGL_INLINE bool igl::edge_exists_near(
+  const Eigen::MatrixBase<DeriveduE> & uE,
+  const Eigen::MatrixBase<DerivedEMAP> & EMAP,
+  const std::vector<std::vector< uE2EType> > & uE2E,
+  const Index & a,
+  const Index & b,
+  const Index & uei)
+{
+  std::vector<Index> face_queue;
+  face_queue.reserve(32);
+  std::vector<Index> pushed;
+  // 32 is faster than 8
+  pushed.reserve(32);
+  assert(a!=b);
+  // starting with the (2) faces incident on e, consider all faces
+  // incident on edges containing either a or b.
+  //
+  // face_queue  Queue containing faces incident on exactly one of a/b
+  // Using a vector seems mildly faster
+  assert(EMAP.size()%3 == 0);
+  const Index num_faces = EMAP.size()/3;
+  const Index f1 = uE2E[uei][0]%num_faces;
+  const Index f2 = uE2E[uei][1]%num_faces;
+  // map is faster than unordered_map here, and vector + brute force
+  // is_member check is even faster
+  face_queue.push_back(f1);
+  pushed.push_back(f1);
+  face_queue.push_back(f2);
+  pushed.push_back(f2);
+  while(!face_queue.empty())
+  {
+    const Index f = face_queue.back();
+    face_queue.pop_back();
+    // consider each edge of this face
+    for(int c = 0;c<3;c++)
+    {
+      // Unique edge id
+      const Index uec = EMAP(c*num_faces+f);
+      const Index s = uE(uec,0);
+      const Index d = uE(uec,1);
+      const bool ona = s == a || d == a;
+      const bool onb = s == b || d == b;
+      // Is this the edge we're looking for?
+      if(ona && onb)
+      {
+        return true;
+      }
+      // not incident on either?
+      if(!ona && !onb)
+      {
+        continue;
+      }
+      // loop over all incident half-edges
+      for(const auto & he : uE2E[uec])
+      {
+        // face of this he
+        const Index fhe = he%num_faces;
+        bool already_pushed = false;
+        for(const auto & fp : pushed)
+        {
+          if(fp == fhe)
+          {
+            already_pushed = true;
+            break;
+          }
+        }
+        if(!already_pushed)
+        {
+          pushed.push_back(fhe);
+          face_queue.push_back(fhe);
+        }
+      }
+    }
+  }
+  return false;
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template instantiation
+// generated by autoexplicit.sh
+template bool igl::edge_exists_near<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, int, int>(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, int const&, int const&, int const&);
+#endif 

+ 47 - 0
include/igl/edge_exists_near.h

@@ -0,0 +1,47 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2018 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_EDGE_EXISTS_NEAR_H
+#define IGL_EDGE_EXISTS_NEAR_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+#include <vector>
+namespace igl
+{
+  // Does edge (a,b) exist in the edges of all faces incident on
+  // existing unique edge uei.
+  //
+  // Inputs:
+  //   uE  #uE by 2 list of unique undirected edges
+  //   EMAP #F*3 list of indices into uE, mapping each directed edge to unique
+  //     undirected edge
+  //   uE2E  #uE list of lists of indices into E of coexisting edges
+  //   E  #F*3 by 2 list of half-edges
+  //   a  1st end-point of query edge
+  //   b  2nd end-point of query edge
+  //   uei  index into uE/uE2E of unique edge
+  // Returns true if edge exists near uei.
+  //
+  // See also: unique_edge_map
+  template <
+    typename DeriveduE,
+    typename DerivedEMAP,
+    typename uE2EType,
+    typename Index>
+  IGL_INLINE bool edge_exists_near(
+    const Eigen::MatrixBase<DeriveduE> & uE,
+    const Eigen::MatrixBase<DerivedEMAP> & EMAP,
+    const std::vector<std::vector< uE2EType> > & uE2E,
+    const Index & a,
+    const Index & b,
+    const Index & uei);
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "edge_exists_near.cpp"
+#endif
+#endif
+

+ 9 - 9
include/igl/edge_flaps.cpp

@@ -12,14 +12,14 @@
 
 IGL_INLINE void igl::edge_flaps(
   const Eigen::MatrixXi & F,
-  const Eigen::MatrixXi & E,
+  const Eigen::MatrixXi & uE,
   const Eigen::VectorXi & EMAP,
   Eigen::MatrixXi & EF,
   Eigen::MatrixXi & EI)
 {
   // Initialize to boundary value
-  EF.setConstant(E.rows(),2,-1);
-  EI.setConstant(E.rows(),2,-1);
+  EF.setConstant(uE.rows(),2,-1);
+  EI.setConstant(uE.rows(),2,-1);
   // loop over all faces
   for(int f = 0;f<F.rows();f++)
   {
@@ -29,13 +29,13 @@ IGL_INLINE void igl::edge_flaps(
       // get edge id
       const int e = EMAP(v*F.rows()+f);
       // See if this is left or right flap w.r.t. edge orientation
-      if( F(f,(v+1)%3) == E(e,0) && F(f,(v+2)%3) == E(e,1))
+      if( F(f,(v+1)%3) == uE(e,0) && F(f,(v+2)%3) == uE(e,1))
       {
         EF(e,0) = f;
         EI(e,0) = v;
       }else
       {
-        assert(F(f,(v+1)%3) == E(e,1) && F(f,(v+2)%3) == E(e,0));
+        assert(F(f,(v+1)%3) == uE(e,1) && F(f,(v+2)%3) == uE(e,0));
         EF(e,1) = f;
         EI(e,1) = v;
       }
@@ -45,16 +45,16 @@ IGL_INLINE void igl::edge_flaps(
 
 IGL_INLINE void igl::edge_flaps(
   const Eigen::MatrixXi & F,
-  Eigen::MatrixXi & E,
+  Eigen::MatrixXi & uE,
   Eigen::VectorXi & EMAP,
   Eigen::MatrixXi & EF,
   Eigen::MatrixXi & EI)
 {
   Eigen::MatrixXi allE;
   std::vector<std::vector<int> > uE2E;
-  igl::unique_edge_map(F,allE,E,EMAP,uE2E);
+  igl::unique_edge_map(F,allE,uE,EMAP,uE2E);
   // Const-ify to call overload
-  const auto & cE = E;
+  const auto & cuE = uE;
   const auto & cEMAP = EMAP;
-  return edge_flaps(F,cE,cEMAP,EF,EI);
+  return edge_flaps(F,cuE,cEMAP,EF,EI);
 }

+ 7 - 5
include/igl/edge_flaps.h

@@ -16,15 +16,17 @@ namespace igl
   //
   // Inputs:
   //   F  #F by 3 list of face indices
-  //   E  #E by 2 list of edge indices into V.
-  //   EMAP #F*3 list of indices into E, mapping each directed edge to unique
-  //     unique edge in E
+  //   uE  #uE by 2 list of edge indices into V.
+  //   EMAP #F*3 list of indices into uE, mapping each directed edge to unique
+  //     unique edge in uE
   // Outputs:
   //   EF  #E by 2 list of edge flaps, EF(e,0)=f means e=(i-->j) is the edge of
   //     F(f,:) opposite the vth corner, where EI(e,0)=v. Similarly EF(e,1) "
   //     e=(j->i)
   //   EI  #E by 2 list of edge flap corners (see above).
   //
+  // See also: unique_edge_map
+  //
   // TODO: This seems to be a duplicate of edge_topology.h
   // igl::edge_topology(V,F,etEV,etFE,etEF);
   // igl::edge_flaps(F,efE,efEMAP,efEF,efEI);
@@ -34,14 +36,14 @@ namespace igl
   // all(efEMAP(sub2ind(size(F),repmat(1:size(F,1),3,1)',repmat([1 2 3],size(F,1),1))) == etFE(:,[2 3 1]))
   IGL_INLINE void edge_flaps(
     const Eigen::MatrixXi & F,
-    const Eigen::MatrixXi & E,
+    const Eigen::MatrixXi & uE,
     const Eigen::VectorXi & EMAP,
     Eigen::MatrixXi & EF,
     Eigen::MatrixXi & EI);
   // Only faces as input
   IGL_INLINE void edge_flaps(
     const Eigen::MatrixXi & F,
-    Eigen::MatrixXi & E,
+    Eigen::MatrixXi & uE,
     Eigen::VectorXi & EMAP,
     Eigen::MatrixXi & EF,
     Eigen::MatrixXi & EI);

+ 2 - 0
include/igl/edge_lengths.cpp

@@ -22,6 +22,8 @@ IGL_INLINE void igl::edge_lengths(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
 // generated by autoexplicit.sh
+template void igl::edge_lengths<Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
+// generated by autoexplicit.sh
 template void igl::edge_lengths<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&);
 // generated by autoexplicit.sh
 template void igl::edge_lengths<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<float, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&);

+ 104 - 72
include/igl/embree/EmbreeIntersector.h

@@ -21,8 +21,8 @@
 #include <Eigen/Core>
 #include <Eigen/Geometry>
 
-#include <embree2/rtcore.h>
-#include <embree2/rtcore_ray.h>
+#include <embree3/rtcore.h>
+#include <embree3/rtcore_ray.h>
 #include <iostream>
 #include <vector>
 
@@ -177,7 +177,7 @@ namespace igl
       bool initialized;
 
       inline void createRay(
-        RTCRay& ray,
+        RTCRayHit& ray,
         const Eigen::RowVector3f& origin,
         const Eigen::RowVector3f& direction,
         float tnear,
@@ -199,29 +199,28 @@ namespace igl
   {
     // Keeps track of whether the **Global** Embree intersector has been
     // initialized. This should never been done at the global scope.
-    static bool EmbreeIntersector_inited = false;
+    static RTCDevice g_device = nullptr;
   }
 }
 
 inline void igl::embree::EmbreeIntersector::global_init()
 {
-  if(!EmbreeIntersector_inited)
+  if(!g_device)
   {
-    rtcInit();
-    if(rtcGetError() != RTC_NO_ERROR)
+    g_device = rtcNewDevice (NULL);
+    if(rtcGetDeviceError (g_device) != RTC_ERROR_NONE)
       std::cerr << "Embree: An error occurred while initializing embree core!" << std::endl;
 #ifdef IGL_VERBOSE
     else
       std::cerr << "Embree: core initialized." << std::endl;
 #endif
-    EmbreeIntersector_inited = true;
   }
 }
 
 inline void igl::embree::EmbreeIntersector::global_deinit()
 {
-  EmbreeIntersector_inited = false;
-  rtcExit();
+  rtcReleaseDevice (g_device);
+  g_device = nullptr;
 }
 
 inline igl::embree::EmbreeIntersector::EmbreeIntersector()
@@ -287,43 +286,49 @@ inline void igl::embree::EmbreeIntersector::init(
     return;
   }
 
+  RTCBuildQuality buildQuality = isStatic ? RTC_BUILD_QUALITY_HIGH : RTC_BUILD_QUALITY_MEDIUM;
+
   // create a scene
-  RTCSceneFlags flags = RTC_SCENE_ROBUST | RTC_SCENE_HIGH_QUALITY;
-  if(isStatic)
-    flags = flags | RTC_SCENE_STATIC;
-  scene = rtcNewScene(flags,RTC_INTERSECT1);
+  scene = rtcNewScene(g_device);
+  rtcSetSceneFlags(scene, RTC_SCENE_FLAG_ROBUST);
+  rtcSetSceneBuildQuality(scene, buildQuality);
 
   for(int g=0;g<(int)V.size();g++)
   {
     // create triangle mesh geometry in that scene
-    geomID = rtcNewTriangleMesh(scene,RTC_GEOMETRY_STATIC,F[g]->rows(),V[g]->rows(),1);
+    RTCGeometry geom_0 = rtcNewGeometry (g_device, RTC_GEOMETRY_TYPE_TRIANGLE);
+    rtcSetGeometryBuildQuality(geom_0,buildQuality);
+    rtcSetGeometryTimeStepCount(geom_0,1);
+    geomID = rtcAttachGeometry(scene,geom_0);
+    rtcReleaseGeometry(geom_0);
 
     // fill vertex buffer
-    vertices = (Vertex*)rtcMapBuffer(scene,geomID,RTC_VERTEX_BUFFER);
+    vertices = (Vertex*)rtcSetNewGeometryBuffer(geom_0,RTC_BUFFER_TYPE_VERTEX,0,RTC_FORMAT_FLOAT3,4*sizeof(float),V[g]->rows());
     for(int i=0;i<(int)V[g]->rows();i++)
     {
       vertices[i].x = (float)V[g]->coeff(i,0);
       vertices[i].y = (float)V[g]->coeff(i,1);
       vertices[i].z = (float)V[g]->coeff(i,2);
     }
-    rtcUnmapBuffer(scene,geomID,RTC_VERTEX_BUFFER);
+    
 
     // fill triangle buffer
-    triangles = (Triangle*) rtcMapBuffer(scene,geomID,RTC_INDEX_BUFFER);
+    triangles = (Triangle*) rtcSetNewGeometryBuffer(geom_0,RTC_BUFFER_TYPE_INDEX,0,RTC_FORMAT_UINT3,3*sizeof(int),F[g]->rows());
     for(int i=0;i<(int)F[g]->rows();i++)
     {
       triangles[i].v0 = (int)F[g]->coeff(i,0);
       triangles[i].v1 = (int)F[g]->coeff(i,1);
       triangles[i].v2 = (int)F[g]->coeff(i,2);
     }
-    rtcUnmapBuffer(scene,geomID,RTC_INDEX_BUFFER);
+    
 
-    rtcSetMask(scene,geomID,masks[g]);
+    rtcSetGeometryMask(geom_0,masks[g]);
+    rtcCommitGeometry(geom_0);
   }
 
-  rtcCommit(scene);
+  rtcCommitScene(scene);
 
-  if(rtcGetError() != RTC_NO_ERROR)
+  if(rtcGetDeviceError (g_device) != RTC_ERROR_NONE)
       std::cerr << "Embree: An error occurred while initializing the provided geometry!" << endl;
 #ifdef IGL_VERBOSE
   else
@@ -342,11 +347,11 @@ igl::embree::EmbreeIntersector
 
 void igl::embree::EmbreeIntersector::deinit()
 {
-  if(EmbreeIntersector_inited && scene)
+  if(g_device && scene)
   {
-    rtcDeleteScene(scene);
+    rtcReleaseScene(scene);
 
-    if(rtcGetError() != RTC_NO_ERROR)
+    if(rtcGetDeviceError (g_device) != RTC_ERROR_NONE)
     {
         std::cerr << "Embree: An error occurred while resetting!" << std::endl;
     }
@@ -367,23 +372,31 @@ inline bool igl::embree::EmbreeIntersector::intersectRay(
   float tfar,
   int mask) const
 {
-  RTCRay ray;
+  RTCRayHit ray; // EMBREE_FIXME: use RTCRay for occlusion rays
+  ray.ray.flags = 0;
   createRay(ray, origin,direction,tnear,tfar,mask);
 
   // shot ray
-  rtcIntersect(scene,ray);
+  {
+    RTCIntersectContext context;
+    rtcInitIntersectContext(&context);
+    rtcIntersect1(scene,&context,&ray);
+    ray.hit.Ng_x = -ray.hit.Ng_x; // EMBREE_FIXME: only correct for triangles,quads, and subdivision surfaces
+    ray.hit.Ng_y = -ray.hit.Ng_y;
+    ray.hit.Ng_z = -ray.hit.Ng_z;
+  }
 #ifdef IGL_VERBOSE
-  if(rtcGetError() != RTC_NO_ERROR)
+  if(rtcGetDeviceError (g_device) != RTC_ERROR_NONE)
       std::cerr << "Embree: An error occurred while resetting!" << std::endl;
 #endif
 
-  if((unsigned)ray.geomID != RTC_INVALID_GEOMETRY_ID)
+  if((unsigned)ray.hit.geomID != RTC_INVALID_GEOMETRY_ID)
   {
-    hit.id = ray.primID;
-    hit.gid = ray.geomID;
-    hit.u = ray.u;
-    hit.v = ray.v;
-    hit.t = ray.tfar;
+    hit.id = ray.hit.primID;
+    hit.gid = ray.hit.geomID;
+    hit.u = ray.hit.u;
+    hit.v = ray.hit.v;
+    hit.t = ray.ray.tfar;
     return true;
   }
 
@@ -419,6 +432,7 @@ inline bool igl::embree::EmbreeIntersector::intersectBeam(
   const float eps= 1e-5;
 
   Eigen::RowVector3f up(0,1,0);
+  if (direction.cross(up).norm() < eps) up = Eigen::RowVector3f(1,0,0);
   Eigen::RowVector3f offset = direction.cross(up).normalized();
 
   Eigen::Matrix3f rot = Eigen::AngleAxis<float>(2*3.14159265358979/samples,direction).toRotationMatrix();
@@ -462,22 +476,30 @@ igl::embree::EmbreeIntersector
   const double eps = FLOAT_EPS;
   double min_t = tnear;
   bool large_hits_warned = false;
-  RTCRay ray;
+  RTCRayHit ray; // EMBREE_FIXME: use RTCRay for occlusion rays
+  ray.ray.flags = 0;
   createRay(ray,origin,direction,tnear,tfar,mask);
 
   while(true)
   {
-    ray.tnear = min_t;
-    ray.tfar = tfar;
-    ray.geomID = RTC_INVALID_GEOMETRY_ID;
-    ray.primID = RTC_INVALID_GEOMETRY_ID;
-    ray.instID = RTC_INVALID_GEOMETRY_ID;
+    ray.ray.tnear = min_t;
+    ray.ray.tfar = tfar;
+    ray.hit.geomID = RTC_INVALID_GEOMETRY_ID;
+    ray.hit.primID = RTC_INVALID_GEOMETRY_ID;
+    ray.hit.instID[0] = RTC_INVALID_GEOMETRY_ID;
     num_rays++;
-    rtcIntersect(scene,ray);
-    if((unsigned)ray.geomID != RTC_INVALID_GEOMETRY_ID)
+    {
+      RTCIntersectContext context;
+      rtcInitIntersectContext(&context);
+      rtcIntersect1(scene,&context,&ray);
+      ray.hit.Ng_x = -ray.hit.Ng_x; // EMBREE_FIXME: only correct for triangles,quads, and subdivision surfaces
+      ray.hit.Ng_y = -ray.hit.Ng_y;
+      ray.hit.Ng_z = -ray.hit.Ng_z;
+    }
+    if((unsigned)ray.hit.geomID != RTC_INVALID_GEOMETRY_ID)
     {
       // Hit self again, progressively advance
-      if(ray.primID == last_id0 || ray.tfar <= min_t)
+      if(ray.hit.primID == last_id0 || ray.ray.tfar <= min_t)
       {
         // push min_t a bit more
         //double t_push = pow(2.0,self_hits-4)*(hit.t<eps?eps:hit.t);
@@ -492,23 +514,23 @@ igl::embree::EmbreeIntersector
       else
       {
         Hit hit;
-        hit.id = ray.primID;
-        hit.gid = ray.geomID;
-        hit.u = ray.u;
-        hit.v = ray.v;
-        hit.t = ray.tfar;
+        hit.id = ray.hit.primID;
+        hit.gid = ray.hit.geomID;
+        hit.u = ray.hit.u;
+        hit.v = ray.hit.v;
+        hit.t = ray.ray.tfar;
         hits.push_back(hit);
 #ifdef IGL_VERBOSE
         std::cerr<<"  t: "<<hit.t<<endl;
 #endif
         // Instead of moving origin, just change min_t. That way calculations
         // all use exactly same origin values
-        min_t = ray.tfar;
+        min_t = ray.ray.tfar;
 
         // reset t_scale
         self_hits = 0;
       }
-      last_id0 = ray.primID;
+      last_id0 = ray.hit.primID;
     }
     else
       break; // no more hits
@@ -544,18 +566,26 @@ inline bool
 igl::embree::EmbreeIntersector
 ::intersectSegment(const Eigen::RowVector3f& a, const Eigen::RowVector3f& ab, Hit &hit, int mask) const
 {
-  RTCRay ray;
+  RTCRayHit ray; // EMBREE_FIXME: use RTCRay for occlusion rays
+  ray.ray.flags = 0;
   createRay(ray,a,ab,0,1.0,mask);
 
-  rtcIntersect(scene,ray);
+  {
+    RTCIntersectContext context;
+    rtcInitIntersectContext(&context);
+    rtcIntersect1(scene,&context,&ray);
+    ray.hit.Ng_x = -ray.hit.Ng_x; // EMBREE_FIXME: only correct for triangles,quads, and subdivision surfaces
+    ray.hit.Ng_y = -ray.hit.Ng_y;
+    ray.hit.Ng_z = -ray.hit.Ng_z;
+  }
 
-  if((unsigned)ray.geomID != RTC_INVALID_GEOMETRY_ID)
+  if((unsigned)ray.hit.geomID != RTC_INVALID_GEOMETRY_ID)
   {
-    hit.id = ray.primID;
-    hit.gid = ray.geomID;
-    hit.u = ray.u;
-    hit.v = ray.v;
-    hit.t = ray.tfar;
+    hit.id = ray.hit.primID;
+    hit.gid = ray.hit.geomID;
+    hit.u = ray.hit.u;
+    hit.v = ray.hit.v;
+    hit.t = ray.ray.tfar;
     return true;
   }
 
@@ -564,21 +594,23 @@ igl::embree::EmbreeIntersector
 
 inline void
 igl::embree::EmbreeIntersector
-::createRay(RTCRay& ray, const Eigen::RowVector3f& origin, const Eigen::RowVector3f& direction, float tnear, float tfar, int mask) const
+::createRay(RTCRayHit& ray, const Eigen::RowVector3f& origin, const Eigen::RowVector3f& direction, float tnear, float tfar, int mask) const
 {
-  ray.org[0] = origin[0];
-  ray.org[1] = origin[1];
-  ray.org[2] = origin[2];
-  ray.dir[0] = direction[0];
-  ray.dir[1] = direction[1];
-  ray.dir[2] = direction[2];
-  ray.tnear = tnear;
-  ray.tfar = tfar;
-  ray.geomID = RTC_INVALID_GEOMETRY_ID;
-  ray.primID = RTC_INVALID_GEOMETRY_ID;
-  ray.instID = RTC_INVALID_GEOMETRY_ID;
-  ray.mask = mask;
-  ray.time = 0.0f;
+  ray.ray.org_x = origin[0];
+  ray.ray.org_y = origin[1];
+  ray.ray.org_z = origin[2];
+  ray.ray.dir_x = direction[0];
+  ray.ray.dir_y = direction[1];
+  ray.ray.dir_z = direction[2];
+  ray.ray.tnear = tnear;
+  ray.ray.tfar = tfar;
+  ray.ray.id = RTC_INVALID_GEOMETRY_ID;
+  ray.ray.mask = mask;
+  ray.ray.time = 0.0f;
+
+  ray.hit.geomID = RTC_INVALID_GEOMETRY_ID;
+  ray.hit.instID[0] = RTC_INVALID_GEOMETRY_ID;
+  ray.hit.primID = RTC_INVALID_GEOMETRY_ID;
 }
 
 #endif //EMBREE_INTERSECTOR_H

+ 7 - 8
include/igl/find_cross_field_singularities.cpp

@@ -9,11 +9,10 @@
 #include "find_cross_field_singularities.h"
 
 #include <vector>
-#include <igl/cross_field_missmatch.h>
+#include <igl/cross_field_mismatch.h>
 #include <igl/is_border_vertex.h>
 #include <igl/vertex_triangle_adjacency.h>
 #include <igl/is_border_vertex.h>
-#include <igl/cross_field_missmatch.h>
 
 
 template <typename DerivedV, typename DerivedF, typename DerivedM, typename DerivedO>
@@ -38,7 +37,7 @@ IGL_INLINE void igl::find_cross_field_singularities(const Eigen::PlainObjectBase
     if (V_border[vid])
       continue;
 
-    int missmatch=0;
+    int mismatch=0;
     for (unsigned int i=0;i<VF[vid].size();i++)
     {
       // look for the vertex
@@ -48,12 +47,12 @@ IGL_INLINE void igl::find_cross_field_singularities(const Eigen::PlainObjectBase
           j=z;
       assert(j!=-1);
 
-      missmatch+=Handle_MMatch(VF[vid][i],j);
+      mismatch+=Handle_MMatch(VF[vid][i],j);
     }
-    missmatch=missmatch%4;
+    mismatch=mismatch%4;
 
-    isSingularity(vid)=(missmatch!=0);
-    singularityIndex(vid)=missmatch;
+    isSingularity(vid)=(mismatch!=0);
+    singularityIndex(vid)=mismatch;
   }
 
 
@@ -70,7 +69,7 @@ IGL_INLINE void igl::find_cross_field_singularities(const Eigen::PlainObjectBase
 {
   Eigen::Matrix<typename DerivedF::Scalar, Eigen::Dynamic, 3> Handle_MMatch;
 
-  igl::cross_field_missmatch(V, F, PD1, PD2, isCombed, Handle_MMatch);
+  igl::cross_field_mismatch(V, F, PD1, PD2, isCombed, Handle_MMatch);
   igl::find_cross_field_singularities(V, F, Handle_MMatch, isSingularity, singularityIndex);
 }
 

+ 3 - 3
include/igl/find_cross_field_singularities.h

@@ -18,7 +18,7 @@ namespace igl
   // Inputs:
   //   V                #V by 3 eigen Matrix of mesh vertex 3D positions
   //   F                #F by 3 eigen Matrix of face (quad) indices
-  //   Handle_MMatch    #F by 3 eigen Matrix containing the integer missmatch of the cross field
+  //   mismatch         #F by 3 eigen Matrix containing the integer mismatch of the cross field
   //                    across all face edges
   // Output:
   //   isSingularity    #V by 1 boolean eigen Vector indicating the presence of a singularity on a vertex
@@ -27,11 +27,11 @@ namespace igl
   template <typename DerivedV, typename DerivedF, typename DerivedM, typename DerivedO>
   IGL_INLINE void find_cross_field_singularities(const Eigen::PlainObjectBase<DerivedV> &V,
                                                  const Eigen::PlainObjectBase<DerivedF> &F,
-                                                 const Eigen::PlainObjectBase<DerivedM> &Handle_MMatch,
+                                                 const Eigen::PlainObjectBase<DerivedM> &mismatch,
                                                  Eigen::PlainObjectBase<DerivedO> &isSingularity,
                                                  Eigen::PlainObjectBase<DerivedO> &singularityIndex);
 
-  // Wrapper that calculates the missmatch if it is not provided.
+  // Wrapper that calculates the mismatch if it is not provided.
   // Note that the field in PD1 and PD2 MUST BE combed (see igl::comb_cross_field).
   // Inputs:
   //   V                #V by 3 eigen Matrix of mesh vertex 3D positions

+ 16 - 1
include/igl/flip_edge.cpp

@@ -25,6 +25,14 @@ IGL_INLINE void igl::flip_edge(
   typedef typename DerivedF::Scalar Index;
   const size_t num_faces = F.rows();
   assert(F.cols() == 3);
+  // Edge to flip [v1,v2] --> [v3,v4]
+  // Before:
+  // F(f1,:) = [v1,v2,v4] // in some cyclic order
+  // F(f2,:) = [v1,v3,v2] // in some cyclic order
+  // After: 
+  // F(f1,:) = [v1,v3,v4] // in *this* order 
+  // F(f2,:) = [v2,v4,v3] // in *this* order
+  //
   //          v1                 v1
   //          /|\                / \
   //         / | \              /f1 \
@@ -149,5 +157,12 @@ IGL_INLINE void igl::flip_edge(
 
 
 #ifdef IGL_STATIC_LIBRARY
+// Explicit template instantiation
+// generated by autoexplicit.sh
+template void igl::flip_edge<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, int>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, unsigned long);
 template void igl::flip_edge<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>, int>(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> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, unsigned long);
-#endif
+#ifdef WIN32
+template void igl::flip_edge<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>, int>(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> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, unsigned __int64);
+template void igl::flip_edge<class Eigen::Matrix<int,-1,-1,0,-1,-1>,class Eigen::Matrix<int,-1,2,0,-1,2>,class Eigen::Matrix<int,-1,2,0,-1,2>,class Eigen::Matrix<int,-1,1,0,-1,1>,int>(class Eigen::PlainObjectBase<class Eigen::Matrix<int,-1,-1,0,-1,-1> > &,class Eigen::PlainObjectBase<class Eigen::Matrix<int,-1,2,0,-1,2> > &,class Eigen::PlainObjectBase<class Eigen::Matrix<int,-1,2,0,-1,2> > &,class Eigen::PlainObjectBase<class Eigen::Matrix<int,-1,1,0,-1,1> > &,class std::vector<class std::vector<int,class std::allocator<int> >,class std::allocator<class std::vector<int,class std::allocator<int> > > > &,unsigned __int64);
+#endif
+#endif

+ 56 - 67
include/igl/grad.cpp

@@ -15,10 +15,12 @@
 #include "doublearea.h"
 
 template <typename DerivedV, typename DerivedF>
-IGL_INLINE void grad_tet(const Eigen::PlainObjectBase<DerivedV>&V,
-                     const Eigen::PlainObjectBase<DerivedF>&T,
-                            Eigen::SparseMatrix<typename DerivedV::Scalar> &G,
-                            bool uniform) {
+IGL_INLINE void grad_tet(
+  const Eigen::MatrixBase<DerivedV>&V,
+  const Eigen::MatrixBase<DerivedF>&T,
+  Eigen::SparseMatrix<typename DerivedV::Scalar> &G,
+  bool uniform) 
+{
   using namespace Eigen;
   assert(T.cols() == 4);
   const int n = V.rows(); int m = T.rows();
@@ -116,15 +118,22 @@ IGL_INLINE void grad_tet(const Eigen::PlainObjectBase<DerivedV>&V,
 }
 
 template <typename DerivedV, typename DerivedF>
-IGL_INLINE void grad_tri(const Eigen::PlainObjectBase<DerivedV>&V,
-                     const Eigen::PlainObjectBase<DerivedF>&F,
-                    Eigen::SparseMatrix<typename DerivedV::Scalar> &G,
-                    bool uniform)
+IGL_INLINE void grad_tri(
+  const Eigen::MatrixBase<DerivedV>&V,
+  const Eigen::MatrixBase<DerivedF>&F,
+  Eigen::SparseMatrix<typename DerivedV::Scalar> &G,
+  bool uniform)
 {
+  // Number of faces
+  const int m = F.rows();
+  // Number of vertices
+  const int nv = V.rows();
+  // Number of dimensions
+  const int dims = V.cols();
   Eigen::Matrix<typename DerivedV::Scalar,Eigen::Dynamic,3>
-    eperp21(F.rows(),3), eperp13(F.rows(),3);
+    eperp21(m,3), eperp13(m,3);
 
-  for (int i=0;i<F.rows();++i)
+  for (int i=0;i<m;++i)
   {
     // renaming indices of vertices of triangles for convenience
     int i1 = F(i,0);
@@ -132,10 +141,14 @@ IGL_INLINE void grad_tri(const Eigen::PlainObjectBase<DerivedV>&V,
     int i3 = F(i,2);
 
     // #F x 3 matrices of triangle edge vectors, named after opposite vertices
-    Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v32 = V.row(i3) - V.row(i2);
-    Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v13 = V.row(i1) - V.row(i3);
-    Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v21 = V.row(i2) - V.row(i1);
-    Eigen::Matrix<typename DerivedV::Scalar, 1, 3> n = v32.cross(v13);
+    typedef Eigen::Matrix<typename DerivedV::Scalar, 1, 3> RowVector3S;
+    RowVector3S v32 = RowVector3S::Zero(1,3);
+    RowVector3S v13 = RowVector3S::Zero(1,3);
+    RowVector3S v21 = RowVector3S::Zero(1,3);
+    v32.head(V.cols()) = V.row(i3) - V.row(i2);
+    v13.head(V.cols()) = V.row(i1) - V.row(i3);
+    v21.head(V.cols()) = V.row(i2) - V.row(i1);
+    RowVector3S n = v32.cross(v13);
     // area of parallelogram is twice area of triangle
     // area of parallelogram is || v1 x v2 ||
     // This does correct l2 norm of rows, so that it contains #F list of twice
@@ -174,70 +187,46 @@ IGL_INLINE void grad_tri(const Eigen::PlainObjectBase<DerivedV>&V,
     eperp13.row(i) *= norm13 / dblA;
   }
 
-  std::vector<int> rs;
-  rs.reserve(F.rows()*4*3);
-  std::vector<int> cs;
-  cs.reserve(F.rows()*4*3);
-  std::vector<double> vs;
-  vs.reserve(F.rows()*4*3);
-
-  // row indices
-  for(int r=0;r<3;r++)
+  // create sparse gradient operator matrix
+  G.resize(dims*m,nv);
+  std::vector<Eigen::Triplet<typename DerivedV::Scalar> > Gijv;
+  Gijv.reserve(4*dims*m);
+  for(int f = 0;f<F.rows();f++)
   {
-    for(int j=0;j<4;j++)
+    for(int d = 0;d<dims;d++)
     {
-      for(int i=r*F.rows();i<(r+1)*F.rows();i++) rs.push_back(i);
+      Gijv.emplace_back(f+d*m,F(f,1), eperp13(f,d));
+      Gijv.emplace_back(f+d*m,F(f,0),-eperp13(f,d));
+      Gijv.emplace_back(f+d*m,F(f,2), eperp21(f,d));
+      Gijv.emplace_back(f+d*m,F(f,0),-eperp21(f,d));
     }
   }
-
-  // column indices
-  for(int r=0;r<3;r++)
-  {
-    for(int i=0;i<F.rows();i++) cs.push_back(F(i,1));
-    for(int i=0;i<F.rows();i++) cs.push_back(F(i,0));
-    for(int i=0;i<F.rows();i++) cs.push_back(F(i,2));
-    for(int i=0;i<F.rows();i++) cs.push_back(F(i,0));
-  }
-
-  // values
-  for(int i=0;i<F.rows();i++) vs.push_back(eperp13(i,0));
-  for(int i=0;i<F.rows();i++) vs.push_back(-eperp13(i,0));
-  for(int i=0;i<F.rows();i++) vs.push_back(eperp21(i,0));
-  for(int i=0;i<F.rows();i++) vs.push_back(-eperp21(i,0));
-  for(int i=0;i<F.rows();i++) vs.push_back(eperp13(i,1));
-  for(int i=0;i<F.rows();i++) vs.push_back(-eperp13(i,1));
-  for(int i=0;i<F.rows();i++) vs.push_back(eperp21(i,1));
-  for(int i=0;i<F.rows();i++) vs.push_back(-eperp21(i,1));
-  for(int i=0;i<F.rows();i++) vs.push_back(eperp13(i,2));
-  for(int i=0;i<F.rows();i++) vs.push_back(-eperp13(i,2));
-  for(int i=0;i<F.rows();i++) vs.push_back(eperp21(i,2));
-  for(int i=0;i<F.rows();i++) vs.push_back(-eperp21(i,2));
-
-  // create sparse gradient operator matrix
-  G.resize(3*F.rows(),V.rows());
-  std::vector<Eigen::Triplet<typename DerivedV::Scalar> > triplets;
-  for (int i=0;i<(int)vs.size();++i)
-  {
-    triplets.push_back(Eigen::Triplet<typename DerivedV::Scalar>(rs[i],cs[i],vs[i]));
-  }
-  G.setFromTriplets(triplets.begin(), triplets.end());
+  G.setFromTriplets(Gijv.begin(), Gijv.end());
 }
 
 template <typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::grad(const Eigen::PlainObjectBase<DerivedV>&V,
-                     const Eigen::PlainObjectBase<DerivedF>&F,
-                    Eigen::SparseMatrix<typename DerivedV::Scalar> &G,
-                    bool uniform)
+IGL_INLINE void igl::grad(
+  const Eigen::MatrixBase<DerivedV>&V,
+  const Eigen::MatrixBase<DerivedF>&F,
+  Eigen::SparseMatrix<typename DerivedV::Scalar> &G,
+  bool uniform)
 {
   assert(F.cols() == 3 || F.cols() == 4);
-  if (F.cols() == 3)
-    return grad_tri(V,F,G,uniform);
-  if (F.cols() == 4)
-    return grad_tet(V,F,G,uniform);
+  switch(F.cols())
+  {
+    case 3:
+      return grad_tri(V,F,G,uniform);
+    case 4:
+      return grad_tet(V,F,G,uniform);
+    default:
+      assert(false);
+  }
 }
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
-template void igl::grad<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::SparseMatrix<Eigen::Matrix<double, -1, -1, 0, -1, -1>::Scalar, 0, int>&, bool);
-template void igl::grad<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::SparseMatrix<Eigen::Matrix<double, -1, 3, 0, -1, 3>::Scalar, 0, int>&, bool);
+// generated by autoexplicit.sh
+template void igl::grad<Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<Eigen::Matrix<double, -1, 2, 0, -1, 2>::Scalar, 0, int>&, bool);
+template void igl::grad<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<Eigen::Matrix<double, -1, -1, 0, -1, -1>::Scalar, 0, int>&, bool);
+template void igl::grad<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::SparseMatrix<Eigen::Matrix<double, -1, 3, 0, -1, 3>::Scalar, 0, int>&, bool);
 #endif

+ 8 - 7
include/igl/grad.h

@@ -5,8 +5,8 @@
 // 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_GRAD_MAT_H
-#define IGL_GRAD_MAT_H
+#ifndef IGL_GRAD_H
+#define IGL_GRAD_H
 #include "igl_inline.h"
 
 #include <Eigen/Core>
@@ -33,11 +33,12 @@ namespace igl {
   // i, and A is the area of triangle (i,j,k). ^R90 represent a rotation of
   // 90 degrees
   //
-template <typename DerivedV, typename DerivedF>
-IGL_INLINE void grad(const Eigen::PlainObjectBase<DerivedV>&V,
-                     const Eigen::PlainObjectBase<DerivedF>&F,
-                    Eigen::SparseMatrix<typename DerivedV::Scalar> &G,
-                    bool uniform = false);
+  template <typename DerivedV, typename DerivedF>
+  IGL_INLINE void grad(
+    const Eigen::MatrixBase<DerivedV>&V,
+    const Eigen::MatrixBase<DerivedF>&F,
+    Eigen::SparseMatrix<typename DerivedV::Scalar> &G,
+    bool uniform = false);
 }
 #ifndef IGL_STATIC_LIBRARY
 #  include "grad.cpp"

+ 69 - 0
include/igl/grad_intrinsic.cpp

@@ -0,0 +1,69 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2018 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/.
+#include "grad_intrinsic.h"
+#include "grad.h"
+
+template <typename Derivedl, typename DerivedF, typename Gtype>
+IGL_INLINE void igl::grad_intrinsic(
+  const Eigen::MatrixBase<Derivedl>&l,
+  const Eigen::MatrixBase<DerivedF>&F,
+  Eigen::SparseMatrix<Gtype> &G)
+{
+  assert(F.cols() ==3 && "Only triangles supported");
+  // number of vertices
+  const int n = F.maxCoeff()+1;
+  // number of faces
+  const int m = F.rows();
+  typedef Eigen::Matrix<Gtype,Eigen::Dynamic,2> MatrixX2S;
+  MatrixX2S V2 = MatrixX2S::Zero(3*m,2);
+  //     1=[x,y]
+  //     /\
+  // l3 /   \ l2
+  //   /      \
+  //  /         \
+  // 2-----------3
+  //       l1
+  //
+  // x = (l2²-l1²-l3²)/(-2*l1)
+  // y = sqrt(l3² - x²)
+  //
+  //
+  // Place 3rd vertex at [l(:,1) 0]
+  V2.block(2*m,0,m,1) = l.col(0);
+  // Place second vertex at [0 0]
+  // Place third vertex at [x y]
+  V2.block(0,0,m,1) = 
+    (l.col(1).cwiseAbs2()-l.col(0).cwiseAbs2()-l.col(2).cwiseAbs2()).array()/
+    (-2.*l.col(0)).array();
+  V2.block(0,1,m,1) = 
+    (l.col(2).cwiseAbs2() - V2.block(0,0,m,1).cwiseAbs2()).array().sqrt();
+  DerivedF F2(F.rows(),F.cols());
+  std::vector<Eigen::Triplet<Gtype> > Pijv;
+  Pijv.reserve(F.size());
+  for(int f = 0;f<m;f++)
+  {
+    for(int c = 0;c<F.cols();c++)
+    {
+      F2(f,c) = f+c*m;
+      Pijv.emplace_back(F2(f,c),F(f,c),1);
+    }
+  }
+  Eigen::SparseMatrix<Gtype> P(m*3,n);
+  P.setFromTriplets(Pijv.begin(),Pijv.end());
+  Eigen::SparseMatrix<Gtype> G2;
+  grad(V2,F2,G2);
+  G = G2*P;
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template instantiation
+// generated by autoexplicit.sh
+template void igl::grad_intrinsic<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double>(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<double, 0, int>&);
+// generated by autoexplicit.sh
+template void igl::grad_intrinsic<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<double, 0, int>&);
+#endif

+ 35 - 0
include/igl/grad_intrinsic.h

@@ -0,0 +1,35 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2018 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_GRAD_INTRINSIC_H
+#define IGL_GRAD_INTRINSIC_H
+#include "igl_inline.h"
+
+#include <Eigen/Core>
+#include <Eigen/Sparse>
+
+namespace igl {
+  // GRAD_INTRINSIC Construct an intrinsic gradient operator.
+  //
+  // Inputs:
+  //  l  #F by 3 list of edge lengths
+  //  F  #F by 3 list of triangle indices into some vertex list V
+  // Outputs:
+  //  G  #F*2 by #V gradient matrix: G=[Gx;Gy] where x runs along the 23 edge and
+  //    y runs in the counter-clockwise 90° rotation.
+  template <typename Derivedl, typename DerivedF, typename Gtype>
+  IGL_INLINE void grad_intrinsic(
+    const Eigen::MatrixBase<Derivedl>&l,
+    const Eigen::MatrixBase<DerivedF>&F,
+    Eigen::SparseMatrix<Gtype> &G);
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "grad_intrinsic.cpp"
+#endif
+
+#endif
+

+ 22 - 12
include/igl/grid.cpp

@@ -6,6 +6,7 @@
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can 
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "grid.h"
+#include <cassert>
 
 template <
   typename Derivedres,
@@ -16,23 +17,30 @@ IGL_INLINE void igl::grid(
 {
   using namespace Eigen;
   typedef typename DerivedGV::Scalar Scalar;
-  GV.resize(res(0)*res(1)*res(2),3);
-  for(int zi = 0;zi<res(2);zi++)
+  GV.resize(res.array().prod(),res.size());
+  const auto lerp = 
+    [&res](const Scalar di, const int d)->Scalar{return di/(Scalar)(res(d)-1);};
+  int gi = 0;
+  Derivedres sub;
+  sub.resizeLike(res);
+  sub.setConstant(0);
+  for(int gi = 0;gi<GV.rows();gi++)
   {
-    const auto lerp = 
-      [&](const Scalar di, const int d)->Scalar{return di/(Scalar)(res(d)-1);};
-    const Scalar z = lerp(zi,2);
-    for(int yi = 0;yi<res(1);yi++)
+    // omg, I'm implementing addition...
+    for(int c = 0;c<res.size()-1;c++)
     {
-      const Scalar y = lerp(yi,1);
-      for(int xi = 0;xi<res(0);xi++)
+      if(sub(c)>=res(c))
       {
-        const Scalar x = lerp(xi,0);
-        const int gi = xi+res(0)*(yi + res(1)*zi);
-        GV.row(gi) = 
-          Eigen::Matrix<Scalar,1,3>(x,y,z);
+        sub(c) = 0;
+        // roll over
+        sub(c+1)++;
       }
     }
+    for(int c = 0;c<res.size();c++)
+    {
+      GV(gi,c) = lerp(sub(c),c);
+    }
+    sub(0)++;
   }
 }
 
@@ -40,6 +48,8 @@ IGL_INLINE void igl::grid(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
 // generated by autoexplicit.sh
+template void igl::grid<Eigen::Matrix<int, 2, 1, 0, 2, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<int, 2, 1, 0, 2, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+// generated by autoexplicit.sh
 template void igl::grid<Eigen::Matrix<int, 1, 3, 1, 1, 3>, Eigen::Matrix<float, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<int, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&);
 // generated by autoexplicit.sh
 template void igl::grid<Eigen::Matrix<int, 3, 1, 0, 3, 1>, Eigen::Matrix<float, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<int, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&);

+ 3 - 2
include/igl/grid.h

@@ -1,6 +1,7 @@
 // This file is part of libigl, a simple c++ geometry processing library.
 // 
 // Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+// Copyright (C) 2018 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 
@@ -15,9 +16,9 @@ namespace igl
   // `igl::marching_cubes`
   //
   // Inputs:
-  //   res  3-long list of number of vertices along the x y and z dimensions
+  //   res  #res list of number of vertices along each dimension
   // Outputs:
-  //   GV  res(0)*res(1)*res(2) by 3 list of mesh vertex positions.
+  //   GV  res.array().prod() by #res list of mesh vertex positions.
   //   
   template <
     typename Derivedres,

+ 159 - 0
include/igl/heat_geodesics.cpp

@@ -0,0 +1,159 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2018 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/.
+
+#include "heat_geodesics.h"
+#include "grad.h"
+#include "doublearea.h"
+#include "cotmatrix.h"
+#include "intrinsic_delaunay_cotmatrix.h"
+#include "massmatrix.h"
+#include "massmatrix_intrinsic.h"
+#include "grad_intrinsic.h"
+#include "boundary_facets.h"
+#include "unique.h"
+#include "slice.h"
+#include "avg_edge_length.h"
+
+
+template < typename DerivedV, typename DerivedF, typename Scalar >
+IGL_INLINE bool igl::heat_geodesics_precompute(
+  const Eigen::MatrixBase<DerivedV> & V,
+  const Eigen::MatrixBase<DerivedF> & F,
+  HeatGeodesicsData<Scalar> & data)
+{
+  // default t value
+  const Scalar h = avg_edge_length(V,F);
+  const Scalar t = h*h;
+  return heat_geodesics_precompute(V,F,t,data);
+}
+
+template < typename DerivedV, typename DerivedF, typename Scalar >
+IGL_INLINE bool igl::heat_geodesics_precompute(
+  const Eigen::MatrixBase<DerivedV> & V,
+  const Eigen::MatrixBase<DerivedF> & F,
+  const Scalar t,
+  HeatGeodesicsData<Scalar> & data)
+{
+  typedef Eigen::Matrix<Scalar,Eigen::Dynamic,1> VectorXS;
+  typedef Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> MatrixXS;
+  Eigen::SparseMatrix<Scalar> L,M;
+  Eigen::Matrix<Scalar,Eigen::Dynamic,3> l_intrinsic;
+  DerivedF F_intrinsic;
+  VectorXS dblA;
+  if(data.use_intrinsic_delaunay)
+  {
+    igl::intrinsic_delaunay_cotmatrix(V,F,L,l_intrinsic,F_intrinsic);
+    igl::massmatrix_intrinsic(l_intrinsic,F_intrinsic,MASSMATRIX_TYPE_DEFAULT,M);
+    igl::doublearea(l_intrinsic,0,dblA);
+    igl::grad_intrinsic(l_intrinsic,F_intrinsic,data.Grad);
+  }else
+  {
+    igl::cotmatrix(V,F,L);
+    igl::massmatrix(V,F,MASSMATRIX_TYPE_DEFAULT,M);
+    igl::doublearea(V,F,dblA);
+    igl::grad(V,F,data.Grad);
+  }
+  // div
+  assert(F.cols() == 3 && "Only triangles are supported");
+  // number of gradient components
+  data.ng = data.Grad.rows() / F.rows();
+  assert(data.ng == 3 || data.ng == 2);
+  data.Div = -0.25*data.Grad.transpose()*dblA.replicate(data.ng,1).asDiagonal();
+
+  Eigen::SparseMatrix<Scalar> Q = M - t*L;
+  Eigen::MatrixXi O;
+  igl::boundary_facets(F,O);
+  igl::unique(O,data.b);
+  {
+    Eigen::SparseMatrix<Scalar> _;
+    if(!igl::min_quad_with_fixed_precompute(
+      Q,Eigen::VectorXi(),_,true,data.Neumann))
+    {
+      return false;
+    }
+    // Only need if there's a boundary
+    if(data.b.size()>0)
+    {
+      if(!igl::min_quad_with_fixed_precompute(Q,data.b,_,true,data.Dirichlet))
+      {
+        return false;
+      }
+    }
+    const Eigen::SparseMatrix<double> Aeq = M.diagonal().transpose().sparseView();
+    if(!igl::min_quad_with_fixed_precompute(
+      (-L*0.5).eval(),Eigen::VectorXi(),Aeq,true,data.Poisson))
+    {
+      return false;
+    }
+  }
+  return true;
+}
+
+template < typename Scalar, typename Derivedgamma, typename DerivedD>
+IGL_INLINE void igl::heat_geodesics_solve(
+  const HeatGeodesicsData<Scalar> & data,
+  const Eigen::MatrixBase<Derivedgamma> & gamma,
+  Eigen::PlainObjectBase<DerivedD> & D)
+{
+  // number of mesh vertices
+  const int n = data.Grad.cols();
+  // Set up delta at gamma
+  DerivedD u0 = DerivedD::Zero(n,1);
+  for(int g = 0;g<gamma.size();g++)
+  {
+    u0(gamma(g)) = 1;
+  }
+  // Neumann solution
+  DerivedD u;
+  igl::min_quad_with_fixed_solve(
+    data.Neumann,u0,DerivedD(),DerivedD(),u);
+  if(data.b.size()>0)
+  {
+    // Average Dirichelt and Neumann solutions
+    DerivedD uD;
+    igl::min_quad_with_fixed_solve(
+      data.Dirichlet,u0,DerivedD::Zero(data.b.size()),DerivedD(),uD);
+    u += uD;
+    u *= 0.5;
+  }
+  DerivedD grad_u = data.Grad*u;
+  const int m = data.Grad.rows()/data.ng;
+  for(int i = 0;i<m;i++)
+  {
+    Scalar norm = 0;
+    for(int d = 0;d<data.ng;d++)
+    {
+      norm += grad_u(d*m+i)*grad_u(d*m+i);
+    }
+    norm = sqrt(norm);
+    if(norm == 0)
+    {
+      for(int d = 0;d<data.ng;d++) { grad_u(d*m+i) = 0; }
+    }else
+    {
+      for(int d = 0;d<data.ng;d++) { grad_u(d*m+i) /= norm; }
+    }
+  }
+  const DerivedD div_X = -data.Div*grad_u;
+  const DerivedD Beq = (DerivedD(1,1)<<0).finished();
+  igl::min_quad_with_fixed_solve(data.Poisson,-2.0*div_X,DerivedD(),Beq,D);
+  DerivedD Dgamma;
+  igl::slice(D,gamma,Dgamma);
+  D.array() -= Dgamma.mean();
+  if(D.mean() < 0)
+  {
+    D = -D;
+  }
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template instantiation
+template void igl::heat_geodesics_solve<double, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(igl::HeatGeodesicsData<double> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
+template bool igl::heat_geodesics_precompute<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, double, igl::HeatGeodesicsData<double>&);
+template bool igl::heat_geodesics_precompute<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, igl::HeatGeodesicsData<double>&);
+#endif

+ 69 - 0
include/igl/heat_geodesics.h

@@ -0,0 +1,69 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2018 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_HEAT_GEODESICS_H
+#define IGL_HEAT_GEODESICS_H
+#include "igl_inline.h"
+#include "min_quad_with_fixed.h"
+#include <Eigen/Sparse>
+#include <Eigen/Sparse>
+namespace igl
+{
+  template <typename Scalar>
+  struct HeatGeodesicsData
+  {
+    // Gradient and Divergence operators
+    Eigen::SparseMatrix<Scalar> Grad,Div;
+    // Number of gradient components
+    int ng;
+    // List of boundary vertex indices
+    Eigen::VectorXi b;
+    // Solvers for Dirichet, Neumann problems
+    min_quad_with_fixed_data<Scalar> Dirichlet,Neumann,Poisson;
+    bool use_intrinsic_delaunay = false;
+  };
+  // Precompute factorized solvers for computing a fast approximation of
+  // geodesic distances on a mesh (V,F). [Crane et al. 2013]
+  //
+  // Inputs:
+  //   V  #V by dim list of mesh vertex positions
+  //   F  #F by 3 list of mesh face indices into V
+  // Outputs:
+  //   data  precomputation data (see heat_geodesics_solve)
+  template < typename DerivedV, typename DerivedF, typename Scalar >
+  IGL_INLINE bool heat_geodesics_precompute(
+    const Eigen::MatrixBase<DerivedV> & V,
+    const Eigen::MatrixBase<DerivedF> & F,
+    HeatGeodesicsData<Scalar> & data);
+  // Inputs:
+  //   t  "heat" parameter (smaller --> more accurate, less stable)
+  template < typename DerivedV, typename DerivedF, typename Scalar >
+  IGL_INLINE bool heat_geodesics_precompute(
+    const Eigen::MatrixBase<DerivedV> & V,
+    const Eigen::MatrixBase<DerivedF> & F,
+    const Scalar t,
+    HeatGeodesicsData<Scalar> & data);
+  // Compute fast approximate geodesic distances using precomputed data from a
+  // set of selected source vertices (gamma)
+  //
+  // Inputs: 
+  //   data  precomputation data (see heat_geodesics_precompute)
+  //   gamma  #gamma list of indices into V of source vertices
+  // Outputs:
+  //   D  #V list of distances to gamma 
+  template < typename Scalar, typename Derivedgamma, typename DerivedD>
+  IGL_INLINE void heat_geodesics_solve(
+    const HeatGeodesicsData<Scalar> & data,
+    const Eigen::MatrixBase<Derivedgamma> & gamma,
+    Eigen::PlainObjectBase<DerivedD> & D);
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#include "heat_geodesics.cpp"
+#endif
+
+#endif

+ 54 - 0
include/igl/intrinsic_delaunay_cotmatrix.cpp

@@ -0,0 +1,54 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2018 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/.
+#include "intrinsic_delaunay_cotmatrix.h"
+#include "edge_lengths.h"
+#include "intrinsic_delaunay_triangulation.h"
+#include "cotmatrix_intrinsic.h"
+#include <cassert>
+
+template <typename DerivedV, typename DerivedF, typename Scalar>
+IGL_INLINE void igl::intrinsic_delaunay_cotmatrix(
+  const Eigen::MatrixBase<DerivedV> & V, 
+  const Eigen::MatrixBase<DerivedF> & F, 
+  Eigen::SparseMatrix<Scalar>& L)
+{
+  Eigen::Matrix<Scalar, Eigen::Dynamic, 3> l_intrinsic;
+  DerivedF F_intrinsic;
+  return igl::intrinsic_delaunay_cotmatrix(V,F,L,l_intrinsic,F_intrinsic);
+}
+
+template <
+  typename DerivedV, 
+  typename DerivedF, 
+  typename Scalar,
+  typename Derivedl_intrinsic,
+  typename DerivedF_intrinsic>
+IGL_INLINE void igl::intrinsic_delaunay_cotmatrix(
+  const Eigen::MatrixBase<DerivedV> & V, 
+  const Eigen::MatrixBase<DerivedF> & F, 
+  Eigen::SparseMatrix<Scalar>& L,
+  Eigen::PlainObjectBase<Derivedl_intrinsic> & l_intrinsic,
+  Eigen::PlainObjectBase<DerivedF_intrinsic> & F_intrinsic)
+{
+  assert(F.cols() == 3 && "Only triangles are supported");
+  Eigen::Matrix<Scalar, Eigen::Dynamic, 3> l;
+  igl::edge_lengths(V,F,l);
+  igl::intrinsic_delaunay_triangulation(l,F,l_intrinsic,F_intrinsic);
+  igl::cotmatrix_intrinsic(l_intrinsic,F_intrinsic,L);
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template instantiation
+// generated by autoexplicit.sh
+template void igl::intrinsic_delaunay_cotmatrix<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<double, 0, int>&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+// generated by autoexplicit.sh
+template void igl::intrinsic_delaunay_cotmatrix<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<double, 0, int>&);
+// generated by autoexplicit.sh
+template void igl::intrinsic_delaunay_cotmatrix<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<double, 0, int>&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+// generated by autoexplicit.sh
+#endif

+ 51 - 0
include/igl/intrinsic_delaunay_cotmatrix.h

@@ -0,0 +1,51 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2018 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_INTRINSIC_DELAUNAY_COTMATRIX_H
+#define IGL_INTRINSIC_DELAUNAY_COTMATRIX_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+#include <Eigen/Sparse>
+namespace igl
+{
+  // INTRINSIC_DELAUNAY_COTMATRIX Computes the discrete cotangent Laplacian of a
+  // mesh after converting it into its intrinsic Delaunay triangulation (see,
+  // e.g., [Fisher et al. 2007].
+  //
+  // Inputs:
+  //   V  #V by dim list of mesh vertex positions
+  //   F  #F by 3 list of mesh elements (triangles or tetrahedra)
+  // Outputs: 
+  //   L  #V by #V cotangent matrix, each row i corresponding to V(i,:)
+  //   l_intrinsic  #F by 3 list of intrinsic edge-lengths used to compute L
+  //   F_intrinsic  #F by 3 list of intrinsic face indices used to compute L
+  //
+  // See also: intrinsic_delaunay_triangulation, cotmatrix, cotmatrix_intrinsic
+  template <
+    typename DerivedV, 
+    typename DerivedF, 
+    typename Scalar,
+    typename Derivedl_intrinsic,
+    typename DerivedF_intrinsic>
+  IGL_INLINE void intrinsic_delaunay_cotmatrix(
+    const Eigen::MatrixBase<DerivedV> & V, 
+    const Eigen::MatrixBase<DerivedF> & F, 
+    Eigen::SparseMatrix<Scalar>& L,
+    Eigen::PlainObjectBase<Derivedl_intrinsic> & l_intrinsic,
+    Eigen::PlainObjectBase<DerivedF_intrinsic> & F_intrinsic);
+  template <typename DerivedV, typename DerivedF, typename Scalar>
+  IGL_INLINE void intrinsic_delaunay_cotmatrix(
+    const Eigen::MatrixBase<DerivedV> & V, 
+    const Eigen::MatrixBase<DerivedF> & F, 
+    Eigen::SparseMatrix<Scalar>& L);
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "intrinsic_delaunay_cotmatrix.cpp"
+#endif
+
+#endif

+ 199 - 0
include/igl/intrinsic_delaunay_triangulation.cpp

@@ -0,0 +1,199 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2018 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/.
+#include "intrinsic_delaunay_triangulation.h"
+#include "is_intrinsic_delaunay.h"
+#include "tan_half_angle.h"
+#include "unique_edge_map.h"
+#include "flip_edge.h"
+#include "EPS.h"
+#include "matlab_format.h"
+#include <iostream>
+#include <queue>
+#include <map>
+
+template <
+  typename Derivedl_in,
+  typename DerivedF_in,
+  typename Derivedl,
+  typename DerivedF>
+IGL_INLINE void igl::intrinsic_delaunay_triangulation(
+  const Eigen::MatrixBase<Derivedl_in> & l_in,
+  const Eigen::MatrixBase<DerivedF_in> & F_in,
+  Eigen::PlainObjectBase<Derivedl> & l,
+  Eigen::PlainObjectBase<DerivedF> & F)
+{
+  typedef Eigen::Matrix<typename DerivedF::Scalar,Eigen::Dynamic,2> MatrixX2I;
+  typedef Eigen::Matrix<typename DerivedF::Scalar,Eigen::Dynamic,1> VectorXI;
+  MatrixX2I E,uE;
+  VectorXI EMAP;
+  std::vector<std::vector<typename DerivedF::Scalar> > uE2E;
+  return intrinsic_delaunay_triangulation(l_in,F_in,l,F,E,uE,EMAP,uE2E);
+}
+
+template <
+  typename Derivedl_in,
+  typename DerivedF_in,
+  typename Derivedl,
+  typename DerivedF,
+  typename DerivedE,
+  typename DeriveduE,
+  typename DerivedEMAP,
+  typename uE2EType>
+IGL_INLINE void igl::intrinsic_delaunay_triangulation(
+  const Eigen::MatrixBase<Derivedl_in> & l_in,
+  const Eigen::MatrixBase<DerivedF_in> & F_in,
+  Eigen::PlainObjectBase<Derivedl> & l,
+  Eigen::PlainObjectBase<DerivedF> & F,
+  Eigen::PlainObjectBase<DerivedE> & E,
+  Eigen::PlainObjectBase<DeriveduE> & uE,
+  Eigen::PlainObjectBase<DerivedEMAP> & EMAP,
+  std::vector<std::vector<uE2EType> > & uE2E)
+{
+  igl::unique_edge_map(F_in, E, uE, EMAP, uE2E);
+  // We're going to work in place
+  l = l_in;
+  F = F_in;
+  typedef typename DerivedF::Scalar Index;
+  typedef typename Derivedl::Scalar Scalar;
+  const Index num_faces = F.rows();
+
+  // Vector is faster than queue...
+  std::vector<Index> Q;
+  Q.reserve(uE2E.size());
+  for (size_t uei=0; uei<uE2E.size(); uei++) 
+  {
+    Q.push_back(uei);
+  }
+  // I tried using a "delaunay_since = iter" flag to avoid duplicates, but there
+  // was no speed up.
+
+  while(!Q.empty())
+  {
+#ifdef IGL_INTRINSIC_DELAUNAY_TRIANGULATION_DEBUG
+    // Expensive sanity check
+    {
+      Eigen::Matrix<bool,Eigen::Dynamic,1> inQ(uE2E.size(),1);
+      inQ.setConstant(false);
+      for(const auto uei : Q)
+      {
+        inQ(uei) = true;
+      }
+      for (Index uei=0; uei<uE2E.size(); uei++) 
+      {
+        if(!inQ(uei) && !is_intrinsic_delaunay(l,uE2E,num_faces,uei))
+        {
+          std::cout<<"  "<<uei<<" might never be fixed!"<<std::endl;
+        }
+      }
+    }
+#endif
+
+    const Index uei = Q.back();
+    Q.pop_back();
+    if (uE2E[uei].size() == 2) 
+    {
+      if(!is_intrinsic_delaunay(l,uE2E,num_faces,uei)) 
+      {
+        // update l just before flipping edge
+        //      .        //
+        //     /|\       //
+        //   a/ | \d     //
+        //   /  e  \     //
+        //  /   |   \    //
+        // .----|-f--.   //
+        //  \   |   /    //
+        //   \  |  /     //
+        //   b\α|δ/c     //
+        //     \|/       //
+        //      .        //
+        // Annotated from flip_edge:
+        // Edge to flip [v1,v2] --> [v3,v4]
+        // Before:
+        // F(f1,:) = [v1,v2,v4] // in some cyclic order
+        // F(f2,:) = [v1,v3,v2] // in some cyclic order
+        // After: 
+        // F(f1,:) = [v1,v3,v4] // in *this* order 
+        // F(f2,:) = [v2,v4,v3] // in *this* order
+        //
+        //          v1                 v1
+        //          /|\                / \
+        //        c/ | \b            c/f1 \b
+        //     v3 /f2|f1\ v4  =>  v3 /__f__\ v4
+        //        \  e  /            \ f2  /
+        //        d\ | /a            d\   /a
+        //          \|/                \ /
+        //          v2                 v2
+        //
+        // Compute intrinsic length of oppposite edge
+        assert(uE2E[uei].size() == 2 && "edge should have 2 incident faces");
+        const Index f1 = uE2E[uei][0]%num_faces;
+        const Index f2 = uE2E[uei][1]%num_faces;
+        const Index c1 = uE2E[uei][0]/num_faces;
+        const Index c2 = uE2E[uei][1]/num_faces;
+        assert(c1 < 3);
+        assert(c2 < 3);
+        assert(f1 != f2);
+        const Index v1 = F(f1, (c1+1)%3);
+        const Index v2 = F(f1, (c1+2)%3);
+        const Index v4 = F(f1, c1);
+        const Index v3 = F(f2, c2);
+        assert(F(f2, (c2+2)%3) == v1);
+        assert(F(f2, (c2+1)%3) == v2);
+        assert( std::abs(l(f1,c1)-l(f2,c2)) < igl::EPS<Scalar>() );
+        const Scalar e = l(f1,c1);
+        const Scalar a = l(f1,(c1+1)%3);
+        const Scalar b = l(f1,(c1+2)%3);
+        const Scalar c = l(f2,(c2+1)%3);
+        const Scalar d = l(f2,(c2+2)%3);
+        // tan(α/2)
+        const Scalar tan_a_2= tan_half_angle(a,b,e);
+        // tan(δ/2)
+        const Scalar tan_d_2 = tan_half_angle(d,e,c);
+        // tan((α+δ)/2)
+        const Scalar tan_a_d_2 = (tan_a_2 + tan_d_2)/(1.0-tan_a_2*tan_d_2);
+        // cos(α+δ)
+        const Scalar cos_a_d = 
+          (1.0 - tan_a_d_2*tan_a_d_2)/(1.0+tan_a_d_2*tan_a_d_2);
+        const Scalar f = sqrt(b*b + c*c - 2.0*b*c*cos_a_d);
+        l(f1,0) = f;
+        l(f1,1) = b;
+        l(f1,2) = c;
+        l(f2,0) = f;
+        l(f2,1) = d;
+        l(f2,2) = a;
+        // Important to grab these indices _before_ calling flip_edges (they
+        // will be correct after)
+        const size_t e_24 = f1 + ((c1 + 1) % 3) * num_faces;
+        const size_t e_41 = f1 + ((c1 + 2) % 3) * num_faces;
+        const size_t e_13 = f2 + ((c2 + 1) % 3) * num_faces;
+        const size_t e_32 = f2 + ((c2 + 2) % 3) * num_faces;
+        const size_t ue_24 = EMAP(e_24);
+        const size_t ue_41 = EMAP(e_41);
+        const size_t ue_13 = EMAP(e_13);
+        const size_t ue_32 = EMAP(e_32);
+        flip_edge(F, E, uE, EMAP, uE2E, uei);
+        Q.push_back(ue_24);
+        Q.push_back(ue_41);
+        Q.push_back(ue_13);
+        Q.push_back(ue_32);
+      }
+    }
+  }
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template instantiation
+// generated by autoexplicit.sh
+template void igl::intrinsic_delaunay_triangulation<Eigen::Matrix<double, -1, 3, 0, -1, 3>, 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::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+// generated by autoexplicit.sh
+template void igl::intrinsic_delaunay_triangulation<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+// generated by autoexplicit.sh
+template void igl::intrinsic_delaunay_triangulation<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<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, int>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > 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> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&);
+// generated by autoexplicit.sh
+template void igl::intrinsic_delaunay_triangulation<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::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+#endif

+ 79 - 0
include/igl/intrinsic_delaunay_triangulation.h

@@ -0,0 +1,79 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2018 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_INTRINSIC_DELAUNAY_TRIANGULATION_H
+#define IGL_INTRINSIC_DELAUNAY_TRIANGULATION_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+#include <vector>
+namespace igl
+{
+  // INTRINSIC_DELAUNAY_TRIANGULATION Flip edges _intrinsically_ until all are
+  // "intrinsic Delaunay". See "An algorithm for the construction of intrinsic
+  // delaunay triangulations with applications to digital geometry processing"
+  // [Fisher et al. 2007].
+  //
+  // Inputs:
+  //   l_in  #F_in by 3 list of edge lengths (see edge_lengths)
+  //   F_in  #F_in by 3 list of face indices into some unspecified vertex list V
+  // Outputs:
+  //   l  #F by 3 list of edge lengths
+  //   F  #F by 3 list of new face indices. Note: Combinatorially F may contain
+  //     non-manifold edges, duplicate faces and self-loops (e.g., an edge [1,1]
+  //     or a face [1,1,1]). However, the *intrinsic geometry* is still
+  //     well-defined and correct. See [Fisher et al. 2007] Figure 3 and 2nd to
+  //     last paragraph of 1st page. Since F may be "non-eddge-manifold" in the
+  //     usual combinatorial sense, it may be useful to call the more verbose
+  //     overload below if disentangling edges will be necessary later on.
+  //     Calling unique_edge_map on this F will give a _different_ result than
+  //     those outputs.
+  //
+  // See also: is_intrinsic_delaunay
+  template <
+    typename Derivedl_in,
+    typename DerivedF_in,
+    typename Derivedl,
+    typename DerivedF>
+  IGL_INLINE void intrinsic_delaunay_triangulation(
+    const Eigen::MatrixBase<Derivedl_in> & l_in,
+    const Eigen::MatrixBase<DerivedF_in> & F_in,
+    Eigen::PlainObjectBase<Derivedl> & l,
+    Eigen::PlainObjectBase<DerivedF> & F);
+  // Outputs:
+  //   E  #F*3 by 2 list of all directed edges, such that E.row(f+#F*c) is the
+  //     edge opposite F(f,c)
+  //   uE  #uE by 2 list of unique undirected edges
+  //   EMAP #F*3 list of indices into uE, mapping each directed edge to unique
+  //     undirected edge
+  //   uE2E  #uE list of lists of indices into E of coexisting edges
+  //
+  // See also: unique_edge_map
+  template <
+    typename Derivedl_in,
+    typename DerivedF_in,
+    typename Derivedl,
+    typename DerivedF,
+    typename DerivedE,
+    typename DeriveduE,
+    typename DerivedEMAP,
+    typename uE2EType>
+  IGL_INLINE void intrinsic_delaunay_triangulation(
+    const Eigen::MatrixBase<Derivedl_in> & l_in,
+    const Eigen::MatrixBase<DerivedF_in> & F_in,
+    Eigen::PlainObjectBase<Derivedl> & l,
+    Eigen::PlainObjectBase<DerivedF> & F,
+    Eigen::PlainObjectBase<DerivedE> & E,
+    Eigen::PlainObjectBase<DeriveduE> & uE,
+    Eigen::PlainObjectBase<DerivedEMAP> & EMAP,
+    std::vector<std::vector<uE2EType> > & uE2E);
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "intrinsic_delaunay_triangulation.cpp"
+#endif
+
+#endif

+ 14 - 7
include/igl/is_border_vertex.cpp

@@ -10,14 +10,13 @@
 
 #include "triangle_triangle_adjacency.h"
 
-template <typename DerivedV, typename DerivedF>
+template <typename DerivedF>
 IGL_INLINE std::vector<bool> igl::is_border_vertex(
-    const Eigen::PlainObjectBase<DerivedV> &V,
-    const Eigen::PlainObjectBase<DerivedF> &F)
+  const Eigen::MatrixBase<DerivedF> &F)
 {
   DerivedF FF;
   igl::triangle_triangle_adjacency(F,FF);
-  std::vector<bool> ret(V.rows());
+  std::vector<bool> ret(F.maxCoeff()+1);
   for(unsigned i=0; i<ret.size();++i)
     ret[i] = false;
 
@@ -31,9 +30,17 @@ IGL_INLINE std::vector<bool> igl::is_border_vertex(
   return ret;
 }
 
+template <typename DerivedV, typename DerivedF>
+IGL_INLINE std::vector<bool> igl::is_border_vertex(
+  const Eigen::MatrixBase<DerivedV> &/*V*/,
+  const Eigen::MatrixBase<DerivedF> &F)
+{
+  return igl::is_border_vertex(F);
+}
+
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
-template std::vector<bool, std::allocator<bool> > igl::is_border_vertex<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&);
-template std::vector<bool, std::allocator<bool> > igl::is_border_vertex<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&);
-template std::vector<bool, std::allocator<bool> > igl::is_border_vertex<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&);
+template std::vector<bool, std::allocator<bool> > igl::is_border_vertex<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&);
+template std::vector<bool, std::allocator<bool> > igl::is_border_vertex<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
+template std::vector<bool, std::allocator<bool> > igl::is_border_vertex<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
 #endif

+ 7 - 4
include/igl/is_border_vertex.h

@@ -22,13 +22,16 @@ namespace igl
   //   F  #F by 3 list of triangle indices
   // Returns #V vector of bools revealing whether vertices are on boundary
   //
-  // Known Bugs: - does not depend on V
-  //             - assumes mesh is edge manifold
+  // Known Bugs: - assumes mesh is edge manifold
   // 
+  template <typename DerivedF>
+  IGL_INLINE std::vector<bool> is_border_vertex(
+   const Eigen::MatrixBase<DerivedF> &F);
+  // Deprecated:
   template <typename DerivedV, typename DerivedF>
   IGL_INLINE std::vector<bool> is_border_vertex(
-   const Eigen::PlainObjectBase<DerivedV> &V,
-   const Eigen::PlainObjectBase<DerivedF> &F);
+   const Eigen::MatrixBase<DerivedV> &V,
+   const Eigen::MatrixBase<DerivedF> &F);
 }
 
 #ifndef IGL_STATIC_LIBRARY

+ 105 - 0
include/igl/is_delaunay.cpp

@@ -0,0 +1,105 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2018 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/.
+#include "is_delaunay.h"
+#include "unique_edge_map.h"
+#include <cassert>
+
+template <
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedD>
+IGL_INLINE void igl::is_delaunay(
+  const Eigen::MatrixBase<DerivedV> & V,
+  const Eigen::MatrixBase<DerivedF> & F,
+  Eigen::PlainObjectBase<DerivedD> & D)
+{
+  typedef typename DerivedV::Scalar Scalar;
+  // Should use Shewchuk's predicates instead.
+  const auto float_incircle = [](
+    const Scalar pa[2],
+    const Scalar pb[2],
+    const Scalar pc[2],
+    const Scalar pd[2])->short
+  {
+    // I acknowledge that I am cating to double
+    const Eigen::Matrix3d A = (Eigen::Matrix3d(3,3)<<
+      pa[0]-pd[0], pa[1]-pd[1],(pa[0]-pd[0])*(pa[0]-pd[0])+(pa[1]-pd[1])*(pa[1]-pd[1]),
+      pb[0]-pd[0], pb[1]-pd[1],(pb[0]-pd[0])*(pb[0]-pd[0])+(pb[1]-pd[1])*(pb[1]-pd[1]),
+      pc[0]-pd[0], pc[1]-pd[1],(pc[0]-pd[0])*(pc[0]-pd[0])+(pc[1]-pd[1])*(pc[1]-pd[1])
+      ).finished();
+    const Scalar detA = A.determinant();
+    return (Scalar(0) < detA) - (detA < Scalar(0));
+  };
+
+  typedef Eigen::Matrix<typename DerivedF::Scalar,Eigen::Dynamic,2> MatrixX2I;
+  typedef Eigen::Matrix<typename DerivedF::Scalar,Eigen::Dynamic,1> VectorXI;
+  MatrixX2I E,uE;
+  VectorXI EMAP;
+  std::vector<std::vector<typename DerivedF::Scalar> > uE2E;
+  igl::unique_edge_map(F, E, uE, EMAP, uE2E);
+  const int num_faces = F.rows();
+  D.setConstant(F.rows(),F.cols(),false);
+  // loop over all unique edges
+  for(int ue = 0;ue < uE2E.size(); ue++)
+  {
+    const bool ue_is_d = is_delaunay(V,F,uE2E,float_incircle,ue);
+    // Set for all instances
+    for(int e = 0;e<uE2E[ue].size();e++)
+    {
+      D( uE2E[ue][e]%num_faces, uE2E[ue][e]/num_faces) = ue_is_d;
+    }
+  }
+}
+
+template <
+  typename DerivedV,
+  typename DerivedF,
+  typename uE2EType,
+  typename InCircle,
+  typename ueiType>
+IGL_INLINE bool igl::is_delaunay(
+  const Eigen::MatrixBase<DerivedV> & V,
+  const Eigen::MatrixBase<DerivedF> & F,
+  const std::vector<std::vector<uE2EType> > & uE2E,
+  const InCircle incircle,
+  const ueiType uei)
+{
+  if(uE2E[uei].size() == 1) return true;
+  if(uE2E[uei].size() > 2) return false;
+  const int num_faces = F.rows();
+  typedef typename DerivedV::Scalar Scalar;
+  const auto& half_edges = uE2E[uei];
+  assert((half_edges.size() == 2)  && "uE2E[uei].size() should be 2");
+  const size_t f1 = half_edges[0] % num_faces;
+  const size_t f2 = half_edges[1] % num_faces;
+  const size_t c1 = half_edges[0] / num_faces;
+  const size_t c2 = half_edges[1] / num_faces;
+  assert(c1 < 3);
+  assert(c2 < 3);
+  assert(f1 != f2);
+  const size_t v1 = F(f1, (c1+1)%3);
+  const size_t v2 = F(f1, (c1+2)%3);
+  const size_t v4 = F(f1, c1);
+  const size_t v3 = F(f2, c2);
+  const Scalar p1[] = {V(v1, 0), V(v1, 1)};
+  const Scalar p2[] = {V(v2, 0), V(v2, 1)};
+  const Scalar p3[] = {V(v3, 0), V(v3, 1)};
+  const Scalar p4[] = {V(v4, 0), V(v4, 1)};
+  auto orientation = incircle(p1, p2, p4, p3);
+  return orientation <= 0;
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template instantiation
+// generated by autoexplicit.sh
+template void igl::is_delaunay<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<bool, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 3, 0, -1, 3> >&);
+// generated by autoexplicit.sh
+template void igl::is_delaunay<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<bool, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, -1, 0, -1, -1> >&);
+// generated by autoexplicit.sh
+template bool igl::is_delaunay<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, int, short (*)(double const*, double const*, double const*, double const*), unsigned long>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, short (*)(double const*, double const*, double const*, double const*), unsigned long);
+#endif

+ 64 - 0
include/igl/is_delaunay.h

@@ -0,0 +1,64 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2018 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_IS_DELAUNAY_H
+#define IGL_IS_DELAUNAY_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+#include <vector>
+namespace igl
+{
+  // IS_DELAUNAY Determine if each edge in the mesh (V,F) is Delaunay.
+  //
+  // Inputs:
+  //   V  #V by dim list of vertex positions
+  //   F  #F by 3 list of triangles indices
+  // Outputs:
+  //   D  #F by 3 list of bools revealing whether edges corresponding 23 31 12
+  //     are locally Delaunay. Boundary edges are by definition Delaunay.
+  //     Non-Manifold edges are by definition not Delaunay.
+  template <
+    typename DerivedV,
+    typename DerivedF,
+    typename DerivedD>
+  IGL_INLINE void is_delaunay(
+    const Eigen::MatrixBase<DerivedV> & V,
+    const Eigen::MatrixBase<DerivedF> & F,
+    Eigen::PlainObjectBase<DerivedD> & D);
+  // Determine whether a single edge is Delaunay using a provided (extrinsic) incirle
+  // test.
+  //
+  // Inputs:
+  //   V  #V by dim list of vertex positions
+  //   F  #F by 3 list of triangles indices
+  //   uE2E  #uE list of lists of indices into E of coexisting edges (see
+  //     unique_edge_map)
+  //   incircle  A functor such that incircle(pa, pb, pc, pd) returns
+  //               1 if pd is on the positive size of circumcirle of (pa,pb,pc)
+  //              -1 if pd is on the positive size of circumcirle of (pa,pb,pc)
+  //               0 if pd is cocircular with pa, pb, pc.
+  //               (see delaunay_triangulation)
+  //   uei  index into uE2E of edge to check
+  // Returns true iff edge is Delaunay
+  template <
+    typename DerivedV,
+    typename DerivedF,
+    typename uE2EType,
+    typename InCircle,
+    typename ueiType>
+  IGL_INLINE bool is_delaunay(
+    const Eigen::MatrixBase<DerivedV> & V,
+    const Eigen::MatrixBase<DerivedF> & F,
+    const std::vector<std::vector<uE2EType> > & uE2E,
+    const InCircle incircle,
+    const ueiType uei);
+
+}
+#ifndef IGL_STATIC_LIBRARY
+#include "is_delaunay.cpp"
+#endif
+#endif

+ 147 - 0
include/igl/is_intrinsic_delaunay.cpp

@@ -0,0 +1,147 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2018 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/.
+#include "is_intrinsic_delaunay.h"
+#include "unique_edge_map.h"
+#include "tan_half_angle.h"
+#include "EPS.h"
+#include "matlab_format.h"
+#include "cotmatrix_entries.h"
+#include <iostream>
+#include <cassert>
+template <
+  typename Derivedl,
+  typename DerivedF,
+  typename DerivedD>
+IGL_INLINE void igl::is_intrinsic_delaunay(
+  const Eigen::MatrixBase<Derivedl> & l,
+  const Eigen::MatrixBase<DerivedF> & F,
+  Eigen::PlainObjectBase<DerivedD> & D)
+{
+  typedef Eigen::Matrix<typename DerivedF::Scalar,Eigen::Dynamic,2> MatrixX2I;
+  typedef Eigen::Matrix<typename DerivedF::Scalar,Eigen::Dynamic,1> VectorXI;
+  MatrixX2I E,uE;
+  VectorXI EMAP;
+  std::vector<std::vector<typename DerivedF::Scalar> > uE2E;
+  igl::unique_edge_map(F, E, uE, EMAP, uE2E);
+  return is_intrinsic_delaunay(l,F,uE2E,D);
+}
+
+template <
+  typename Derivedl,
+  typename DerivedF,
+  typename uE2EType,
+  typename DerivedD>
+IGL_INLINE void igl::is_intrinsic_delaunay(
+  const Eigen::MatrixBase<Derivedl> & l,
+  const Eigen::MatrixBase<DerivedF> & F,
+  const std::vector<std::vector<uE2EType> > & uE2E,
+  Eigen::PlainObjectBase<DerivedD> & D)
+{
+  const int num_faces = F.rows();
+  D.setConstant(F.rows(),F.cols(),false);
+  // loop over all unique edges
+  for(int ue = 0;ue < uE2E.size(); ue++)
+  {
+    const bool ue_is_d = is_intrinsic_delaunay(l,uE2E,num_faces,ue);
+    // Set for all instances
+    for(int e = 0;e<uE2E[ue].size();e++)
+    {
+      D( uE2E[ue][e]%num_faces, uE2E[ue][e]/num_faces) = ue_is_d;
+    }
+  }
+};
+
+template <
+  typename Derivedl,
+  typename uE2EType,
+  typename Index>
+IGL_INLINE bool igl::is_intrinsic_delaunay(
+  const Eigen::MatrixBase<Derivedl> & l,
+  const std::vector<std::vector<uE2EType> > & uE2E,
+  const Index num_faces,
+  const Index uei)
+{
+  if(uE2E[uei].size() == 1) return true;
+  if(uE2E[uei].size() > 2) return false;
+  typedef typename Derivedl::Scalar Scalar;
+
+  const auto cot_alpha = [](
+    const Scalar & a,
+    const Scalar & b,
+    const Scalar & c)->Scalar
+  {
+    // Fisher 2007
+    const Scalar t = tan_half_angle(a,b,c);
+    return (1.0-t*t)/(2*t);
+  };
+
+  //      2        //
+  //     /|\       //
+  //   a/ | \d     //
+  //   /  e  \     //
+  //  /   |   \    //
+  //0.α---|-f-β.3  //
+  //  \   |   /    //
+  //   \  |  /     //
+  //   b\ | /c     //
+  //     \|/       //
+  //      .        //
+  //      1
+
+  // Fisher 2007
+  assert(uE2E[uei].size() == 2 && "edge should have 2 incident faces");
+  const Index he1 = uE2E[uei][0];
+  const Index he2 = uE2E[uei][1];
+  const Index f1 = he1%num_faces;
+  const Index c1 = he1/num_faces;
+  const Index f2 = he2%num_faces;
+  const Index c2 = he2/num_faces;
+  assert( std::abs(l(f1,c1)-l(f2,c2)) < igl::EPS<Scalar>());
+  const Scalar e = l(f1,c1);
+  const Scalar a = l(f1,(c1+1)%3);
+  const Scalar b = l(f1,(c1+2)%3);
+  const Scalar c = l(f2,(c2+1)%3);
+  const Scalar d = l(f2,(c2+2)%3);
+  const Scalar w = cot_alpha(e,a,b) + cot_alpha(e,c,d);
+
+  //// Test
+  //{
+  //  Eigen::MatrixXd l(2,3);
+  //  l<<e,a,b,
+  //     d,e,c;
+  //  //Eigen::MatrixXi F(2,3);
+  //  //F<<0,1,2,
+  //  //   1,3,2;
+  //  Eigen::MatrixXd C;
+  //  cotmatrix_entries(l,C);
+  //  if(std::abs(w-(2.0*(C(0,0)+C(1,1))))>1e-10)
+  //  {
+  //    std::cout<<matlab_format(l,"l")<<std::endl;
+  //    std::cout<<w<<std::endl;
+  //    std::cout<<(2.0*(C(0,0)+C(1,1)))<<std::endl;
+  //    std::cout<<w-(2.0*(C(0,0)+C(1,1)))<<std::endl;
+  //    std::cout<<std::endl;
+  //  }
+  //}
+
+  return w >= 0;
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template instantiation
+// generated by autoexplicit.sh
+template bool igl::is_intrinsic_delaunay<Eigen::Matrix<double, -1, 3, 0, -1, 3>, int, int>(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, int, int);
+// generated by autoexplicit.sh
+template bool igl::is_intrinsic_delaunay<Eigen::Matrix<double, -1, -1, 0, -1, -1>, int, int>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, int, int);
+// generated by autoexplicit.sh
+template void igl::is_intrinsic_delaunay<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, int, Eigen::Matrix<bool, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 3, 0, -1, 3> >&);
+// generated by autoexplicit.sh
+template void igl::is_intrinsic_delaunay<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<bool, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, -1, 0, -1, -1> >&);
+// generated by autoexplicit.sh
+template void igl::is_intrinsic_delaunay<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<bool, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 3, 0, -1, 3> >&);
+#endif

+ 69 - 0
include/igl/is_intrinsic_delaunay.h

@@ -0,0 +1,69 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2018 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_IS_INTRINSIC_DELAUNAY_H
+#define IGL_IS_INTRINSIC_DELAUNAY_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+#include <vector>
+namespace igl
+{
+  // IS_INTRINSIC_DELAUNAY Determine if each edge in the mesh (V,F) is Delaunay.
+  //
+  // Inputs:
+  //   l  #l by dim list of edge lengths
+  //   F  #F by 3 list of triangles indices
+  // Outputs:
+  //   D  #F by 3 list of bools revealing whether edges corresponding 23 31 12
+  //     are locally Delaunay. Boundary edges are by definition Delaunay.
+  //     Non-Manifold edges are by definition not Delaunay.
+  template <
+    typename Derivedl,
+    typename DerivedF,
+    typename DerivedD>
+  IGL_INLINE void is_intrinsic_delaunay(
+    const Eigen::MatrixBase<Derivedl> & l,
+    const Eigen::MatrixBase<DerivedF> & F,
+    Eigen::PlainObjectBase<DerivedD> & D);
+  // Inputs:
+  //   uE2E  #uE list of lists mapping unique edges to (half-)edges
+  template <
+    typename Derivedl,
+    typename DerivedF,
+    typename uE2EType,
+    typename DerivedD>
+  IGL_INLINE void is_intrinsic_delaunay(
+    const Eigen::MatrixBase<Derivedl> & l,
+    const Eigen::MatrixBase<DerivedF> & F,
+    const std::vector<std::vector<uE2EType> > & uE2E,
+    Eigen::PlainObjectBase<DerivedD> & D);
+  // Determine whether a single edge is Delaunay using a provided (extrinsic) incirle
+  // test.
+  //
+  // Inputs:
+  //   l  #l by dim list of edge lengths
+  //   uE2E  #uE list of lists of indices into E of coexisting edges (see
+  //     unique_edge_map)
+  //   num_faces  number of faces (==#F)
+  //   uei  index into uE2E of edge to check
+  // Returns true iff edge is Delaunay
+  template <
+    typename Derivedl,
+    typename uE2EType,
+    typename Index>
+  IGL_INLINE bool is_intrinsic_delaunay(
+    const Eigen::MatrixBase<Derivedl> & l,
+    const std::vector<std::vector<uE2EType> > & uE2E,
+    const Index num_faces,
+    const Index uei);
+
+}
+#ifndef IGL_STATIC_LIBRARY
+#include "is_intrinsic_delaunay.cpp"
+#endif
+#endif
+

+ 3 - 3
include/igl/lexicographic_triangulation.cpp

@@ -19,7 +19,7 @@ template<
   typename DerivedF
   >
 IGL_INLINE void igl::lexicographic_triangulation(
-    const Eigen::PlainObjectBase<DerivedP>& P,
+    const Eigen::MatrixBase<DerivedP>& P,
     Orient2D orient2D,
     Eigen::PlainObjectBase<DerivedF>& F)
 {
@@ -128,5 +128,5 @@ IGL_INLINE void igl::lexicographic_triangulation(
 
 
 #ifdef IGL_STATIC_LIBRARY
-template void igl::lexicographic_triangulation<Eigen::Matrix<double, -1, -1, 0, -1, -1>, short (*)(double const*, double const*, double const*), Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, short (*)(double const*, double const*, double const*), Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
-#endif
+template void igl::lexicographic_triangulation<Eigen::Matrix<double, -1, -1, 0, -1, -1>, short (*)(double const*, double const*, double const*), Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, short (*)(double const*, double const*, double const*), Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+#endif

+ 1 - 1
include/igl/lexicographic_triangulation.h

@@ -33,7 +33,7 @@ namespace igl
     typename DerivedF
     >
   IGL_INLINE void lexicographic_triangulation(
-      const Eigen::PlainObjectBase<DerivedP>& P,
+      const Eigen::MatrixBase<DerivedP>& P,
       Orient2D orient2D,
       Eigen::PlainObjectBase<DerivedF>& F);
 }

+ 14 - 14
include/igl/line_field_missmatch.cpp → include/igl/line_field_mismatch.cpp

@@ -6,7 +6,7 @@
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can
 // obtain one at http://mozilla.org/MPL/2.0/.
 
-#include "line_field_missmatch.h"
+#include "line_field_mismatch.h"
 
 #include <vector>
 #include <deque>
@@ -24,7 +24,7 @@
 
 namespace igl {
 template <typename DerivedV, typename DerivedF, typename DerivedO>
-class MissMatchCalculatorLine
+class MismatchCalculatorLine
 {
 public:
 
@@ -46,8 +46,8 @@ private:
 private:
 
     //compute the mismatch between 2 faces
-    inline int MissMatchByLine(const int f0,
-                               const int f1)
+    inline int mismatchByLine(const int f0,
+                              const int f1)
     {
         Eigen::Matrix<typename DerivedV::Scalar, 3, 1> dir0 = PD1.row(f0);
         Eigen::Matrix<typename DerivedV::Scalar, 3, 1> dir1 = PD1.row(f1);
@@ -81,7 +81,7 @@ private:
 
 public:
 
-    inline MissMatchCalculatorLine(const Eigen::PlainObjectBase<DerivedV> &_V,
+    inline MismatchCalculatorLine(const Eigen::PlainObjectBase<DerivedV> &_V,
                                const Eigen::PlainObjectBase<DerivedF> &_F,
                                const Eigen::PlainObjectBase<DerivedV> &_PD1,
                                const Eigen::PlainObjectBase<DerivedV> &_PD2
@@ -97,7 +97,7 @@ public:
         igl::triangle_triangle_adjacency(F,TT,TTi);
     }
 
-    inline void calculateMissmatchLine(Eigen::PlainObjectBase<DerivedO> &Handle_MMatch)
+    inline void calculateMismatchLine(Eigen::PlainObjectBase<DerivedO> &Handle_MMatch)
     {
         Handle_MMatch.setConstant(F.rows(),3,-1);
         for (unsigned int i=0;i<F.rows();i++)
@@ -107,7 +107,7 @@ public:
                 if (i==TT(i,j) || TT(i,j) == -1)
                     Handle_MMatch(i,j)=0;
                 else
-                    Handle_MMatch(i,j) = MissMatchByLine(i,TT(i,j));
+                    Handle_MMatch(i,j) = mismatchByLine(i, TT(i, j));
             }
         }
     }
@@ -117,11 +117,11 @@ public:
 
 
 template <typename DerivedV, typename DerivedF, typename DerivedO>
-IGL_INLINE void igl::line_field_missmatch(const Eigen::PlainObjectBase<DerivedV> &V,
-                                const Eigen::PlainObjectBase<DerivedF> &F,
-                                const Eigen::PlainObjectBase<DerivedV> &PD1,
-                                const bool isCombed,
-                                Eigen::PlainObjectBase<DerivedO> &missmatch)
+IGL_INLINE void igl::line_field_mismatch(const Eigen::PlainObjectBase<DerivedV> &V,
+                                         const Eigen::PlainObjectBase<DerivedF> &F,
+                                         const Eigen::PlainObjectBase<DerivedV> &PD1,
+                                         const bool isCombed,
+                                         Eigen::PlainObjectBase<DerivedO> &mismatch)
 {
     DerivedV PD1_combed;
     DerivedV PD2_combed;
@@ -135,8 +135,8 @@ IGL_INLINE void igl::line_field_missmatch(const Eigen::PlainObjectBase<DerivedV>
     Eigen::MatrixXd B1,B2,B3;
     igl::local_basis(V,F,B1,B2,B3);
     PD2_combed = igl::rotate_vectors(PD1_combed, Eigen::VectorXd::Constant(1,igl::PI/2), B1, B2);
-    igl::MissMatchCalculatorLine<DerivedV, DerivedF, DerivedO> sf(V, F, PD1_combed, PD2_combed);
-    sf.calculateMissmatchLine(missmatch);
+    igl::MismatchCalculatorLine<DerivedV, DerivedF, DerivedO> sf(V, F, PD1_combed, PD2_combed);
+    sf.calculateMismatchLine(mismatch);
 }
 
 #ifdef IGL_STATIC_LIBRARY

+ 11 - 12
include/igl/cross_field_missmatch.h → include/igl/line_field_mismatch.h

@@ -1,19 +1,19 @@
 // This file is part of libigl, a simple c++ geometry processing library.
 //
-// Copyright (C) 2014 Daniele Panozzo <daniele.panozzo@gmail.com>, Olga Diamanti <olga.diam@gmail.com>
+// Copyright (C) 2014 Nico Pietroni <nico.pietroni@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_CROSS_FIELD_MISSMATCH_H
-#define IGL_CROSS_FIELD_MISSMATCH_H
+#ifndef IGL_LINE_FIELD_MISSMATCH_H
+#define IGL_LINE_FIELD_MISSMATCH_H
 #include "igl_inline.h"
 #include <Eigen/Core>
 namespace igl
 {
-  // Calculates the missmatch (integer), at each face edge, of a cross field defined on the mesh faces.
-  // The integer missmatch is a multiple of pi/2 that transforms the cross on one side of the edge to
+  // Calculates the mismatch (integer), at each face edge, of a cross field defined on the mesh faces.
+  // The integer mismatch is a multiple of pi/2 that transforms the cross on one side of the edge to
   // the cross on the other side. It represents the deviation from a Lie connection across the edge.
 
   // Inputs:
@@ -24,20 +24,19 @@ namespace igl
   //   isCombed  boolean, specifying whether the field is combed (i.e. matching has been precomputed.
   //             If not, the field is combed first.
   // Output:
-  //   Handle_MMatch    #F by 3 eigen Matrix containing the integer missmatch of the cross field
-  //                    across all face edges
+  //   mismatch  #F by 3 eigen Matrix containing the integer mismatch of the cross field
+  //             across all face edges
   //
 
-  template <typename DerivedV, typename DerivedF, typename DerivedM>
-  IGL_INLINE void cross_field_missmatch(const Eigen::PlainObjectBase<DerivedV> &V,
+    template <typename DerivedV, typename DerivedF, typename DerivedO>
+    IGL_INLINE void line_field_mismatch(const Eigen::PlainObjectBase<DerivedV> &V,
                                         const Eigen::PlainObjectBase<DerivedF> &F,
                                         const Eigen::PlainObjectBase<DerivedV> &PD1,
-                                        const Eigen::PlainObjectBase<DerivedV> &PD2,
                                         const bool isCombed,
-                                        Eigen::PlainObjectBase<DerivedM> &missmatch);
+                                        Eigen::PlainObjectBase<DerivedO> &mismatch);
 }
 #ifndef IGL_STATIC_LIBRARY
-#include "cross_field_missmatch.cpp"
+#include "line_field_mismatch.cpp"
 #endif
 
 #endif

+ 0 - 42
include/igl/line_field_missmatch.h

@@ -1,42 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2014 Nico Pietroni <nico.pietroni@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_LINE_FIELD_MISSMATCH_H
-#define IGL_LINE_FIELD_MISSMATCH_H
-#include "igl_inline.h"
-#include <Eigen/Core>
-namespace igl
-{
-  // Calculates the missmatch (integer), at each face edge, of a cross field defined on the mesh faces.
-  // The integer missmatch is a multiple of pi/2 that transforms the cross on one side of the edge to
-  // the cross on the other side. It represents the deviation from a Lie connection across the edge.
-
-  // Inputs:
-  //   V         #V by 3 eigen Matrix of mesh vertex 3D positions
-  //   F         #F by 3 eigen Matrix of face (quad) indices
-  //   PD1       #F by 3 eigen Matrix of the first per face cross field vector
-  //   PD2       #F by 3 eigen Matrix of the second per face cross field vector
-  //   isCombed  boolean, specifying whether the field is combed (i.e. matching has been precomputed.
-  //             If not, the field is combed first.
-  // Output:
-  //   Handle_MMatch    #F by 3 eigen Matrix containing the integer missmatch of the cross field
-  //                    across all face edges
-  //
-
-    template <typename DerivedV, typename DerivedF, typename DerivedO>
-    IGL_INLINE void line_field_missmatch(const Eigen::PlainObjectBase<DerivedV> &V,
-                                         const Eigen::PlainObjectBase<DerivedF> &F,
-                                         const Eigen::PlainObjectBase<DerivedV> &PD1,
-                                         const bool isCombed,
-                                         Eigen::PlainObjectBase<DerivedO> &missmatch);
-}
-#ifndef IGL_STATIC_LIBRARY
-#include "line_field_missmatch.cpp"
-#endif
-
-#endif

+ 9 - 81
include/igl/massmatrix.cpp

@@ -6,6 +6,8 @@
 // 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 "massmatrix.h"
+#include "massmatrix_intrinsic.h"
+#include "edge_lengths.h"
 #include "normalize_row_sums.h"
 #include "sparse.h"
 #include "doublearea.h"
@@ -37,92 +39,18 @@ IGL_INLINE void igl::massmatrix(
   // Not yet supported
   assert(type!=MASSMATRIX_TYPE_FULL);
 
-  Matrix<int,Dynamic,1> MI;
-  Matrix<int,Dynamic,1> MJ;
-  Matrix<Scalar,Dynamic,1> MV;
   if(simplex_size == 3)
   {
     // Triangles
     // edge lengths numbered same as opposite vertices
-    Matrix<Scalar,Dynamic,3> l(m,3);
-    // loop over faces
-    for(int i = 0;i<m;i++)
-    {
-      l(i,0) = (V.row(F(i,1))-V.row(F(i,2))).norm();
-      l(i,1) = (V.row(F(i,2))-V.row(F(i,0))).norm();
-      l(i,2) = (V.row(F(i,0))-V.row(F(i,1))).norm();
-    }
-    Matrix<Scalar,Dynamic,1> dblA;
-    doublearea(l,0.,dblA);
-
-    switch(eff_type)
-    {
-      case MASSMATRIX_TYPE_BARYCENTRIC:
-        // diagonal entries for each face corner
-        MI.resize(m*3,1); MJ.resize(m*3,1); MV.resize(m*3,1);
-        MI.block(0*m,0,m,1) = F.col(0);
-        MI.block(1*m,0,m,1) = F.col(1);
-        MI.block(2*m,0,m,1) = F.col(2);
-        MJ = MI;
-        repmat(dblA,3,1,MV);
-        MV.array() /= 6.0;
-        break;
-      case MASSMATRIX_TYPE_VORONOI:
-        {
-          // diagonal entries for each face corner
-          // http://www.alecjacobson.com/weblog/?p=874
-          MI.resize(m*3,1); MJ.resize(m*3,1); MV.resize(m*3,1);
-          MI.block(0*m,0,m,1) = F.col(0);
-          MI.block(1*m,0,m,1) = F.col(1);
-          MI.block(2*m,0,m,1) = F.col(2);
-          MJ = MI;
-
-          // Holy shit this needs to be cleaned up and optimized
-          Matrix<Scalar,Dynamic,3> cosines(m,3);
-          cosines.col(0) = 
-            (l.col(2).array().pow(2)+l.col(1).array().pow(2)-l.col(0).array().pow(2))/(l.col(1).array()*l.col(2).array()*2.0);
-          cosines.col(1) = 
-            (l.col(0).array().pow(2)+l.col(2).array().pow(2)-l.col(1).array().pow(2))/(l.col(2).array()*l.col(0).array()*2.0);
-          cosines.col(2) = 
-            (l.col(1).array().pow(2)+l.col(0).array().pow(2)-l.col(2).array().pow(2))/(l.col(0).array()*l.col(1).array()*2.0);
-          Matrix<Scalar,Dynamic,3> barycentric = cosines.array() * l.array();
-          normalize_row_sums(barycentric,barycentric);
-          Matrix<Scalar,Dynamic,3> partial = barycentric;
-          partial.col(0).array() *= dblA.array() * 0.5;
-          partial.col(1).array() *= dblA.array() * 0.5;
-          partial.col(2).array() *= dblA.array() * 0.5;
-          Matrix<Scalar,Dynamic,3> quads(partial.rows(),partial.cols());
-          quads.col(0) = (partial.col(1)+partial.col(2))*0.5;
-          quads.col(1) = (partial.col(2)+partial.col(0))*0.5;
-          quads.col(2) = (partial.col(0)+partial.col(1))*0.5;
-
-          quads.col(0) = (cosines.col(0).array()<0).select( 0.25*dblA,quads.col(0));
-          quads.col(1) = (cosines.col(0).array()<0).select(0.125*dblA,quads.col(1));
-          quads.col(2) = (cosines.col(0).array()<0).select(0.125*dblA,quads.col(2));
-
-          quads.col(0) = (cosines.col(1).array()<0).select(0.125*dblA,quads.col(0));
-          quads.col(1) = (cosines.col(1).array()<0).select(0.25*dblA,quads.col(1));
-          quads.col(2) = (cosines.col(1).array()<0).select(0.125*dblA,quads.col(2));
-
-          quads.col(0) = (cosines.col(2).array()<0).select(0.125*dblA,quads.col(0));
-          quads.col(1) = (cosines.col(2).array()<0).select(0.125*dblA,quads.col(1));
-          quads.col(2) = (cosines.col(2).array()<0).select( 0.25*dblA,quads.col(2));
-
-          MV.block(0*m,0,m,1) = quads.col(0);
-          MV.block(1*m,0,m,1) = quads.col(1);
-          MV.block(2*m,0,m,1) = quads.col(2);
-          
-          break;
-        }
-      case MASSMATRIX_TYPE_FULL:
-        assert(false && "Implementation incomplete");
-        break;
-      default:
-        assert(false && "Unknown Mass matrix eff_type");
-    }
-
+    Matrix<Scalar,Dynamic,3> l;
+    igl::edge_lengths(V,F,l);
+    return massmatrix_intrinsic(l,F,type,M);
   }else if(simplex_size == 4)
   {
+    Matrix<int,Dynamic,1> MI;
+    Matrix<int,Dynamic,1> MJ;
+    Matrix<Scalar,Dynamic,1> MV;
     assert(V.cols() == 3);
     assert(eff_type == MASSMATRIX_TYPE_BARYCENTRIC);
     MI.resize(m*4,1); MJ.resize(m*4,1); MV.resize(m*4,1);
@@ -145,12 +73,12 @@ IGL_INLINE void igl::massmatrix(
       MV(i+2*m) = v/4.0;
       MV(i+3*m) = v/4.0;
     }
+    sparse(MI,MJ,MV,n,n,M);
   }else
   {
     // Unsupported simplex size
     assert(false && "Unsupported simplex size");
   }
-  sparse(MI,MJ,MV,n,n,M);
 }
 
 #ifdef IGL_STATIC_LIBRARY

+ 2 - 3
include/igl/massmatrix.h

@@ -5,11 +5,10 @@
 // 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_MASSMATRIX_TYPE_H
-#define IGL_MASSMATRIX_TYPE_H
+#ifndef IGL_MASSMATRIX_H
+#define IGL_MASSMATRIX_H
 #include "igl_inline.h"
 
-#define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
 #include <Eigen/Dense>
 #include <Eigen/Sparse>
 

+ 128 - 0
include/igl/massmatrix_intrinsic.cpp

@@ -0,0 +1,128 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "massmatrix_intrinsic.h"
+#include "edge_lengths.h"
+#include "normalize_row_sums.h"
+#include "sparse.h"
+#include "doublearea.h"
+#include "repmat.h"
+#include <Eigen/Geometry>
+#include <iostream>
+#include <cassert>
+
+template <typename Derivedl, typename DerivedF, typename Scalar>
+IGL_INLINE void igl::massmatrix_intrinsic(
+  const Eigen::MatrixBase<Derivedl> & l, 
+  const Eigen::MatrixBase<DerivedF> & F, 
+  const MassMatrixType type,
+  Eigen::SparseMatrix<Scalar>& M)
+{
+  const int n = F.maxCoeff()+1;
+  return massmatrix_intrinsic(l,F,type,n,M);
+}
+
+template <typename Derivedl, typename DerivedF, typename Scalar>
+IGL_INLINE void igl::massmatrix_intrinsic(
+  const Eigen::MatrixBase<Derivedl> & l, 
+  const Eigen::MatrixBase<DerivedF> & F, 
+  const MassMatrixType type,
+  const int n,
+  Eigen::SparseMatrix<Scalar>& M)
+{
+  using namespace Eigen;
+  using namespace std;
+  MassMatrixType eff_type = type;
+  const int m = F.rows();
+  const int simplex_size = F.cols();
+  // Use voronoi of for triangles by default, otherwise barycentric
+  if(type == MASSMATRIX_TYPE_DEFAULT)
+  {
+    eff_type = (simplex_size == 3?MASSMATRIX_TYPE_VORONOI:MASSMATRIX_TYPE_BARYCENTRIC);
+  }
+  assert(F.cols() == 3 && "only triangles supported");
+  Matrix<Scalar,Dynamic,1> dblA;
+  doublearea(l,0.,dblA);
+  Matrix<int,Dynamic,1> MI;
+  Matrix<int,Dynamic,1> MJ;
+  Matrix<Scalar,Dynamic,1> MV;
+
+  switch(eff_type)
+  {
+    case MASSMATRIX_TYPE_BARYCENTRIC:
+      // diagonal entries for each face corner
+      MI.resize(m*3,1); MJ.resize(m*3,1); MV.resize(m*3,1);
+      MI.block(0*m,0,m,1) = F.col(0);
+      MI.block(1*m,0,m,1) = F.col(1);
+      MI.block(2*m,0,m,1) = F.col(2);
+      MJ = MI;
+      repmat(dblA,3,1,MV);
+      MV.array() /= 6.0;
+      break;
+    case MASSMATRIX_TYPE_VORONOI:
+      {
+        // diagonal entries for each face corner
+        // http://www.alecjacobson.com/weblog/?p=874
+        MI.resize(m*3,1); MJ.resize(m*3,1); MV.resize(m*3,1);
+        MI.block(0*m,0,m,1) = F.col(0);
+        MI.block(1*m,0,m,1) = F.col(1);
+        MI.block(2*m,0,m,1) = F.col(2);
+        MJ = MI;
+
+        // Holy shit this needs to be cleaned up and optimized
+        Matrix<Scalar,Dynamic,3> cosines(m,3);
+        cosines.col(0) = 
+          (l.col(2).array().pow(2)+l.col(1).array().pow(2)-l.col(0).array().pow(2))/(l.col(1).array()*l.col(2).array()*2.0);
+        cosines.col(1) = 
+          (l.col(0).array().pow(2)+l.col(2).array().pow(2)-l.col(1).array().pow(2))/(l.col(2).array()*l.col(0).array()*2.0);
+        cosines.col(2) = 
+          (l.col(1).array().pow(2)+l.col(0).array().pow(2)-l.col(2).array().pow(2))/(l.col(0).array()*l.col(1).array()*2.0);
+        Matrix<Scalar,Dynamic,3> barycentric = cosines.array() * l.array();
+        normalize_row_sums(barycentric,barycentric);
+        Matrix<Scalar,Dynamic,3> partial = barycentric;
+        partial.col(0).array() *= dblA.array() * 0.5;
+        partial.col(1).array() *= dblA.array() * 0.5;
+        partial.col(2).array() *= dblA.array() * 0.5;
+        Matrix<Scalar,Dynamic,3> quads(partial.rows(),partial.cols());
+        quads.col(0) = (partial.col(1)+partial.col(2))*0.5;
+        quads.col(1) = (partial.col(2)+partial.col(0))*0.5;
+        quads.col(2) = (partial.col(0)+partial.col(1))*0.5;
+
+        quads.col(0) = (cosines.col(0).array()<0).select( 0.25*dblA,quads.col(0));
+        quads.col(1) = (cosines.col(0).array()<0).select(0.125*dblA,quads.col(1));
+        quads.col(2) = (cosines.col(0).array()<0).select(0.125*dblA,quads.col(2));
+
+        quads.col(0) = (cosines.col(1).array()<0).select(0.125*dblA,quads.col(0));
+        quads.col(1) = (cosines.col(1).array()<0).select(0.25*dblA,quads.col(1));
+        quads.col(2) = (cosines.col(1).array()<0).select(0.125*dblA,quads.col(2));
+
+        quads.col(0) = (cosines.col(2).array()<0).select(0.125*dblA,quads.col(0));
+        quads.col(1) = (cosines.col(2).array()<0).select(0.125*dblA,quads.col(1));
+        quads.col(2) = (cosines.col(2).array()<0).select( 0.25*dblA,quads.col(2));
+
+        MV.block(0*m,0,m,1) = quads.col(0);
+        MV.block(1*m,0,m,1) = quads.col(1);
+        MV.block(2*m,0,m,1) = quads.col(2);
+        
+        break;
+      }
+    case MASSMATRIX_TYPE_FULL:
+      assert(false && "Implementation incomplete");
+      break;
+    default:
+      assert(false && "Unknown Mass matrix eff_type");
+  }
+  sparse(MI,MJ,MV,n,n,M);
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template instantiation
+template void igl::massmatrix_intrinsic<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 4, 0, -1, 4>, double>(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 4, 0, -1, 4> > const&, igl::MassMatrixType, Eigen::SparseMatrix<double, 0, int>&);
+template void igl::massmatrix_intrinsic<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double>(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, igl::MassMatrixType, Eigen::SparseMatrix<double, 0, int>&);
+template void igl::massmatrix_intrinsic<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3>, double>(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, igl::MassMatrixType, Eigen::SparseMatrix<double, 0, int>&);
+template void igl::massmatrix_intrinsic<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, double>(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, igl::MassMatrixType, Eigen::SparseMatrix<double, 0, int>&);
+#endif

+ 56 - 0
include/igl/massmatrix_intrinsic.h

@@ -0,0 +1,56 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_MASSMATRIX_INTRINSIC_H
+#define IGL_MASSMATRIX_INTRINSIC_H
+#include "igl_inline.h"
+#include "massmatrix.h"
+
+#include <Eigen/Dense>
+#include <Eigen/Sparse>
+
+namespace igl 
+{
+
+  // Constructs the mass (area) matrix for a given mesh (V,F).
+  //
+  // Inputs:
+  //   l  #l by simplex_size list of mesh edge lengths
+  //   F  #F by simplex_size list of mesh elements (triangles or tetrahedra)
+  //   type  one of the following ints:
+  //     MASSMATRIX_TYPE_BARYCENTRIC  barycentric
+  //     MASSMATRIX_TYPE_VORONOI voronoi-hybrid {default}
+  //     MASSMATRIX_TYPE_FULL full {not implemented}
+  // Outputs: 
+  //   M  #V by #V mass matrix
+  //
+  // See also: adjacency_matrix
+  //
+  template <typename Derivedl, typename DerivedF, typename Scalar>
+  IGL_INLINE void massmatrix_intrinsic(
+    const Eigen::MatrixBase<Derivedl> & l, 
+    const Eigen::MatrixBase<DerivedF> & F, 
+    const MassMatrixType type,
+    Eigen::SparseMatrix<Scalar>& M);
+  // Inputs:
+  //   n  number of vertices (>= F.maxCoeff()+1)
+  template <typename Derivedl, typename DerivedF, typename Scalar>
+  IGL_INLINE void massmatrix_intrinsic(
+    const Eigen::MatrixBase<Derivedl> & l, 
+    const Eigen::MatrixBase<DerivedF> & F, 
+    const MassMatrixType type,
+    const int n,
+    Eigen::SparseMatrix<Scalar>& M);
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "massmatrix_intrinsic.cpp"
+#endif
+
+#endif
+
+

+ 7 - 0
include/igl/matlab_format.cpp

@@ -114,6 +114,12 @@ IGL_INLINE const std::string igl::matlab_format(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
 // generated by autoexplicit.sh
+template Eigen::WithFormat<Eigen::CwiseUnaryOp<Eigen::internal::scalar_cast_op<bool, int>, Eigen::Matrix<bool, -1, 3, 0, -1, 3> const> > const igl::matlab_format<Eigen::CwiseUnaryOp<Eigen::internal::scalar_cast_op<bool, int>, Eigen::Matrix<bool, -1, 3, 0, -1, 3> const> >(Eigen::DenseBase<Eigen::CwiseUnaryOp<Eigen::internal::scalar_cast_op<bool, int>, Eigen::Matrix<bool, -1, 3, 0, -1, 3> const> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >);
+// generated by autoexplicit.sh
+template Eigen::WithFormat<Eigen::CwiseUnaryOp<Eigen::internal::scalar_add_op<int>, Eigen::ArrayWrapper<Eigen::Matrix<int, -1, -1, 0, -1, -1> const> const> > const igl::matlab_format<Eigen::CwiseUnaryOp<Eigen::internal::scalar_add_op<int>, Eigen::ArrayWrapper<Eigen::Matrix<int, -1, -1, 0, -1, -1> const> const> >(Eigen::DenseBase<Eigen::CwiseUnaryOp<Eigen::internal::scalar_add_op<int>, Eigen::ArrayWrapper<Eigen::Matrix<int, -1, -1, 0, -1, -1> const> const> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >);
+// generated by autoexplicit.sh
+template Eigen::WithFormat<Eigen::CwiseUnaryOp<Eigen::internal::scalar_add_op<int>, Eigen::ArrayWrapper<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const> > const igl::matlab_format<Eigen::CwiseUnaryOp<Eigen::internal::scalar_add_op<int>, Eigen::ArrayWrapper<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const> >(Eigen::DenseBase<Eigen::CwiseUnaryOp<Eigen::internal::scalar_add_op<int>, Eigen::ArrayWrapper<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >);
+// generated by autoexplicit.sh
 template Eigen::WithFormat<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const igl::matlab_format<Eigen::Matrix<float, 1, 3, 1, 1, 3> >(Eigen::DenseBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >);
 // generated by autoexplicit.sh
 template Eigen::WithFormat<Eigen::Matrix<int, 4, 1, 0, 4, 1> > const igl::matlab_format<Eigen::Matrix<int, 4, 1, 0, 4, 1> >(Eigen::DenseBase<Eigen::Matrix<int, 4, 1, 0, 4, 1> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >);
@@ -152,4 +158,5 @@ template Eigen::WithFormat<Eigen::Matrix<double, 3, 2, 0, 3, 2> > const igl::mat
 template Eigen::WithFormat<Eigen::Matrix<float, -1, 1, 0, -1, 1> > const igl::matlab_format<Eigen::Matrix<float, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<float, -1, 1, 0, -1, 1> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >);
 template Eigen::WithFormat<Eigen::Matrix<int, 2, 2, 0, 2, 2> > const igl::matlab_format<Eigen::Matrix<int, 2, 2, 0, 2, 2> >(Eigen::DenseBase<Eigen::Matrix<int, 2, 2, 0, 2, 2> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >);
 template Eigen::WithFormat<Eigen::Matrix<float, 4, 4, 0, 4, 4> > const igl::matlab_format<Eigen::Matrix<float, 4, 4, 0, 4, 4> >(Eigen::DenseBase<Eigen::Matrix<float, 4, 4, 0, 4, 4> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >);
+template Eigen::WithFormat<Eigen::Matrix<bool, -1, 1, 0, -1, 1> > const igl::matlab_format<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >);
 #endif

+ 2 - 1
include/igl/min_quad_with_fixed.cpp

@@ -582,7 +582,8 @@ IGL_INLINE bool igl::min_quad_with_fixed(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
-// generated by autoexplicit.sh
+template bool igl::min_quad_with_fixed_solve<double, Eigen::CwiseUnaryOp<Eigen::internal::scalar_multiple_op<double>, Eigen::Matrix<double, -1, 1, 0, -1, 1> const>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(igl::min_quad_with_fixed_data<double> const&, Eigen::MatrixBase<Eigen::CwiseUnaryOp<Eigen::internal::scalar_multiple_op<double>, Eigen::Matrix<double, -1, 1, 0, -1, 1> const> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
+template bool igl::min_quad_with_fixed_solve<double, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<double>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(igl::min_quad_with_fixed_data<double> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<double>, Eigen::Matrix<double, -1, 1, 0, -1, 1> > > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 template bool igl::min_quad_with_fixed<double, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::SparseMatrix<double, 0, int> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<double, 0, int> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 template bool igl::min_quad_with_fixed_solve<double, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(igl::min_quad_with_fixed_data<double> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 template bool igl::min_quad_with_fixed_precompute<double, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::SparseMatrix<double, 0, int> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::SparseMatrix<double, 0, int> const&, bool, igl::min_quad_with_fixed_data<double>&);

+ 1 - 1
include/igl/next_filename.h

@@ -17,7 +17,7 @@ namespace igl
   // Inputs:
   //   prefix  path to containing dir and filename prefix
   //   zeros number of leading zeros as if digit printed with printf
-  //   suffix  suffix of filename and extension (should included dot)
+  //   suffix  suffix of filename and extension (should include dot)
   // Outputs:
   //   next  path to next file
   // Returns true if found, false if exceeding range in zeros

+ 10 - 2
include/igl/opengl/ViewerData.h

@@ -19,6 +19,14 @@
 // Alec: This is a mesh class containing a variety of data types (normals,
 // overlays, material colors, etc.)
 //
+// WARNING: Eigen data members (such as Eigen::Vector4f) should explicitly
+// disable alignment (e.g. use `Eigen::Matrix<float, 4, 1, Eigen::DontAlign>`),
+// in order to avoid alignment issues further down the line (esp. if the
+// structure are stored in a std::vector).
+//
+// See this thread for a more detailed discussion:
+// https://github.com/libigl/libigl/pull/1029
+//
 namespace igl
 {
 
@@ -105,7 +113,7 @@ public:
   //   C  #E|1 by 3 color(s)
   IGL_INLINE void set_edges (const Eigen::MatrixXd& P, const Eigen::MatrixXi& E, const Eigen::MatrixXd& C);
   // Alec: This is very confusing. Why does add_edges have a different API from
-  // set_edges? 
+  // set_edges?
   IGL_INLINE void add_edges (const Eigen::MatrixXd& P1, const Eigen::MatrixXd& P2, const Eigen::MatrixXd& C);
   IGL_INLINE void add_label (const Eigen::VectorXd& P,  const std::string& str);
 
@@ -192,7 +200,7 @@ public:
   // Point size / line width
   float point_size;
   float line_width;
-  Eigen::Vector4f line_color;
+  Eigen::Matrix<float, 4, 1, Eigen::DontAlign> line_color;
 
   // Shape material
   float shininess;

+ 5 - 4
include/igl/oriented_facets.h

@@ -12,14 +12,15 @@
 namespace igl
 {
   // ORIENTED_FACETS Determines all "directed
-  // [facets](https://en.wikipedia.org/wiki/Simplex#Elements)" of a given set
-  // of simplicial elements. For a manifold triangle mesh, this computes all
+  // [facets](https://en.wikipedia.org/wiki/Simplex#Elements)" of a given set of
+  // simplicial elements. For a manifold triangle mesh, this computes all
   // half-edges. For a manifold tetrahedral mesh, this computes all half-faces.
   //
   // Inputs:
-  //   F  #F by simplex_size list of simplices
+  //   F  #F by simplex_size  list of simplices
   // Outputs:
-  //   E  #E by simplex_size-1  list of facets
+  //   E  #E by simplex_size-1  list of facets, such that E.row(f+#F*c) is the
+  //     facet opposite F(f,c)
   //
   // Note: this is not the same as igl::edges because this includes every
   // directed edge including repeats (meaning interior edges on a surface will

+ 3 - 0
include/igl/per_face_normals.cpp

@@ -105,6 +105,8 @@ IGL_INLINE void igl::per_face_normals_stable(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
+// Nonsense template
+namespace igl{template<> void per_face_normals<Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&){} }
 // generated by autoexplicit.sh
 template void igl::per_face_normals<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<float, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&);
 // generated by autoexplicit.sh
@@ -122,6 +124,7 @@ template void igl::per_face_normals<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eige
 template void igl::per_face_normals<Eigen::Matrix<float, -1, -1, 1, -1, -1>, Eigen::Matrix<unsigned int, -1, -1, 1, -1, -1>, Eigen::Matrix<float, -1, -1, 1, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 1, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<unsigned int, -1, -1, 1, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 1, -1, -1> >&);
 template void igl::per_face_normals<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3>, Eigen::Matrix<float, -1, 3, 1, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&);
 template void igl::per_face_normals<class Eigen::Matrix<double,-1,3,0,-1,3>,class Eigen::Matrix<int,-1,-1,0,-1,-1>,class Eigen::Matrix<double,-1,-1,0,-1,-1> >(class Eigen::MatrixBase<class Eigen::Matrix<double,-1,3,0,-1,3> > const &,class Eigen::MatrixBase<class Eigen::Matrix<int,-1,-1,0,-1,-1> > const &,class Eigen::PlainObjectBase<class Eigen::Matrix<double,-1,-1,0,-1,-1> > &);
+template void igl::per_face_normals<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, 2, 3, 0, 2, 3>, Eigen::Matrix<double, 2, 3, 0, 2, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, 2, 3, 0, 2, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 2, 3, 0, 2, 3> >&);
 template void igl::per_face_normals_stable<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::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 template void igl::per_face_normals_stable<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
 template void igl::per_face_normals_stable<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::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);

+ 1 - 1
include/igl/principal_curvature.cpp

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

+ 3 - 3
include/igl/project.cpp

@@ -31,7 +31,7 @@ Eigen::Matrix<Scalar,3,1> igl::project(
 
 template <typename DerivedV, typename DerivedM, typename DerivedN, typename DerivedO, typename DerivedP>
 IGL_INLINE void igl::project(
-  const    Eigen::PlainObjectBase<DerivedV>&  V,
+  const    Eigen::MatrixBase<DerivedV>&  V,
   const    Eigen::MatrixBase<DerivedM>& model,
   const    Eigen::MatrixBase<DerivedN>& proj,
   const    Eigen::MatrixBase<DerivedO>&  viewport,
@@ -54,6 +54,6 @@ IGL_INLINE void igl::project(
 // Explicit template instantiation
 template Eigen::Matrix<double, 3, 1, 0, 3, 1> igl::project<double>(Eigen::Matrix<double, 3, 1, 0, 3, 1> const&, Eigen::Matrix<double, 4, 4, 0, 4, 4> const&, Eigen::Matrix<double, 4, 4, 0, 4, 4> const&, Eigen::Matrix<double, 4, 1, 0, 4, 1> const&);
 template Eigen::Matrix<float, 3, 1, 0, 3, 1> igl::project<float>(Eigen::Matrix<float, 3, 1, 0, 3, 1> const&, Eigen::Matrix<float, 4, 4, 0, 4, 4> const&, Eigen::Matrix<float, 4, 4, 0, 4, 4> const&, Eigen::Matrix<float, 4, 1, 0, 4, 1> const&);
-template void igl::project<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, 4, 4, 0, 4, 4>, Eigen::Matrix<float, 4, 4, 0, 4, 4>, Eigen::Matrix<float, 4, 1, 0, 4, 1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>>(const Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1>>&, const Eigen::MatrixBase<Eigen::Matrix<float, 4, 4, 0, 4, 4>>&, const Eigen::MatrixBase<Eigen::Matrix<float, 4, 4, 0, 4, 4>>&, const Eigen::MatrixBase<Eigen::Matrix<float, 4, 1, 0, 4, 1>>&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1>>&);
-template void igl::project<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 4, 4, 0, 4, 4>, Eigen::Matrix<double, 4, 4, 0, 4, 4>, Eigen::Matrix<double, 4, 1, 0, 4, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>>(const Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>>&, const Eigen::MatrixBase<Eigen::Matrix<double, 4, 4, 0, 4, 4>>&, const Eigen::MatrixBase<Eigen::Matrix<double, 4, 4, 0, 4, 4>>&, const Eigen::MatrixBase<Eigen::Matrix<double, 4, 1, 0, 4, 1>>&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>>&);
+template void igl::project<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, 4, 4, 0, 4, 4>, Eigen::Matrix<float, 4, 4, 0, 4, 4>, Eigen::Matrix<float, 4, 1, 0, 4, 1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>>(const Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1>>&, const Eigen::MatrixBase<Eigen::Matrix<float, 4, 4, 0, 4, 4>>&, const Eigen::MatrixBase<Eigen::Matrix<float, 4, 4, 0, 4, 4>>&, const Eigen::MatrixBase<Eigen::Matrix<float, 4, 1, 0, 4, 1>>&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1>>&);
+template void igl::project<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 4, 4, 0, 4, 4>, Eigen::Matrix<double, 4, 4, 0, 4, 4>, Eigen::Matrix<double, 4, 1, 0, 4, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>>(const Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>>&, const Eigen::MatrixBase<Eigen::Matrix<double, 4, 4, 0, 4, 4>>&, const Eigen::MatrixBase<Eigen::Matrix<double, 4, 4, 0, 4, 4>>&, const Eigen::MatrixBase<Eigen::Matrix<double, 4, 1, 0, 4, 1>>&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>>&);
 #endif

+ 1 - 1
include/igl/project.h

@@ -34,7 +34,7 @@ namespace igl
   //   P  #V by 3 list of screen space points
   template <typename DerivedV, typename DerivedM, typename DerivedN, typename DerivedO, typename DerivedP>
   IGL_INLINE void project(
-    const    Eigen::PlainObjectBase<DerivedV>&  V,
+    const    Eigen::MatrixBase<DerivedV>&  V,
     const    Eigen::MatrixBase<DerivedM>& model,
     const    Eigen::MatrixBase<DerivedN>& proj,
     const    Eigen::MatrixBase<DerivedO>&  viewport,

+ 1 - 0
include/igl/remove_unreferenced.cpp

@@ -120,4 +120,5 @@ template void igl::remove_unreferenced<Eigen::Matrix<double, -1, 3, 0, -1, 3>, E
 template void igl::remove_unreferenced<Eigen::Matrix<double, -1, 3, 0, -1, 3>, 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::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > 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::remove_unreferenced<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<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > 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> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::remove_unreferenced<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::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > 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::remove_unreferenced<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::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > 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> >&);
 #endif

+ 1 - 1
include/igl/rotate_vectors.h

@@ -12,7 +12,7 @@
 #include <Eigen/Core>
 namespace igl
 {
-  // Rotate the vectors V by A radiants on the tangent plane spanned by B1 and
+  // Rotate the vectors V by A radians on the tangent plane spanned by B1 and
   // B2
   //
   // Inputs:

+ 1 - 1
include/igl/scaf.cpp

@@ -704,4 +704,4 @@ IGL_INLINE Eigen::MatrixXd igl::scaf_solve(SCAFData &s, int iter_num)
 }
 
 #ifdef IGL_STATIC_LIBRARY
-#endif
+#endif

+ 38 - 38
include/igl/segment_segment_intersect.cpp

@@ -11,55 +11,55 @@
 
 template<typename DerivedSource, typename DerivedDir>
 IGL_INLINE bool igl::segments_intersect(
-        const Eigen::PlainObjectBase <DerivedSource> &p,
-        const Eigen::PlainObjectBase <DerivedDir> &r,
-        const Eigen::PlainObjectBase <DerivedSource> &q,
-        const Eigen::PlainObjectBase <DerivedDir> &s,
-        double &a_t,
-        double &a_u,
-        double eps
+  const Eigen::PlainObjectBase <DerivedSource> &p,
+  const Eigen::PlainObjectBase <DerivedDir> &r,
+  const Eigen::PlainObjectBase <DerivedSource> &q,
+  const Eigen::PlainObjectBase <DerivedDir> &s,
+  double &a_t,
+  double &a_u,
+  double eps
 )
 {
-    // http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect
-    // Search intersection between two segments
-    // p + t*r :  t \in [0,1]
-    // q + u*s :  u \in [0,1]
+  // http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect
+  // Search intersection between two segments
+  // p + t*r :  t \in [0,1]
+  // q + u*s :  u \in [0,1]
 
-    // p + t * r = q + u * s  // x s
-    // t(r x s) = (q - p) x s
-    // t = (q - p) x s / (r x s)
+  // p + t * r = q + u * s  // x s
+  // t(r x s) = (q - p) x s
+  // t = (q - p) x s / (r x s)
 
-    // (r x s) ~ 0 --> directions are parallel, they will never cross
-    Eigen::RowVector3d rxs = r.cross(s);
-    if (rxs.norm() <= eps)
-        return false;
+  // (r x s) ~ 0 --> directions are parallel, they will never cross
+  Eigen::RowVector3d rxs = r.cross(s);
+  if (rxs.norm() <= eps)
+    return false;
 
-    int sign;
+  int sign;
 
-    double u;
-    // u = (q − p) × r / (r × s)
-    Eigen::RowVector3d u1 = (q - p).cross(r);
-    sign = ((u1.dot(rxs)) > 0) ? 1 : -1;
-    u = u1.norm() / rxs.norm();
-    u = u * sign;
+  double u;
+  // u = (q − p) × r / (r × s)
+  Eigen::RowVector3d u1 = (q - p).cross(r);
+  sign = ((u1.dot(rxs)) > 0) ? 1 : -1;
+  u = u1.norm() / rxs.norm();
+  u = u * sign;
 
-    if ((u - 1.) > eps || u < -eps)
-        return false;
+  double t;
+  // t = (q - p) x s / (r x s)
+  Eigen::RowVector3d t1 = (q - p).cross(s);
+  sign = ((t1.dot(rxs)) > 0) ? 1 : -1;
+  t = t1.norm() / rxs.norm();
+  t = t * sign;
 
-    double t;
-    // t = (q - p) x s / (r x s)
-    Eigen::RowVector3d t1 = (q - p).cross(s);
-    sign = ((t1.dot(rxs)) > 0) ? 1 : -1;
-    t = t1.norm() / rxs.norm();
-    t = t * sign;
+  a_t = t;
+  a_u = u;
 
-    if (t < -eps || fabs(t) < eps)
-        return false;
+  if ((u - 1.) > eps || u < -eps)
+    return false;
 
-    a_t = t;
-    a_u = u;
+  if ((t - 1.) > eps || t < -eps)
+    return false;
 
-    return true;
+  return true;
 };
 
 #ifdef IGL_STATIC_LIBRARY

+ 1 - 1
include/igl/simplify_polyhedron.cpp

@@ -55,7 +55,7 @@ IGL_INLINE void igl::simplify_polyhedron(
       const auto vi = E(e,positive);
       const auto vj = E(e,!positive);
       p = V.row(vj);
-      std::vector<int> faces = igl::circulation(e,positive,F,E,EMAP,EF,EI);
+      std::vector<int> faces = igl::circulation(e,positive,EMAP,EF,EI);
       cost = 0;
       for(auto f : faces)
       {

+ 4 - 0
include/igl/slice.cpp

@@ -248,6 +248,8 @@ IGL_INLINE DerivedX igl::slice(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
 // generated by autoexplicit.sh
+template void igl::slice<Eigen::MatrixBase<Eigen::CwiseUnaryOp<Eigen::internal::scalar_multiple_op<double>, Eigen::Matrix<double, -1, 1, 0, -1, 1> const> >, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::CwiseUnaryOp<Eigen::internal::scalar_multiple_op<double>, Eigen::Matrix<double, -1, 1, 0, -1, 1> const> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
+// generated by autoexplicit.sh
 template void igl::slice<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<float, -1, 3, 1, -1, 3> >(Eigen::DenseBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&);
 // generated by autoexplicit.sh
 template void igl::slice<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 3, 1, -1, 3> >(Eigen::DenseBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> >&);
@@ -356,6 +358,8 @@ template void igl::slice<Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0,
 template void igl::slice<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::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::DenseBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
 template void igl::slice<unsigned int, unsigned int>(Eigen::SparseMatrix<unsigned int, 0, int> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::SparseMatrix<unsigned int, 0, int>&);
 template void igl::slice<Eigen::SparseMatrix<double, 0, int>, Eigen::Array<int, -1, 1, 0, -1, 1>, Eigen::SparseMatrix<double, 0, int> >(Eigen::SparseMatrix<double, 0, int> const&, Eigen::DenseBase<Eigen::Array<int, -1, 1, 0, -1, 1> > const&, int, Eigen::SparseMatrix<double, 0, int>&);
+template void igl::slice<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Block<Eigen::Matrix<int, -1, -1, 0, -1, -1> const, -1, 1, true>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::DenseBase<Eigen::Block<Eigen::Matrix<int, -1, -1, 0, -1, -1> const, -1, 1, true> > const&, int, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
+template void igl::slice<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Block<Eigen::Matrix<int, -1, 1, 0, -1, 1> const, -1, 1, true>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::DenseBase<Eigen::Block<Eigen::Matrix<int, -1, 1, 0, -1, 1> const, -1, 1, true> > const&, int, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
 #ifdef WIN32
 template void igl::slice<class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, class Eigen::PlainObjectBase<class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>>>(class Eigen::Matrix<__int64, -1, 1, 0, -1, 1> const &, class Eigen::DenseBase<class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>> const &, int, class Eigen::PlainObjectBase<class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>> &);
 template void igl::slice<class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1>>, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1>>>(class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1>> const &, class Eigen::DenseBase<class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>> const &, int, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1>> &);

+ 2 - 0
include/igl/sort.cpp

@@ -317,6 +317,8 @@ if(!ascending)
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
 // generated by autoexplicit.sh
+template void igl::sort<Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::DenseBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+// generated by autoexplicit.sh
 template void igl::sort<Eigen::Matrix<int, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::DenseBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 // generated by autoexplicit.sh
 template void igl::sort<Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::DenseBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);

+ 2 - 0
include/igl/squared_edge_lengths.cpp

@@ -73,6 +73,8 @@ IGL_INLINE void igl::squared_edge_lengths(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
 // generated by autoexplicit.sh
+template void igl::squared_edge_lengths<Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
+// generated by autoexplicit.sh
 template void igl::squared_edge_lengths<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&);
 // generated by autoexplicit.sh
 template void igl::squared_edge_lengths<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<float, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&);

+ 37 - 0
include/igl/tan_half_angle.cpp

@@ -0,0 +1,37 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2018 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/.
+
+#include "tan_half_angle.h"
+#include <cmath>
+template < typename Scalar>
+IGL_INLINE Scalar igl::tan_half_angle(
+  const Scalar & a,
+  const Scalar & b,
+  const Scalar & c)
+{
+  //      .
+  //     /|
+  //   c/ |
+  //   /  |
+  //  /   |
+  // .α   | a
+  //  \   |
+  //   \  |
+  //   b\ |  
+  //     \| 
+  //
+  // tan(α/2)
+  // Fisher 2007
+  return sqrt(((a-b+c)*(a+b-c))/((a+b+c)*(-a+b+c)));
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template instantiation
+// generated by autoexplicit.sh
+template double igl::tan_half_angle<double>(double const&, double const&, double const&);
+#endif

+ 35 - 0
include/igl/tan_half_angle.h

@@ -0,0 +1,35 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2018 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_TAN_HALF_ANGLE_H
+#define IGL_TAN_HALF_ANGLE_H
+#include "igl_inline.h"
+namespace igl
+{
+  // TAN_HALF_ANGLE Compute the tangent of half of the angle opposite the side
+  // with length a, in a triangle with side lengths (a,b,c).
+  //
+  // Inputs:
+  //   a  scalar edge length of first side of triangle
+  //   b  scalar edge length of second side of triangle
+  //   c  scalar edge length of third side of triangle
+  // Returns tangent of half of the angle opposite side with length a
+  //
+  // See also: is_intrinsic_delaunay
+  template < typename Scalar>
+  IGL_INLINE Scalar tan_half_angle(
+    const Scalar & a,
+    const Scalar & b,
+    const Scalar & c);
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "tan_half_angle.cpp"
+#endif
+
+#endif
+

部分文件因文件數量過多而無法顯示