Browse Source

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

Former-commit-id: d196175456119bb8461815a0e1747112411d0ac0
Alec Jacobson 9 years ago
parent
commit
ada13bdb77
39 changed files with 1178 additions and 781 deletions
  1. 19 0
      .appveyor.yml
  2. 47 0
      .travis.yml
  3. 2 1
      README.md
  4. 1 1
      include/igl/angle_bound_frame_fields.cpp
  5. 13 10
      include/igl/colon.cpp
  6. 1 1
      include/igl/comb_cross_field.cpp
  7. 2 2
      include/igl/comb_line_field.cpp
  8. 34 1
      include/igl/copyleft/boolean/mesh_boolean.cpp
  9. 4 1
      include/igl/copyleft/cgal/SelfIntersectMesh.h
  10. 31 0
      include/igl/copyleft/cgal/cell_adjacency.cpp
  11. 50 0
      include/igl/copyleft/cgal/cell_adjacency.h
  12. 8 9
      include/igl/copyleft/cgal/extract_cells.cpp
  13. 61 21
      include/igl/copyleft/cgal/propagate_winding_numbers.cpp
  14. 37 0
      include/igl/copyleft/cgal/propagate_winding_numbers.h
  15. 121 0
      include/igl/copyleft/cgal/relabel_small_immersed_cells.cpp
  16. 59 0
      include/igl/copyleft/cgal/relabel_small_immersed_cells.h
  17. 79 82
      include/igl/copyleft/marching_cubes.cpp
  18. 10 10
      include/igl/copyleft/marching_cubes.h
  19. 2 2
      include/igl/copyleft/quadprog.cpp
  20. 2 2
      include/igl/cross_field_missmatch.cpp
  21. 1 1
      include/igl/cut_mesh.cpp
  22. 1 1
      include/igl/cut_mesh_from_singularities.cpp
  23. 3 0
      include/igl/eigs.cpp
  24. 3 1
      include/igl/embree/reorient_facets_raycast.h
  25. 1 1
      include/igl/line_field_missmatch.cpp
  26. 3 0
      include/igl/list_to_matrix.cpp
  27. 1 1
      include/igl/n_polyvector.cpp
  28. 472 473
      include/igl/n_polyvector_general.cpp
  29. 68 110
      include/igl/point_simplex_squared_distance.cpp
  30. 3 3
      include/igl/point_simplex_squared_distance.h
  31. 1 1
      include/igl/polyvector_field_matchings.cpp
  32. 15 17
      include/igl/project_to_line.cpp
  33. 12 15
      include/igl/project_to_line.h
  34. 4 6
      include/igl/project_to_line_segment.cpp
  35. 3 3
      include/igl/project_to_line_segment.h
  36. 3 3
      include/igl/writeOBJ.cpp
  37. 0 0
      include/igl/xml/serialization_test.skip
  38. 0 1
      scripts/pre-commit.sh
  39. 1 1
      tutorial/705_MarchingCubes/main.cpp

+ 19 - 0
.appveyor.yml

@@ -0,0 +1,19 @@
+version: 1.0.{build}
+os: Visual Studio 2015
+test: off
+clone_folder: C:\projects\libigl
+branches:
+  only:
+    - master
+install:
+  - git submodule update --init --recursive
+  - cinstall: python
+build_script:
+  - echo Running cmake...
+  - cd c:\projects\libigl\tutorial
+  - mkdir build
+  - cd build
+  - cmake -D "LIBIGL_USE_STATIC_LIBRARY=ON" -G "Visual Studio 14 2015 Win64" ../
+  - set MSBuildLogger="C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
+  - set MSBuildOptions=/v:m /p:Configuration=Release /logger:%MSBuildLogger%
+  - msbuild %MSBuildOptions% libigl_tutorials.sln

+ 47 - 0
.travis.yml

@@ -0,0 +1,47 @@
+language: cpp
+sudo: false
+matrix:
+  include:
+    - os: linux
+      compiler: gcc-4.8.1
+      script:
+        - git submodule update --init --recursive
+        - mkdir external/nanogui/ext/glfw/include/GL
+        - wget -P external/nanogui/ext/glfw/include/GL http://www.opengl.org/registry/api/GL/glcorearb.h
+        - cd tutorial
+        - mkdir build
+        - cd build
+        - cmake -DLIBIGL_USE_STATIC_LIBRARY=ON -DCMAKE_CXX_COMPILER=g++-4.8 ../
+        - make -j 2
+      addons:
+        apt:
+          sources:
+            - ubuntu-toolchain-r-test
+            - kalakris-cmake
+          packages:
+            - xorg-dev
+            - libglu1-mesa-dev
+            - g++-4.8
+            - cmake
+    #         - binutils
+    #         - libx11-dev
+    #         - mesa-common-dev
+    #         - libgl1-mesa-dev
+    #         - libglu1-mesa-dev
+    #         - libxrandr-dev
+    #         - libxi-dev
+    #         - libxmu-dev
+    #         - libblas-dev
+    #         - xorg-dev
+    - os: osx
+      compiler: clang
+      script:
+        - brew update
+        - brew upgrade cmake
+        - brew upgrade cgal
+        - git submodule update --init --recursive
+        - cd tutorial
+        - mkdir build
+        - cd build
+        - cmake -DLIBIGL_USE_STATIC_LIBRARY=ON ../
+        - make -j 2

+ 2 - 1
README.md

@@ -1,5 +1,6 @@
 # libigl - A simple C++ geometry processing library
-
+[![Build Status](https://travis-ci.org/libigl/libigl.svg?branch=master)](https://travis-ci.org/libigl/libigl)
+[![Build status](https://ci.appveyor.com/api/projects/status/mf3t9rnhco0vhly8?svg=true)](https://ci.appveyor.com/project/danielepanozzo/libigl-6hjk1)
 ![](libigl-teaser.png)
 
 <https://github.com/libigl/libigl/>

+ 1 - 1
include/igl/angle_bound_frame_fields.cpp

@@ -38,7 +38,7 @@ namespace igl {
       Eigen::VectorXi indInteriorToFull;
       Eigen::VectorXi indFullToInterior;
 
-#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
+//#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
       Eigen::PlainObjectBase<DerivedV> B1, B2, FN;
 
       //laplacians

+ 13 - 10
include/igl/colon.cpp

@@ -1,9 +1,9 @@
 // This file is part of libigl, a simple c++ geometry processing library.
-// 
+//
 // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "colon.h"
 
@@ -11,9 +11,9 @@
 
 template <typename L,typename S,typename H,typename T>
 IGL_INLINE void igl::colon(
-  const L low, 
-  const S step, 
-  const H hi, 
+  const L low,
+  const S step,
+  const H hi,
   Eigen::Matrix<T,Eigen::Dynamic,1> & I)
 {
   const int size = ((hi-low)/step)+1;
@@ -22,8 +22,8 @@ IGL_INLINE void igl::colon(
 
 template <typename L,typename H,typename T>
 IGL_INLINE void igl::colon(
-  const L low, 
-  const H hi, 
+  const L low,
+  const H hi,
   Eigen::Matrix<T,Eigen::Dynamic,1> & I)
 {
   return igl::colon(low,(T)1,hi,I);
@@ -31,7 +31,7 @@ IGL_INLINE void igl::colon(
 
 template <typename T,typename L,typename H>
 IGL_INLINE Eigen::Matrix<T,Eigen::Dynamic,1> igl::colon(
-  const L low, 
+  const L low,
   const H hi)
 {
   Eigen::Matrix<T,Eigen::Dynamic,1> I;
@@ -53,4 +53,7 @@ template void igl::colon<int, int, int>(int, int, Eigen::Matrix<int, -1, 1, 0, -
 template void igl::colon<int,long long int,int>(int,long long int,Eigen::Matrix<int,-1,1,0,-1,1> &);
 template void igl::colon<int, int, int, int>(int, int, int, Eigen::Matrix<int, -1, 1, 0, -1, 1>&);
 template void igl::colon<int, long, long>(int, long, Eigen::Matrix<long, -1, 1, 0, -1, 1>&);
+#ifdef WIN32
+template void igl::colon<int, long long,long>(int, long long, class Eigen::Matrix<long,-1,1,0,-1,1> &);
+#endif
 #endif

+ 1 - 1
include/igl/comb_cross_field.cpp

@@ -27,7 +27,7 @@ namespace igl {
     const Eigen::PlainObjectBase<DerivedF> &F;
     const Eigen::PlainObjectBase<DerivedV> &PD1;
     const Eigen::PlainObjectBase<DerivedV> &PD2;
-#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
+//#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
     Eigen::PlainObjectBase<DerivedV> N;
 
   private:

+ 2 - 2
include/igl/comb_line_field.cpp

@@ -25,12 +25,12 @@ public:
     const Eigen::PlainObjectBase<DerivedV> &V;
     const Eigen::PlainObjectBase<DerivedF> &F;
     const Eigen::PlainObjectBase<DerivedV> &PD1;
-#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
+//#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
     Eigen::PlainObjectBase<DerivedV> N;
 
 private:
     // internal
-#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
+//#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
     Eigen::PlainObjectBase<DerivedF> TT;
     Eigen::PlainObjectBase<DerivedF> TTi;
 

+ 34 - 1
include/igl/copyleft/boolean/mesh_boolean.cpp

@@ -12,8 +12,12 @@
 #include "../cgal/assign_scalar.h"
 #include "../cgal/propagate_winding_numbers.h"
 #include "../cgal/remesh_self_intersections.h"
+#include "../cgal/relabel_small_immersed_cells.h"
+#include "../cgal/extract_cells.h"
+#include "../../extract_manifold_patches.h"
 #include "../../remove_unreferenced.h"
 #include "../../unique_simplices.h"
+#include "../../unique_edge_map.h"
 #include "../../slice.h"
 #include "../../resolve_duplicated_faces.h"
 #include "../../get_seconds.h"
@@ -23,6 +27,7 @@
 
 //#define MESH_BOOLEAN_TIMING
 //#define DOUBLE_CHECK_EXACT_OUTPUT
+//#define SMALL_CELL_REMOVAL
 
 template <
   typename DerivedVA,
@@ -91,6 +96,28 @@ IGL_INLINE bool igl::copyleft::boolean::mesh_boolean(
   log_time("resolve_self_intersection");
 #endif
 
+  // Compute edges.
+  Eigen::MatrixXi E, uE;
+  Eigen::VectorXi EMAP;
+  std::vector<std::vector<size_t> > uE2E;
+  igl::unique_edge_map(F, E, uE, EMAP, uE2E);
+
+  // Compute patches
+  Eigen::VectorXi P;
+  const size_t num_patches = igl::extract_manifold_patches(F, EMAP, uE2E, P);
+#ifdef MESH_BOOLEAN_TIMING
+  log_time("patch_extraction");
+#endif
+
+  // Compute cells.
+  Eigen::MatrixXi per_patch_cells;
+  const size_t num_cells =
+    igl::copyleft::cgal::extract_cells(
+        V, F, P, E, uE, uE2E, EMAP, per_patch_cells);
+#ifdef MESH_BOOLEAN_TIMING
+  log_time("cell_extraction");
+#endif
+
   // Compute winding numbers on each side of each facet.
   const size_t num_faces = F.rows();
   Eigen::MatrixXi W;
@@ -101,7 +128,8 @@ IGL_INLINE bool igl::copyleft::boolean::mesh_boolean(
   if (num_faces > 0) 
   {
     valid = valid & 
-      igl::copyleft::cgal::propagate_winding_numbers(V, F, labels, W);
+      igl::copyleft::cgal::propagate_winding_numbers(
+          V, F, uE, uE2E, num_patches, P, num_cells, per_patch_cells, labels, W);
   } else 
   {
     W.resize(0, 4);
@@ -134,6 +162,11 @@ IGL_INLINE bool igl::copyleft::boolean::mesh_boolean(
   log_time("compute_output_winding_number");
 #endif
 
+#ifdef SMALL_CELL_REMOVAL
+  igl::copyleft::cgal::relabel_small_immersed_cells(V, F,
+          num_patches, P, num_cells, per_patch_cells, 1e-3, Wr);
+#endif
+
   // Extract boundary separating inside from outside.
   auto index_to_signed_index = [&](size_t i, bool ori) -> int
   {

+ 4 - 1
include/igl/copyleft/cgal/SelfIntersectMesh.h

@@ -393,10 +393,13 @@ inline igl::copyleft::cgal::SelfIntersectMesh<
     }
     // Otherwise just fall through
   }
-  process_intersecting_boxes();
 #ifdef IGL_SELFINTERSECTMESH_DEBUG
   log_time("box_intersection_d");
 #endif
+  process_intersecting_boxes();
+#ifdef IGL_SELFINTERSECTMESH_DEBUG
+  log_time("resolve_intersection");
+#endif
 
   // Convert lIF to Eigen matrix
   assert(lIF.size()%2 == 0);

+ 31 - 0
include/igl/copyleft/cgal/cell_adjacency.cpp

@@ -0,0 +1,31 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Qingnan Zhou <qnzhou@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+//
+
+#include "cell_adjacency.h"
+
+template <typename DerivedC>
+IGL_INLINE void igl::copyleft::cgal::cell_adjacency(
+    const Eigen::PlainObjectBase<DerivedC>& per_patch_cells,
+    const size_t num_cells,
+    std::vector<std::set<std::tuple<typename DerivedC::Scalar, bool, size_t> > >&
+    adjacency_list) {
+
+  const size_t num_patches = per_patch_cells.rows();
+  adjacency_list.resize(num_cells);
+  for (size_t i=0; i<num_patches; i++) {
+    const int positive_cell = per_patch_cells(i,0);
+    const int negative_cell = per_patch_cells(i,1);
+    adjacency_list[positive_cell].emplace(negative_cell, false, i);
+    adjacency_list[negative_cell].emplace(positive_cell, true, i);
+  }
+}
+
+#ifdef IGL_STATIC_LIBRARY
+template void igl::copyleft::cgal::cell_adjacency<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, unsigned long, std::__1::vector<std::__1::set<std::__1::tuple<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Scalar, bool, unsigned long>, std::__1::less<std::__1::tuple<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Scalar, bool, unsigned long> >, std::__1::allocator<std::__1::tuple<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Scalar, bool, unsigned long> > >, std::__1::allocator<std::__1::set<std::__1::tuple<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Scalar, bool, unsigned long>, std::__1::less<std::__1::tuple<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Scalar, bool, unsigned long> >, std::__1::allocator<std::__1::tuple<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Scalar, bool, unsigned long> > > > >&);
+#endif

+ 50 - 0
include/igl/copyleft/cgal/cell_adjacency.h

@@ -0,0 +1,50 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Qingnan Zhou <qnzhou@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+//
+#ifndef IGL_COPYLEFT_CGAL_CELL_ADJACENCY_H
+#define IGL_COPYLEFT_CGAL_CELL_ADJACENCY_H
+#include "../../igl_inline.h"
+#include <Eigen/Core>
+#include <set>
+#include <tuple>
+#include <vector>
+
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // Inputs:
+      //   per_patch_cells  #P by 2 list of cell labels on each side of each
+      //                    patch.  Cell labels are assumed to be continuous
+      //                    from 0 to #C.
+      //   num_cells        number of cells.
+      //
+      // Outputs:
+      //   adjacency_list  #C array of list of adjcent cell informations.  If
+      //                   cell i and cell j are adjacent via patch x, where i
+      //                   is on the positive side of x, and j is on the
+      //                   negative side.  Then,
+      //                   adjacency_list[i] will contain the entry {j, false, x}
+      //                   and
+      //                   adjacency_list[j] will contain the entry {i, true, x}
+      template < typename DerivedC >
+      IGL_INLINE void cell_adjacency(
+          const Eigen::PlainObjectBase<DerivedC>& per_patch_cells,
+          const size_t num_cells,
+          std::vector<std::set<std::tuple<typename DerivedC::Scalar, bool, size_t> > >&
+          adjacency_list);
+    }
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "cell_adjacency.cpp"
+#endif
+#endif

+ 8 - 9
include/igl/copyleft/cgal/extract_cells.cpp

@@ -154,12 +154,6 @@ IGL_INLINE size_t igl::copyleft::cgal::extract_cells(
   std::vector< std::vector<Kernel::Triangle_3 > > 
     triangle_lists(num_components);
   std::vector<std::vector<bool> > in_Is(num_components);
-  for (size_t i=0; i<num_components; i++)
-  {
-    Is[i].resize(components[i].size());
-    std::copy(components[i].begin(), components[i].end(),Is[i].data());
-    submesh_aabb_tree(V,F,Is[i],trees[i],triangle_lists[i],in_Is[i]);
-  }
 
   // Find outer facets, their orientations and cells for each component
   Eigen::VectorXi outer_facets(num_components);
@@ -167,6 +161,8 @@ IGL_INLINE size_t igl::copyleft::cgal::extract_cells(
   Eigen::VectorXi outer_cells(num_components);
   for (size_t i=0; i<num_components; i++)
   {
+    Is[i].resize(components[i].size());
+    std::copy(components[i].begin(), components[i].end(),Is[i].data());
     bool flipped;
     igl::copyleft::cgal::outer_facet(V, F, Is[i], outer_facets[i], flipped);
     outer_facet_orientation[i] = flipped?1:0;
@@ -194,9 +190,9 @@ IGL_INLINE size_t igl::copyleft::cgal::extract_cells(
     // construct bounding boxes for each component
     DerivedV bbox_min(num_components, 3);
     DerivedV bbox_max(num_components, 3);
-    // Why not just initialize to numeric_limits::min, numeric_limits::max?
-    bbox_min.rowwise() = V.colwise().maxCoeff().eval();
-    bbox_max.rowwise() = V.colwise().minCoeff().eval();
+    // Assuming our mesh (in exact numbers) fits in the range of double.
+    bbox_min.setConstant(std::numeric_limits<double>::max());
+    bbox_max.setConstant(std::numeric_limits<double>::min());
     // Loop over faces
     for (size_t i=0; i<num_faces; i++)
     {
@@ -240,6 +236,9 @@ IGL_INLINE size_t igl::copyleft::cgal::extract_cells(
       const size_t num_candidate_comps = candidate_comps.size();
       if (num_candidate_comps == 0) continue;
 
+      // Build aabb tree for this component.
+      submesh_aabb_tree(V,F,Is[i],trees[i],triangle_lists[i],in_Is[i]);
+
       // Get query points on each candidate component: barycenter of
       // outer-facet 
       DerivedV queries(num_candidate_comps, 3);

+ 61 - 21
include/igl/copyleft/cgal/propagate_winding_numbers.cpp

@@ -20,6 +20,7 @@
 #include "closest_facet.h"
 #include "assign_scalar.h"
 #include "extract_cells.h"
+#include "cell_adjacency.h"
 
 #include <stdexcept>
 #include <limits>
@@ -54,19 +55,11 @@ IGL_INLINE bool igl::copyleft::cgal::propagate_winding_numbers(
   };
   tictoc();
 #endif
-  const size_t num_faces = F.rows();
-  //typedef typename DerivedF::Scalar Index;
 
   Eigen::MatrixXi E, uE;
   Eigen::VectorXi EMAP;
   std::vector<std::vector<size_t> > uE2E;
   igl::unique_edge_map(F, E, uE, EMAP, uE2E);
-  bool valid = true;
-  if (!piecewise_constant_winding_number(F, uE, uE2E)) 
-  {
-    std::cerr << "Input mesh is not orientable!" << std::endl;
-    valid = false;
-  }
 
   Eigen::VectorXi P;
   const size_t num_patches = igl::extract_manifold_patches(F, EMAP, uE2E, P);
@@ -79,14 +72,61 @@ IGL_INLINE bool igl::copyleft::cgal::propagate_winding_numbers(
   log_time("cell_extraction");
 #endif
 
-  typedef std::tuple<size_t, bool, size_t> CellConnection;
-  std::vector<std::set<CellConnection> > cell_adjacency(num_cells);
-  for (size_t i=0; i<num_patches; i++) {
-    const int positive_cell = per_patch_cells(i,0);
-    const int negative_cell = per_patch_cells(i,1);
-    cell_adjacency[positive_cell].emplace(negative_cell, false, i);
-    cell_adjacency[negative_cell].emplace(positive_cell, true, i);
+  return propagate_winding_numbers(V, F,
+          uE, uE2E,
+          num_patches, P,
+          num_cells, per_patch_cells,
+          labels, W);
+}
+
+
+template<
+  typename DerivedV,
+  typename DerivedF,
+  typename DeriveduE,
+  typename uE2EType,
+  typename DerivedP,
+  typename DerivedC,
+  typename DerivedL,
+  typename DerivedW>
+IGL_INLINE bool igl::copyleft::cgal::propagate_winding_numbers(
+    const Eigen::PlainObjectBase<DerivedV>& V,
+    const Eigen::PlainObjectBase<DerivedF>& F,
+    const Eigen::PlainObjectBase<DeriveduE>& uE,
+    const std::vector<std::vector<uE2EType> >& uE2E,
+    const size_t num_patches,
+    const Eigen::PlainObjectBase<DerivedP>& P,
+    const size_t num_cells,
+    const Eigen::PlainObjectBase<DerivedC>& C,
+    const Eigen::PlainObjectBase<DerivedL>& labels,
+    Eigen::PlainObjectBase<DerivedW>& W)
+{
+#ifdef PROPAGATE_WINDING_NUMBER_TIMING
+  const auto & tictoc = []() -> double
+  {
+    static double t_start = igl::get_seconds();
+    double diff = igl::get_seconds()-t_start;
+    t_start += diff;
+    return diff;
+  };
+  const auto log_time = [&](const std::string& label) -> void {
+    std::cout << "propagate_winding_num." << label << ": "
+      << tictoc() << std::endl;
+  };
+  tictoc();
+#endif
+
+  bool valid = true;
+  if (!piecewise_constant_winding_number(F, uE, uE2E)) 
+  {
+    std::cerr << "Input mesh is not orientable!" << std::endl;
+    valid = false;
   }
+
+  const size_t num_faces = F.rows();
+  typedef std::tuple<typename DerivedC::Scalar, bool, size_t> CellConnection;
+  std::vector<std::set<CellConnection> > cell_adj;
+  igl::copyleft::cgal::cell_adjacency(C, num_cells, cell_adj);
 #ifdef PROPAGATE_WINDING_NUMBER_TIMING
   log_time("cell_connectivity");
 #endif
@@ -94,7 +134,7 @@ IGL_INLINE bool igl::copyleft::cgal::propagate_winding_numbers(
   auto save_cell = [&](const std::string& filename, size_t cell_id) -> void{
     std::vector<size_t> faces;
     for (size_t i=0; i<num_patches; i++) {
-      if ((per_patch_cells.row(i).array() == cell_id).any()) {
+      if ((C.row(i).array() == cell_id).any()) {
         for (size_t j=0; j<num_faces; j++) {
           if ((size_t)P[j] == i) {
             faces.push_back(j);
@@ -140,7 +180,7 @@ IGL_INLINE bool igl::copyleft::cgal::propagate_winding_numbers(
           size_t curr_idx = Q.front();
           Q.pop();
           int curr_label = cell_labels[curr_idx];
-          for (const auto& neighbor : cell_adjacency[curr_idx]) {
+          for (const auto& neighbor : cell_adj[curr_idx]) {
             if (cell_labels[std::get<0>(neighbor)] == 0) 
             {
               cell_labels[std::get<0>(neighbor)] = curr_label * -1;
@@ -191,7 +231,7 @@ IGL_INLINE bool igl::copyleft::cgal::propagate_winding_numbers(
 #endif
 
   const size_t outer_patch = P[outer_facet];
-  const size_t infinity_cell = per_patch_cells(outer_patch, flipped?1:0);
+  const size_t infinity_cell = C(outer_patch, flipped?1:0);
 
   Eigen::VectorXi patch_labels(num_patches);
   const int INVALID = std::numeric_limits<int>::max();
@@ -214,7 +254,7 @@ IGL_INLINE bool igl::copyleft::cgal::propagate_winding_numbers(
   while (!Q.empty()) {
     size_t curr_cell = Q.front();
     Q.pop();
-    for (const auto& neighbor : cell_adjacency[curr_cell]) {
+    for (const auto& neighbor : cell_adj[curr_cell]) {
       size_t neighbor_cell, patch_idx;
       bool direction;
       std::tie(neighbor_cell, direction, patch_idx) = neighbor;
@@ -258,8 +298,8 @@ IGL_INLINE bool igl::copyleft::cgal::propagate_winding_numbers(
   for (size_t i=0; i<num_faces; i++) 
   {
     const size_t patch = P[i];
-    const size_t positive_cell = per_patch_cells(patch, 0);
-    const size_t negative_cell = per_patch_cells(patch, 1);
+    const size_t positive_cell = C(patch, 0);
+    const size_t negative_cell = C(patch, 1);
     for (size_t j=0; j<num_labels; j++) {
       W(i,j*2  ) = per_cell_W(positive_cell, j);
       W(i,j*2+1) = per_cell_W(negative_cell, j);

+ 37 - 0
include/igl/copyleft/cgal/propagate_winding_numbers.h

@@ -56,6 +56,43 @@ namespace igl
         const Eigen::PlainObjectBase<DerivedF>& F,
         const Eigen::PlainObjectBase<DerivedL>& labels,
         Eigen::PlainObjectBase<DerivedW>& W);
+
+      // Inputs:
+      //   V  #V by 3 list of vertex positions.
+      //   F  #F by 3 list of triangle indices into V.
+      //   uE    #uE by 2 list of vertex_indices, represents undirected edges.
+      //   uE2E  #uE list of lists that maps uE to E. (a one-to-many map)
+      //   num_patches  number of patches
+      //   P  #F list of patch ids.
+      //   num_cells    number of cells
+      //   C  #P by 2 list of cell ids on each side of each patch.
+      //   labels  #F list of facet labels ranging from 0 to k-1.
+      // Output:
+      //   W  #F by k*2 list of winding numbers.  ``W(i,j*2)`` is the winding
+      //      number on the positive side of facet ``i`` with respect to the
+      //      facets labeled ``j``.  Similarly, ``W(i,j*2+1)`` is the winding
+      //      number on the negative side of facet ``i`` with respect to the
+      //      facets labeled ``j``.
+      template<
+        typename DerivedV,
+        typename DerivedF,
+        typename DeriveduE,
+        typename uE2EType,
+        typename DerivedP,
+        typename DerivedC,
+        typename DerivedL,
+        typename DerivedW>
+      IGL_INLINE bool propagate_winding_numbers(
+        const Eigen::PlainObjectBase<DerivedV>& V,
+        const Eigen::PlainObjectBase<DerivedF>& F,
+        const Eigen::PlainObjectBase<DeriveduE>& uE,
+        const std::vector<std::vector<uE2EType> >& uE2E,
+        const size_t num_patches,
+        const Eigen::PlainObjectBase<DerivedP>& P,
+        const size_t num_cells,
+        const Eigen::PlainObjectBase<DerivedC>& C,
+        const Eigen::PlainObjectBase<DerivedL>& labels,
+        Eigen::PlainObjectBase<DerivedW>& W);
     }
   }
 }

+ 121 - 0
include/igl/copyleft/cgal/relabel_small_immersed_cells.cpp

@@ -0,0 +1,121 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Qingnan Zhou <qnzhou@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+//
+
+#include "relabel_small_immersed_cells.h"
+#include "../../centroid.h"
+#include "assign_scalar.h"
+#include "cell_adjacency.h"
+
+#include <vector>
+
+template<
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedP,
+  typename DerivedC,
+  typename FT,
+  typename DerivedW>
+IGL_INLINE void igl::copyleft::cgal::relabel_small_immersed_cells(
+    const Eigen::PlainObjectBase<DerivedV>& V,
+    const Eigen::PlainObjectBase<DerivedF>& F,
+    const size_t num_patches,
+    const Eigen::PlainObjectBase<DerivedP>& P,
+    const size_t num_cells,
+    const Eigen::PlainObjectBase<DerivedC>& C,
+    const FT vol_threashold,
+    Eigen::PlainObjectBase<DerivedW>& W)
+{
+  const size_t num_vertices = V.rows();
+  const size_t num_faces = F.rows();
+  typedef std::tuple<typename DerivedC::Scalar, bool, size_t> CellConnection;
+  std::vector<std::set<CellConnection> > cell_adj;
+  igl::copyleft::cgal::cell_adjacency(C, num_cells, cell_adj);
+
+  Eigen::MatrixXd VV(V.rows(), V.cols());
+  for (size_t i=0; i<num_vertices; i++) {
+    igl::copyleft::cgal::assign_scalar(V(i,0), VV(i,0));
+    igl::copyleft::cgal::assign_scalar(V(i,1), VV(i,1));
+    igl::copyleft::cgal::assign_scalar(V(i,2), VV(i,2));
+  }
+
+  auto compute_cell_volume = [&](size_t cell_id) {
+    std::vector<short> is_involved(num_patches, 0);
+    for (size_t i=0; i<num_patches; i++) {
+      if (C(i,0) == cell_id) {
+        // cell is on positive side of patch i.
+        is_involved[i] = 1;
+      }
+      if (C(i,1) == cell_id) {
+        // cell is on negative side of patch i.
+        is_involved[i] = -1;
+      }
+    }
+
+    std::vector<size_t> involved_positive_faces;
+    std::vector<size_t> involved_negative_faces;
+    for (size_t i=0; i<num_faces; i++) {
+      switch (is_involved[P[i]]) {
+        case 1:
+          involved_negative_faces.push_back(i);
+          break;
+        case -1:
+          involved_positive_faces.push_back(i);
+          break;
+      }
+    }
+
+    const size_t num_positive_faces = involved_positive_faces.size();
+    const size_t num_negative_faces = involved_negative_faces.size();
+    DerivedF selected_faces(num_positive_faces + num_negative_faces, 3);
+    for (size_t i=0; i<num_positive_faces; i++) {
+      selected_faces.row(i) = F.row(involved_positive_faces[i]);
+    }
+    for (size_t i=0; i<num_negative_faces; i++) {
+      selected_faces.row(num_positive_faces+i) =
+        F.row(involved_negative_faces[i]).reverse();
+    }
+
+    Eigen::VectorXd c(3);
+    double vol;
+    igl::centroid(VV, selected_faces, c, vol);
+    return vol;
+  };
+
+  std::vector<typename DerivedV::Scalar> cell_volumes(num_cells);
+  for (size_t i=0; i<num_cells; i++) {
+    cell_volumes[i] = compute_cell_volume(i);
+  }
+
+  std::vector<typename DerivedW::Scalar> cell_values(num_cells);
+  for (size_t i=0; i<num_faces; i++) {
+    cell_values[C(P[i], 0)] = W(i, 0);
+    cell_values[C(P[i], 1)] = W(i, 1);
+  }
+
+  for (size_t i=1; i<num_cells; i++) {
+    std::cout << cell_volumes[i] << std::endl;
+    if (cell_volumes[i] >= vol_threashold) continue;
+    std::set<typename DerivedW::Scalar> neighbor_values;
+    const auto neighbors = cell_adj[i];
+    for (const auto& entry : neighbors) {
+      const auto& j = std::get<0>(entry);
+      neighbor_values.insert(cell_values[j]);
+    }
+    // If cell i is immersed, assign its value to be the immersed value.
+    if (neighbor_values.size() == 1) {
+      cell_values[i] = *neighbor_values.begin();
+    }
+  }
+
+  for (size_t i=0; i<num_faces; i++) {
+    W(i,0) = cell_values[C(P[i], 0)];
+    W(i,1) = cell_values[C(P[i], 1)];
+  }
+}
+

+ 59 - 0
include/igl/copyleft/cgal/relabel_small_immersed_cells.h

@@ -0,0 +1,59 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Qingnan Zhou <qnzhou@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+//
+#ifndef IGL_RELABEL_SMALL_IMMERSED_CELLS
+#define IGL_RELABEL_SMALL_IMMERSED_CELLS
+
+#include "../../igl_inline.h"
+#include <Eigen/Core>
+#include <vector>
+
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // Inputs:
+      //   V  #V by 3 list of vertex positions.
+      //   F  #F by 3 list of triangle indices into V.
+      //   num_patches  number of patches
+      //   P  #F list of patch ids.
+      //   num_cells    number of cells
+      //   C  #P by 2 list of cell ids on each side of each patch.
+      //   vol_threshold  Volume threshold, cells smaller than this
+      //                  and is completely immersed will be relabeled.
+      //
+      // In/Output:
+      //   W  #F by 2 cell labels.  W(i,0) is the label on the positive side of
+      //      face i, W(i,1) is the label on the negative side of face i.  W
+      //      will be modified in place by this method.
+      template<
+        typename DerivedV,
+        typename DerivedF,
+        typename DerivedP,
+        typename DerivedC,
+        typename FT,
+        typename DerivedW>
+      IGL_INLINE void relabel_small_immersed_cells(
+          const Eigen::PlainObjectBase<DerivedV>& V,
+          const Eigen::PlainObjectBase<DerivedF>& F,
+          const size_t num_patches,
+          const Eigen::PlainObjectBase<DerivedP>& P,
+          const size_t num_cells,
+          const Eigen::PlainObjectBase<DerivedC>& C,
+          const FT vol_threashold,
+          Eigen::PlainObjectBase<DerivedW>& W);
+    }
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "relabel_small_immersed_cells.cpp"
+#endif
+#endif

+ 79 - 82
include/igl/copyleft/marching_cubes.cpp

@@ -4,7 +4,7 @@
  *        Copyright (C) 2002 by Computer Graphics Group, RWTH Aachen         *
  *                         www.rwth-graphics.de                              *
  *                                                                           *
- *---------------------------------------------------------------------------* 
+ *---------------------------------------------------------------------------*
  *                                                                           *
  *                                License                                    *
  *                                                                           *
@@ -31,58 +31,59 @@ extern const int edgeTable[256];
 extern const int triTable[256][2][17];
 extern const int polyTable[8][16];
 
-class EdgeKey 
+class EdgeKey
 {
 public:
-  
+
   EdgeKey(unsigned i0, unsigned i1) {
     if (i0 < i1)  { i0_ = i0;  i1_ = i1; }
     else            { i0_ = i1;  i1_ = i0; }
   }
-  
-  bool operator<(const EdgeKey& _rhs) const 
+
+  bool operator<(const EdgeKey& _rhs) const
   {
     if (i0_ != _rhs.i0_)
       return (i0_ < _rhs.i0_);
     else
       return (i1_ < _rhs.i1_);
   }
-  
+
 private:
   unsigned i0_, i1_;
 };
 
 
-template <typename DerivedV, typename DerivedF>
+template <typename DerivedV1, typename DerivedV2, typename DerivedF>
 class MarchingCubes
 {
-  typedef Eigen::PlainObjectBase<DerivedV> PointMatrixType;
-  typedef Eigen::PlainObjectBase<DerivedF> FaceMatrixType;
   typedef std::map<EdgeKey, unsigned>  MyMap;
   typedef typename MyMap::const_iterator   MyMapIterator;
-  
+
 public:
-  MarchingCubes(const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 1> &values,
-                const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 3> &points,
+  MarchingCubes(
+                const Eigen::PlainObjectBase<DerivedV1> &values,
+                const Eigen::PlainObjectBase<DerivedV2> &points,
                 const unsigned x_res,
                 const unsigned y_res,
                 const unsigned z_res,
-                PointMatrixType &vertices,
-                FaceMatrixType &faces)
+                Eigen::PlainObjectBase<DerivedV2> &vertices,
+                Eigen::PlainObjectBase<DerivedF> &faces)
   {
-    
+    assert(values.cols() == 1);
+    assert(points.cols() == 3);
+
     if(x_res <2 || y_res<2 ||z_res<2)
       return;
     faces.resize(10000,3);
     int num_faces = 0;
-    
+
     vertices.resize(10000,3);
     int num_vertices = 0;
-    
-    
+
+
     unsigned n_cubes  = (x_res-1) * (y_res-1) * (z_res-1);
     assert(unsigned(points.rows()) == x_res * y_res * z_res);
-    
+
     unsigned int         offsets_[8];
     offsets_[0] = 0;
     offsets_[1] = 1;
@@ -92,16 +93,16 @@ public:
     offsets_[5] = 1         + x_res*y_res;
     offsets_[6] = 1 + x_res + x_res*y_res;
     offsets_[7] =     x_res + x_res*y_res;
-    
+
     for (unsigned cube_it =0 ; cube_it < n_cubes; ++cube_it)
     {
-      
+
       unsigned         corner[8];
       typename DerivedF::Scalar samples[12];
       unsigned char    cubetype(0);
       unsigned int     i;
-      
-      
+
+
       // get point indices of corner vertices
       for (i=0; i<8; ++i)
       {
@@ -111,137 +112,133 @@ public:
         unsigned int x = _idx % X;  _idx /= X;
         unsigned int y = _idx % Y;  _idx /= Y;
         unsigned int z = _idx;
-        
+
         // transform to point coordinates
         _idx = x + y*x_res + z*x_res*y_res;
-        
+
         // add offset
         corner[i] = _idx + offsets_[i];
       }
-      
-      
+
+
       // determine cube type
       for (i=0; i<8; ++i)
         if (values[corner[i]] > 0.0)
           cubetype |= (1<<i);
-      
-      
+
+
       // trivial reject ?
       if (cubetype == 0 || cubetype == 255)
         continue;
-      
-      
+
+
       // compute samples on cube's edges
-      if (edgeTable[cubetype]&1)  
+      if (edgeTable[cubetype]&1)
         samples[0]  = add_vertex(values, points, corner[0], corner[1], vertices, num_vertices, edge2vertex);
-      if (edgeTable[cubetype]&2)  
+      if (edgeTable[cubetype]&2)
         samples[1]  = add_vertex(values, points, corner[1], corner[2], vertices, num_vertices, edge2vertex);
-      if (edgeTable[cubetype]&4)  
+      if (edgeTable[cubetype]&4)
         samples[2]  = add_vertex(values, points, corner[3], corner[2], vertices, num_vertices, edge2vertex);
-      if (edgeTable[cubetype]&8)  
+      if (edgeTable[cubetype]&8)
         samples[3]  = add_vertex(values, points, corner[0], corner[3], vertices, num_vertices, edge2vertex);
-      if (edgeTable[cubetype]&16) 
+      if (edgeTable[cubetype]&16)
         samples[4]  = add_vertex(values, points, corner[4], corner[5], vertices, num_vertices, edge2vertex);
-      if (edgeTable[cubetype]&32)  
+      if (edgeTable[cubetype]&32)
         samples[5]  = add_vertex(values, points, corner[5], corner[6], vertices, num_vertices, edge2vertex);
-      if (edgeTable[cubetype]&64)  
+      if (edgeTable[cubetype]&64)
         samples[6]  = add_vertex(values, points, corner[7], corner[6], vertices, num_vertices, edge2vertex);
-      if (edgeTable[cubetype]&128) 
+      if (edgeTable[cubetype]&128)
         samples[7]  = add_vertex(values, points, corner[4], corner[7], vertices, num_vertices, edge2vertex);
-      if (edgeTable[cubetype]&256) 
+      if (edgeTable[cubetype]&256)
         samples[8]  = add_vertex(values, points, corner[0], corner[4], vertices, num_vertices, edge2vertex);
-      if (edgeTable[cubetype]&512) 
+      if (edgeTable[cubetype]&512)
         samples[9]  = add_vertex(values, points, corner[1], corner[5], vertices, num_vertices, edge2vertex);
       if (edgeTable[cubetype]&1024)
         samples[10] = add_vertex(values, points, corner[2], corner[6], vertices, num_vertices, edge2vertex);
       if (edgeTable[cubetype]&2048)
         samples[11] = add_vertex(values, points, corner[3], corner[7], vertices, num_vertices, edge2vertex);
-      
-      
-      
+
+
+
       // connect samples by triangles
       for (i=0; triTable[cubetype][0][i] != -1; i+=3 )
       {
         num_faces++;
         if (num_faces > faces.rows())
           faces.conservativeResize(faces.rows()+10000, Eigen::NoChange);
-        
-        faces.row(num_faces-1) << 
+
+        faces.row(num_faces-1) <<
         samples[triTable[cubetype][0][i  ]],
         samples[triTable[cubetype][0][i+1]],
         samples[triTable[cubetype][0][i+2]];
-        
+
       }
-      
+
     }
-    
+
     vertices.conservativeResize(num_vertices, Eigen::NoChange);
     faces.conservativeResize(num_faces, Eigen::NoChange);
-    
+
   };
-  
-  static typename DerivedF::Scalar  add_vertex(const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 1> &values,
-                                               const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 3> &points,
+
+  static typename DerivedF::Scalar  add_vertex(const Eigen::PlainObjectBase<DerivedV1> &values,
+                                               const Eigen::PlainObjectBase<DerivedV2> &points,
                                                unsigned int i0,
                                                unsigned int i1,
-                                               PointMatrixType &vertices,
+                                               Eigen::PlainObjectBase<DerivedV2> &vertices,
                                                int &num_vertices,
                                                MyMap &edge2vertex)
   {
     // find vertex if it has been computed already
     MyMapIterator it = edge2vertex.find(EdgeKey(i0, i1));
-    if (it != edge2vertex.end()) 
+    if (it != edge2vertex.end())
       return it->second;
     ;
-    
+
     // generate new vertex
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> & p0 = points.row(i0);
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> & p1 = points.row(i1);
-    
-    typename DerivedV::Scalar s0 = fabs(values[i0]);
-    typename DerivedV::Scalar s1 = fabs(values[i1]);
-    typename DerivedV::Scalar t  = s0 / (s0+s1);
-    
-    
+    const Eigen::Matrix<typename DerivedV2::Scalar, 1, 3> & p0 = points.row(i0);
+    const Eigen::Matrix<typename DerivedV2::Scalar, 1, 3> & p1 = points.row(i1);
+
+    typename DerivedV1::Scalar s0 = fabs(values[i0]);
+    typename DerivedV1::Scalar s1 = fabs(values[i1]);
+    typename DerivedV1::Scalar t  = s0 / (s0+s1);
+
+
     num_vertices++;
     if (num_vertices > vertices.rows())
       vertices.conservativeResize(vertices.rows()+10000, Eigen::NoChange);
-    
+
     vertices.row(num_vertices-1)  = (1.0f-t)*p0 + t*p1;
     edge2vertex[EdgeKey(i0, i1)] = num_vertices-1;
-    
+
     return num_vertices-1;
   }
   ;
-  
+
   // maps an edge to the sample vertex generated on it
   MyMap  edge2vertex;
 };
 
 
-template <typename DerivedV, typename DerivedF>
+template <typename DerivedV1, typename DerivedV2, typename DerivedF>
 IGL_INLINE void igl::copyleft::marching_cubes(
-  const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 1> &values,
-  const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 3> &points,
+  const Eigen::PlainObjectBase<DerivedV1> &values,
+  const Eigen::PlainObjectBase<DerivedV2> &points,
   const unsigned x_res,
   const unsigned y_res,
   const unsigned z_res,
-  Eigen::PlainObjectBase<DerivedV> &vertices,
+  Eigen::PlainObjectBase<DerivedV2> &vertices,
   Eigen::PlainObjectBase<DerivedF> &faces)
 {
-  MarchingCubes<DerivedV, DerivedF> mc(values, 
-                                       points, 
-                                       x_res, 
-                                       y_res, 
-                                       z_res, 
-                                       vertices, 
+  MarchingCubes<DerivedV1, DerivedV2, DerivedF> mc(values,
+                                       points,
+                                       x_res,
+                                       y_res,
+                                       z_res,
+                                       vertices,
                                        faces);
 }
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
-template void igl::copyleft::marching_cubes<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::Matrix<Eigen::Matrix<float, -1, 3, 0, -1, 3>::Scalar, -1, 1, 0, -1, 1> const&, Eigen::Matrix<Eigen::Matrix<float, -1, 3, 0, -1, 3>::Scalar, -1, 3, 0, -1, 3> const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
-template void igl::copyleft::marching_cubes<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::Matrix<Eigen::Matrix<double, -1, 3, 0, -1, 3>::Scalar, -1, 1, 0, -1, 1> const&, Eigen::Matrix<Eigen::Matrix<double, -1, 3, 0, -1, 3>::Scalar, -1, 3, 0, -1, 3> const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
-template void igl::copyleft::marching_cubes<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<unsigned int, -1, 3, 0, -1, 3> >(Eigen::Matrix<Eigen::Matrix<double, -1, 3, 0, -1, 3>::Scalar, -1, 1, 0, -1, 1> const&, Eigen::Matrix<Eigen::Matrix<double, -1, 3, 0, -1, 3>::Scalar, -1, 3, 0, -1, 3> const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 0, -1, 3> >&);
-template void igl::copyleft::marching_cubes<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<unsigned int, -1, 3, 0, -1, 3> >(Eigen::Matrix<Eigen::Matrix<float, -1, 3, 0, -1, 3>::Scalar, -1, 1, 0, -1, 1> const&, Eigen::Matrix<Eigen::Matrix<float, -1, 3, 0, -1, 3>::Scalar, -1, 3, 0, -1, 3> const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 0, -1, 3> >&);
-template void igl::copyleft::marching_cubes<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::Matrix<Eigen::Matrix<double, -1, -1, 0, -1, -1>::Scalar, -1, 1, 0, -1, 1> const&, Eigen::Matrix<Eigen::Matrix<double, -1, -1, 0, -1, -1>::Scalar, -1, 3, 0, -1, 3> const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template void igl::copyleft::marching_cubes<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, unsigned int, unsigned int, unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 #endif

+ 10 - 10
include/igl/copyleft/marching_cubes.h

@@ -1,16 +1,16 @@
 // This file is part of libigl, a simple c++ geometry processing library.
-// 
+//
 // Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
 // obtain one at http://mozilla.org/MPL/2.0/.
 #ifndef IGL_COPYLEFT_MARCHINGCUBES_H
 #define IGL_COPYLEFT_MARCHINGCUBES_H
 #include "../igl_inline.h"
 
 #include <Eigen/Core>
-namespace igl 
+namespace igl
 {
   namespace copyleft
   {
@@ -26,7 +26,7 @@ namespace igl
     //  points  #number_of_grid_points x 3 array -- 3-D positions of the grid
     //    points, ordered in x,y,z order:
     //      points[index] = the point at (x,y,z) where :
-    //      x = (index % (xres -1), 
+    //      x = (index % (xres -1),
     //      y = (index / (xres-1)) %(yres-1),
     //      z = index / (xres -1) / (yres -1) ).
     //      where x,y,z index x, y, z dimensions
@@ -38,14 +38,14 @@ namespace igl
     //   vertices  #V by 3 list of mesh vertex positions
     //   faces  #F by 3 list of mesh triangle indices
     //
-    template <typename DerivedV, typename DerivedF>
+    template <typename DerivedV1, typename DerivedV2, typename DerivedF>
       IGL_INLINE void marching_cubes(
-        const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 1> &values,
-        const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 3> &points,
+        const Eigen::PlainObjectBase<DerivedV1> &values,
+        const Eigen::PlainObjectBase<DerivedV2> &points,
         const unsigned x_res,
         const unsigned y_res,
         const unsigned z_res,
-        Eigen::PlainObjectBase<DerivedV> &vertices,
+        Eigen::PlainObjectBase<DerivedV2> &vertices,
         Eigen::PlainObjectBase<DerivedF> &faces);
   }
 }

+ 2 - 2
include/igl/copyleft/quadprog.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 "quadprog.h"
-
+#include <vector>
 /*
  FILE eiquadprog.hh
  
@@ -307,7 +307,7 @@ IGL_INLINE bool igl::copyleft::quadprog(
   VectorXi A(m + p), A_old(m + p), iai(m + p);
   int q;
   int iq, iter = 0;
-  bool iaexcl[m + p];
+  std::vector<bool> iaexcl(m + p);
  	
   me = p; /* number of equality constraints */
   mi = m; /* number of inequality constraints */

+ 2 - 2
include/igl/cross_field_missmatch.cpp

@@ -28,7 +28,7 @@ namespace igl {
     const Eigen::PlainObjectBase<DerivedF> &F;
     const Eigen::PlainObjectBase<DerivedV> &PD1;
     const Eigen::PlainObjectBase<DerivedV> &PD2;
-#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
+//#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
     Eigen::PlainObjectBase<DerivedV> N;
 
   private:
@@ -36,7 +36,7 @@ namespace igl {
     std::vector<bool> V_border; // bool
     std::vector<std::vector<int> > VF;
     std::vector<std::vector<int> > VFi;
-#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
+//#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
     Eigen::PlainObjectBase<DerivedF> TT;
     Eigen::PlainObjectBase<DerivedF> TTi;
 

+ 1 - 1
include/igl/cut_mesh.cpp

@@ -29,7 +29,7 @@ namespace igl {
     int num_scalar_variables;
 
     // per face indexes of vertex in the solver
-#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
+//#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
     Eigen::PlainObjectBase<DerivedF> HandleS_Index;
 
     // per vertex variable indexes

+ 1 - 1
include/igl/cut_mesh_from_singularities.cpp

@@ -30,7 +30,7 @@ namespace igl {
     const Eigen::PlainObjectBase<DerivedM> &Handle_MMatch;
 
     Eigen::VectorXi F_visited;
-#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
+//#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
     Eigen::PlainObjectBase<DerivedF> TT;
     Eigen::PlainObjectBase<DerivedF> TTi;
 

+ 3 - 0
include/igl/eigs.cpp

@@ -153,4 +153,7 @@ IGL_INLINE bool igl::eigs(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 template bool igl::eigs<double, double, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::SparseMatrix<double, 0, int> const&, Eigen::SparseMatrix<double, 0, int> const&, unsigned long, igl::EigsType, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
+#ifdef WIN32
+template bool igl::eigs<double, double, Eigen::Matrix<double,-1,-1,0,-1,-1>, Eigen::Matrix<double,-1,1,0,-1,1> >(Eigen::SparseMatrix<double,0,int> const &,Eigen::SparseMatrix<double,0,int> const &,unsigned long long, igl::EigsType, Eigen::PlainObjectBase< Eigen::Matrix<double,-1,-1,0,-1,-1> > &, Eigen::PlainObjectBase<Eigen::Matrix<double,-1,1,0,-1,1> > &);
+#endif
 #endif

+ 3 - 1
include/igl/embree/reorient_facets_raycast.h

@@ -14,7 +14,9 @@ namespace igl
   namespace embree
   {
     // Orient each component (identified by C) of a mesh (V,F) using ambient
-    // occlusion such that the front side is less occluded than back side
+    // occlusion such that the front side is less occluded than back side, as
+    // described in "A Simple Method for Correcting Facet Orientations in
+    // Polygon Meshes Based on Ray Casting" [Takayama et al. 2014].
     //
     // Inputs:
     //   V  #V by 3 list of vertex positions

+ 1 - 1
include/igl/line_field_missmatch.cpp

@@ -31,7 +31,7 @@ public:
     const Eigen::PlainObjectBase<DerivedF> &F;
     const Eigen::PlainObjectBase<DerivedV> &PD1;
     const Eigen::PlainObjectBase<DerivedV> &PD2;
-#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
+//#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
     Eigen::PlainObjectBase<DerivedV> N;
 
 private:

+ 3 - 0
include/igl/list_to_matrix.cpp

@@ -135,4 +135,7 @@ template bool igl::list_to_matrix<bool, Eigen::Array<bool, -1, -1, 0, -1, -1> >(
 template bool igl::list_to_matrix<bool, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::vector<bool, std::allocator<bool> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template bool igl::list_to_matrix<bool, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::vector<std::vector<bool, std::allocator<bool> >, std::allocator<std::vector<bool, std::allocator<bool> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template bool igl::list_to_matrix<double, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(std::vector<double, std::allocator<double> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
+#ifdef WIN32
+template bool igl::list_to_matrix<unsigned long long,class Eigen::Matrix<int,-1,1,0,-1,1> >(class std::vector<unsigned long long,class std::allocator<unsigned long long> > const &,class Eigen::PlainObjectBase<class Eigen::Matrix<int,-1,1,0,-1,1> > &);
+#endif
 #endif

+ 1 - 1
include/igl/n_polyvector.cpp

@@ -39,7 +39,7 @@ namespace igl {
     Eigen::VectorXi indInteriorToFull;
     Eigen::VectorXi indFullToInterior;
 
-#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
+//#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
     Eigen::PlainObjectBase<DerivedV> B1, B2, FN;
 
     IGL_INLINE void computek();

+ 472 - 473
include/igl/n_polyvector_general.cpp

@@ -7,468 +7,465 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 
 #include <igl/n_polyvector_general.h>
-#include <igl/edge_topology.h>
-#include <igl/local_basis.h>
-#include <igl/nchoosek.h>
-#include <igl/slice.h>
-#include <igl/polyroots.h>
-#include <Eigen/Sparse>
-#include <Eigen/Geometry>
-#include <iostream>
-
-namespace igl {
-  template <typename DerivedV, typename DerivedF>
-  class GeneralPolyVectorFieldFinder
-  {
-  private:
-    const Eigen::PlainObjectBase<DerivedV> &V;
-    const Eigen::PlainObjectBase<DerivedF> &F; int numF;
-    const int n;
-
-    Eigen::MatrixXi EV; int numE;
-    Eigen::MatrixXi F2E;
-    Eigen::MatrixXi E2F;
-    Eigen::VectorXd K;
-
-    Eigen::VectorXi isBorderEdge;
-    int numInteriorEdges;
-    Eigen::Matrix<int,Eigen::Dynamic,2> E2F_int;
-    Eigen::VectorXi indInteriorToFull;
-    Eigen::VectorXi indFullToInterior;
-
-#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
-    Eigen::PlainObjectBase<DerivedV> B1, B2, FN;
-
-    IGL_INLINE void computek();
-    IGL_INLINE void setFieldFromGeneralCoefficients(const  std::vector<Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1>> &coeffs,
-                                                    std::vector<Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 2> > &pv);
-    IGL_INLINE void computeCoefficientLaplacian(int n, Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &D);
-    IGL_INLINE void getGeneralCoeffConstraints(const Eigen::VectorXi &isConstrained,
-                                    const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> &cfW,
-                                    int k,
-                                    const Eigen::VectorXi &rootsIndex,
-                                    Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1> &Ck);
-    IGL_INLINE void precomputeInteriorEdges();
-
-
-    IGL_INLINE void minQuadWithKnownMini(const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &Q,
-                                         const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &f,
-                                         const Eigen::VectorXi isConstrained,
-                                         const Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &xknown,
-                                         Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &x);
-
-  public:
-    IGL_INLINE GeneralPolyVectorFieldFinder(const Eigen::PlainObjectBase<DerivedV> &_V,
-                                     const Eigen::PlainObjectBase<DerivedF> &_F,
-                                     const int &_n);
-    IGL_INLINE bool solve(const Eigen::VectorXi &isConstrained,
-               const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> &cfW,
-               const Eigen::VectorXi &rootsIndex,
-               Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> &output);
-
-  };
-}
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE igl::GeneralPolyVectorFieldFinder<DerivedV, DerivedF>::
-          GeneralPolyVectorFieldFinder(const Eigen::PlainObjectBase<DerivedV> &_V,
-                                const Eigen::PlainObjectBase<DerivedF> &_F,
-                                const int &_n):
-V(_V),
-F(_F),
-numF(_F.rows()),
-n(_n)
-{
-
-  igl::edge_topology(V,F,EV,F2E,E2F);
-  numE = EV.rows();
-
-
-  precomputeInteriorEdges();
-
-  igl::local_basis(V,F,B1,B2,FN);
-
-  computek();
-
-};
-
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::GeneralPolyVectorFieldFinder<DerivedV, DerivedF>::
-precomputeInteriorEdges()
-{
-  // Flag border edges
-  numInteriorEdges = 0;
-  isBorderEdge.setZero(numE,1);
-  indFullToInterior = -1*Eigen::VectorXi::Ones(numE,1);
-
-  for(unsigned i=0; i<numE; ++i)
-  {
-    if ((E2F(i,0) == -1) || ((E2F(i,1) == -1)))
-      isBorderEdge[i] = 1;
-      else
-      {
-        indFullToInterior[i] = numInteriorEdges;
-        numInteriorEdges++;
-      }
-  }
-
-  E2F_int.resize(numInteriorEdges, 2);
-  indInteriorToFull.setZero(numInteriorEdges,1);
-  int ii = 0;
-  for (int k=0; k<numE; ++k)
-  {
-    if (isBorderEdge[k])
-      continue;
-    E2F_int.row(ii) = E2F.row(k);
-    indInteriorToFull[ii] = k;
-    ii++;
-  }
-
-}
-
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::GeneralPolyVectorFieldFinder<DerivedV, DerivedF>::
-minQuadWithKnownMini(const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &Q,
-                          const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &f,
-                     const Eigen::VectorXi isConstrained,
-                          const Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &xknown,
-                          Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &x)
-{
-  int N = Q.rows();
-
-  int nc = xknown.rows();
-  Eigen::VectorXi known; known.setZero(nc,1);
-  Eigen::VectorXi unknown; unknown.setZero(N-nc,1);
-
-  int indk = 0, indu = 0;
-  for (int i = 0; i<N; ++i)
-    if (isConstrained[i])
-    {
-      known[indk] = i;
-      indk++;
-    }
-    else
-    {
-      unknown[indu] = i;
-      indu++;
-    }
-
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar>> Quu, Quk;
-
-  igl::slice(Q,unknown, unknown, Quu);
-  igl::slice(Q,unknown, known, Quk);
-
-
-  std::vector<typename Eigen::Triplet<std::complex<typename DerivedV::Scalar> > > tripletList;
-
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > fu(N-nc,1);
-
-  igl::slice(f,unknown, Eigen::VectorXi::Zero(1,1), fu);
-
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > rhs = (Quk*xknown).sparseView()+.5*fu;
-
-  Eigen::SparseLU< Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar>>> solver;
-  solver.compute(-Quu);
-  if(solver.info()!=Eigen::Success)
-  {
-    std::cerr<<"Decomposition failed!"<<std::endl;
-    return;
-  }
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar>>  b  = solver.solve(rhs);
-  if(solver.info()!=Eigen::Success)
-  {
-    std::cerr<<"Solving failed!"<<std::endl;
-    return;
-  }
-
-  indk = 0, indu = 0;
-  x.setZero(N,1);
-  for (int i = 0; i<N; ++i)
-    if (isConstrained[i])
-      x[i] = xknown[indk++];
-    else
-      x[i] = b.coeff(indu++,0);
-
-}
-
-
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE bool igl::GeneralPolyVectorFieldFinder<DerivedV, DerivedF>::
-                     solve(const Eigen::VectorXi &isConstrained,
-                           const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> &cfW,
-                           const Eigen::VectorXi &rootsIndex,
-                           Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> &output)
-{
-
-  // polynomial is of the form:
-  // z^(2n) +
-  // -c[0]z^(2n-1) +
-  // c[1]z^(2n-2) +
-  // -c[2]z^(2n-3) +
-  // ... +
-  // (-1)^n c[n-1]
-
-  std::vector<Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1>> coeffs(n,Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1>::Zero(numF, 1));
-
-  for (int i =0; i<n; ++i)
-  {
-    int degree = i+1;
-
-    Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1> Ck;
-    getGeneralCoeffConstraints(isConstrained,
-                               cfW,
-                               i,
-                               rootsIndex,
-                               Ck);
-
-    Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > DD;
-    computeCoefficientLaplacian(degree, DD);
-    Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > f; f.resize(numF,1);
-
-    if (isConstrained.sum() == numF)
-      coeffs[i] = Ck;
-    else
-      minQuadWithKnownMini(DD, f, isConstrained, Ck, coeffs[i]);
-  }
-
-  std::vector<Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 2> > pv;
-  setFieldFromGeneralCoefficients(coeffs, pv);
-
-  output.setZero(numF,3*n);
-  for (int fi=0; fi<numF; ++fi)
-  {
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &b1 = B1.row(fi);
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &b2 = B2.row(fi);
-    for (int i=0; i<n; ++i)
-      output.block(fi,3*i, 1, 3) = pv[i](fi,0)*b1 + pv[i](fi,1)*b2;
-  }
-  return true;
-}
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::GeneralPolyVectorFieldFinder<DerivedV, DerivedF>::setFieldFromGeneralCoefficients(const  std::vector<Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1>> &coeffs,
-                                                            std::vector<Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 2>> &pv)
-{
-  pv.assign(n, Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 2>::Zero(numF, 2));
-  for (int i = 0; i <numF; ++i)
-  {
-
-    //    poly coefficients: 1, 0, -Acoeff, 0, Bcoeff
-    //    matlab code from roots (given there are no trailing zeros in the polynomial coefficients)
-    Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1> polyCoeff;
-    polyCoeff.setZero(n+1,1);
-    polyCoeff[0] = 1.;
-    int sign = 1;
-    for (int k =0; k<n; ++k)
-    {
-      sign = -sign;
-      int degree = k+1;
-      polyCoeff[degree] = (1.*sign)*coeffs[k](i);
-    }
-
-    Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1> roots;
-    igl::polyRoots<std::complex<typename DerivedV::Scalar>, typename DerivedV::Scalar >(polyCoeff,roots);
-    for (int k=0; k<n; ++k)
-    {
-      pv[k](i,0) = real(roots[k]);
-      pv[k](i,1) = imag(roots[k]);
-    }
-  }
-
-}
-
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::GeneralPolyVectorFieldFinder<DerivedV, DerivedF>::computeCoefficientLaplacian(int n, Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &D)
-{
-  std::vector<Eigen::Triplet<std::complex<typename DerivedV::Scalar> >> tripletList;
-
-  // For every non-border edge
-  for (unsigned eid=0; eid<numE; ++eid)
-  {
-    if (!isBorderEdge[eid])
-    {
-      int fid0 = E2F(eid,0);
-      int fid1 = E2F(eid,1);
-
-      tripletList.push_back(Eigen::Triplet<std::complex<typename DerivedV::Scalar> >(fid0,
-                                           fid0,
-                                           std::complex<typename DerivedV::Scalar>(1.)));
-      tripletList.push_back(Eigen::Triplet<std::complex<typename DerivedV::Scalar> >(fid1,
-                                           fid1,
-                                           std::complex<typename DerivedV::Scalar>(1.)));
-      tripletList.push_back(Eigen::Triplet<std::complex<typename DerivedV::Scalar> >(fid0,
-                                           fid1,
-                                                                                     -1.*std::polar(1.,-1.*n*K[eid])));
-      tripletList.push_back(Eigen::Triplet<std::complex<typename DerivedV::Scalar> >(fid1,
-                                           fid0,
-                                                                                     -1.*std::polar(1.,1.*n*K[eid])));
-
-    }
-  }
-  D.resize(numF,numF);
-  D.setFromTriplets(tripletList.begin(), tripletList.end());
-
-
-}
-
-//this gives the coefficients without the (-1)^k that multiplies them
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::GeneralPolyVectorFieldFinder<DerivedV, DerivedF>::getGeneralCoeffConstraints(const Eigen::VectorXi &isConstrained,
-                                                       const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> &cfW,
-                                                       int k,
-                                                       const Eigen::VectorXi &rootsIndex,
-                                                       Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1> &Ck)
-{
-  int numConstrained = isConstrained.sum();
-  Ck.resize(numConstrained,1);
-  // int n = rootsIndex.cols();
-
-  Eigen::MatrixXi allCombs;
-  {
-    Eigen::VectorXi V = Eigen::VectorXi::LinSpaced(n,0,n-1);
-    igl::nchoosek(V,k+1,allCombs);
-  }
-
-  int ind = 0;
-  for (int fi = 0; fi <numF; ++fi)
-  {
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &b1 = B1.row(fi);
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &b2 = B2.row(fi);
-    if(isConstrained[fi])
-    {
-      std::complex<typename DerivedV::Scalar> ck(0);
-
-      for (int j = 0; j < allCombs.rows(); ++j)
-      {
-        std::complex<typename DerivedV::Scalar> tk(1.);
-        //collect products
-        for (int i = 0; i < allCombs.cols(); ++i)
-        {
-          int index = allCombs(j,i);
-
-          int ri = rootsIndex[index];
-          Eigen::Matrix<typename DerivedV::Scalar, 1, 3> w;
-          if (ri>0)
-            w = cfW.block(fi,3*(ri-1),1,3);
-          else
-            w = -cfW.block(fi,3*(-ri-1),1,3);
-          typename DerivedV::Scalar w0 = w.dot(b1);
-          typename DerivedV::Scalar w1 = w.dot(b2);
-          std::complex<typename DerivedV::Scalar> u(w0,w1);
-          tk*= u;
-        }
-        //collect sum
-        ck += tk;
-      }
-      Ck(ind) = ck;
-      ind ++;
-    }
-  }
-
-
-}
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::GeneralPolyVectorFieldFinder<DerivedV, DerivedF>::computek()
-{
-  K.setZero(numE);
-  // For every non-border edge
-  for (unsigned eid=0; eid<numE; ++eid)
-  {
-    if (!isBorderEdge[eid])
-    {
-      int fid0 = E2F(eid,0);
-      int fid1 = E2F(eid,1);
-
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> N0 = FN.row(fid0);
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> N1 = FN.row(fid1);
-
-      // find common edge on triangle 0 and 1
-      int fid0_vc = -1;
-      int fid1_vc = -1;
-      for (unsigned i=0;i<3;++i)
-      {
-        if (F2E(fid0,i) == eid)
-          fid0_vc = i;
-        if (F2E(fid1,i) == eid)
-          fid1_vc = i;
-      }
-      assert(fid0_vc != -1);
-      assert(fid1_vc != -1);
-
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> common_edge = V.row(F(fid0,(fid0_vc+1)%3)) - V.row(F(fid0,fid0_vc));
-      common_edge.normalize();
-
-      // Map the two triangles in a new space where the common edge is the x axis and the N0 the z axis
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 3> P;
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> o = V.row(F(fid0,fid0_vc));
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> tmp = -N0.cross(common_edge);
-      P << common_edge, tmp, N0;
-//      P.transposeInPlace();
-
-
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 3> V0;
-      V0.row(0) = V.row(F(fid0,0)) -o;
-      V0.row(1) = V.row(F(fid0,1)) -o;
-      V0.row(2) = V.row(F(fid0,2)) -o;
-
-      V0 = (P*V0.transpose()).transpose();
-
-//      assert(V0(0,2) < 1e-10);
-//      assert(V0(1,2) < 1e-10);
-//      assert(V0(2,2) < 1e-10);
-
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 3> V1;
-      V1.row(0) = V.row(F(fid1,0)) -o;
-      V1.row(1) = V.row(F(fid1,1)) -o;
-      V1.row(2) = V.row(F(fid1,2)) -o;
-      V1 = (P*V1.transpose()).transpose();
-
-//      assert(V1(fid1_vc,2) < 10e-10);
-//      assert(V1((fid1_vc+1)%3,2) < 10e-10);
-
-      // compute rotation R such that R * N1 = N0
-      // i.e. map both triangles to the same plane
-      double alpha = -atan2(V1((fid1_vc+2)%3,2),V1((fid1_vc+2)%3,1));
-
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 3> R;
-      R << 1,          0,            0,
-      0, cos(alpha), -sin(alpha) ,
-      0, sin(alpha),  cos(alpha);
-      V1 = (R*V1.transpose()).transpose();
-
-//      assert(V1(0,2) < 1e-10);
-//      assert(V1(1,2) < 1e-10);
-//      assert(V1(2,2) < 1e-10);
-
-      // measure the angle between the reference frames
-      // k_ij is the angle between the triangle on the left and the one on the right
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> ref0 = V0.row(1) - V0.row(0);
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> ref1 = V1.row(1) - V1.row(0);
-
-      ref0.normalize();
-      ref1.normalize();
-
-      double ktemp = atan2(ref1(1),ref1(0)) - atan2(ref0(1),ref0(0));
-
-      // just to be sure, rotate ref0 using angle ktemp...
-      Eigen::Matrix<typename DerivedV::Scalar, 2, 2> R2;
-      R2 << cos(ktemp), -sin(ktemp), sin(ktemp), cos(ktemp);
-
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 2> tmp1 = R2*(ref0.head(2)).transpose();
-
-//      assert(tmp1(0) - ref1(0) < 1e-10);
-//      assert(tmp1(1) - ref1(1) < 1e-10);
-
-      K[eid] = ktemp;
-    }
-  }
-
-}
+//#include <igl/edge_topology.h>
+//#include <igl/local_basis.h>
+//#include <igl/nchoosek.h>
+//#include <igl/slice.h>
+//#include <igl/polyroots.h>
+//#include <Eigen/Sparse>
+//#include <Eigen/Geometry>
+//#include <iostream>
+//#include <iostream>
+//
+//namespace igl {
+//  template <typename DerivedV, typename DerivedF>
+//  class GeneralPolyVectorFieldFinder
+//  {
+//  private:
+//    const Eigen::PlainObjectBase<DerivedV> &V;
+//    const Eigen::PlainObjectBase<DerivedF> &F; int numF;
+//    const int n;
+//
+//    Eigen::MatrixXi EV; int numE;
+//    Eigen::MatrixXi F2E;
+//    Eigen::MatrixXi E2F;
+//    Eigen::VectorXd K;
+//
+//    Eigen::VectorXi isBorderEdge;
+//    int numInteriorEdges;
+//    Eigen::Matrix<int,Eigen::Dynamic,2> E2F_int;
+//    Eigen::VectorXi indInteriorToFull;
+//    Eigen::VectorXi indFullToInterior;
+//
+////#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
+//    Eigen::PlainObjectBase<DerivedV> B1, B2, FN;
+//
+//    IGL_INLINE void computek();
+//    IGL_INLINE void setFieldFromGeneralCoefficients(const  std::vector<Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1>> &coeffs,
+//                                                    std::vector<Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 2> > &pv);
+//    IGL_INLINE void computeCoefficientLaplacian(int n, Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &D);
+//    IGL_INLINE void getGeneralCoeffConstraints(const Eigen::VectorXi &isConstrained,
+//                                    const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> &cfW,
+//                                    int k,
+//                                    const Eigen::VectorXi &rootsIndex,
+//                                    Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1> &Ck);
+//    IGL_INLINE void precomputeInteriorEdges();
+//
+//
+//    IGL_INLINE void minQuadWithKnownMini(const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &Q,
+//                                         const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &f,
+//                                         const Eigen::VectorXi isConstrained,
+//                                         const Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &xknown,
+//                                         Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &x);
+//
+//  public:
+//    IGL_INLINE GeneralPolyVectorFieldFinder(const Eigen::PlainObjectBase<DerivedV> &_V,
+//                                     const Eigen::PlainObjectBase<DerivedF> &_F,
+//                                     const int &_n);
+//    IGL_INLINE bool solve(const Eigen::VectorXi &isConstrained,
+//               const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> &cfW,
+//               const Eigen::VectorXi &rootsIndex,
+//               Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> &output);
+//
+//  };
+//}
+//
+//template<typename DerivedV, typename DerivedF>
+//IGL_INLINE igl::GeneralPolyVectorFieldFinder<DerivedV, DerivedF>::
+//          GeneralPolyVectorFieldFinder(const Eigen::PlainObjectBase<DerivedV> &_V,
+//                                const Eigen::PlainObjectBase<DerivedF> &_F,
+//                                const int &_n):
+//V(_V),
+//F(_F),
+//numF(_F.rows()),
+//n(_n)
+//{
+//
+//  igl::edge_topology(V,F,EV,F2E,E2F);
+//  numE = EV.rows();
+//
+//
+//  precomputeInteriorEdges();
+//
+//  igl::local_basis(V,F,B1,B2,FN);
+//
+//  computek();
+//
+//};
+//
+//
+//template<typename DerivedV, typename DerivedF>
+//IGL_INLINE void igl::GeneralPolyVectorFieldFinder<DerivedV, DerivedF>::
+//precomputeInteriorEdges()
+//{
+//  // Flag border edges
+//  numInteriorEdges = 0;
+//  isBorderEdge.setZero(numE,1);
+//  indFullToInterior = -1*Eigen::VectorXi::Ones(numE,1);
+//
+//  for(unsigned i=0; i<numE; ++i)
+//  {
+//    if ((E2F(i,0) == -1) || ((E2F(i,1) == -1)))
+//      isBorderEdge[i] = 1;
+//      else
+//      {
+//        indFullToInterior[i] = numInteriorEdges;
+//        numInteriorEdges++;
+//      }
+//  }
+//
+//  E2F_int.resize(numInteriorEdges, 2);
+//  indInteriorToFull.setZero(numInteriorEdges,1);
+//  int ii = 0;
+//  for (int k=0; k<numE; ++k)
+//  {
+//    if (isBorderEdge[k])
+//      continue;
+//    E2F_int.row(ii) = E2F.row(k);
+//    indInteriorToFull[ii] = k;
+//    ii++;
+//  }
+//
+//}
+//
+//
+//template<typename DerivedV, typename DerivedF>
+//IGL_INLINE void igl::GeneralPolyVectorFieldFinder<DerivedV, DerivedF>::
+//minQuadWithKnownMini(const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &Q,
+//                          const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &f,
+//                     const Eigen::VectorXi isConstrained,
+//                          const Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &xknown,
+//                          Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &x)
+//{
+//  int N = Q.rows();
+//
+//  int nc = xknown.rows();
+//  Eigen::VectorXi known; known.setZero(nc,1);
+//  Eigen::VectorXi unknown; unknown.setZero(N-nc,1);
+//
+//  int indk = 0, indu = 0;
+//  for (int i = 0; i<N; ++i)
+//    if (isConstrained[i])
+//    {
+//      known[indk] = i;
+//      indk++;
+//    }
+//    else
+//    {
+//      unknown[indu] = i;
+//      indu++;
+//    }
+//
+//  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar>> Quu, Quk;
+//
+//  igl::slice(Q,unknown, unknown, Quu);
+//  igl::slice(Q,unknown, known, Quk);
+//
+//
+//  std::vector<typename Eigen::Triplet<std::complex<typename DerivedV::Scalar> > > tripletList;
+//
+//  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > fu(N-nc,1);
+//
+//  igl::slice(f,unknown, Eigen::VectorXi::Zero(1,1), fu);
+//
+//  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > rhs = (Quk*xknown).sparseView()+.5*fu;
+//
+//  Eigen::SparseLU< Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar>>> solver;
+//  solver.compute(-Quu);
+//  if(solver.info()!=Eigen::Success)
+//  {
+//    std::cerr<<"Decomposition failed!"<<std::endl;
+//    return;
+//  }
+//  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar>>  b  = solver.solve(rhs);
+//  if(solver.info()!=Eigen::Success)
+//  {
+//    std::cerr<<"Solving failed!"<<std::endl;
+//    return;
+//  }
+//
+//  indk = 0, indu = 0;
+//  x.setZero(N,1);
+//  for (int i = 0; i<N; ++i)
+//    if (isConstrained[i])
+//      x[i] = xknown[indk++];
+//    else
+//      x[i] = b.coeff(indu++,0);
+//
+//}
+//
+//
+//
+//template<typename DerivedV, typename DerivedF>
+//IGL_INLINE bool igl::GeneralPolyVectorFieldFinder<DerivedV, DerivedF>::
+//                     solve(const Eigen::VectorXi &isConstrained,
+//                           const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> &cfW,
+//                           const Eigen::VectorXi &rootsIndex,
+//                           Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> &output)
+//{
+//	std::cerr << "This code is broken!" << std::endl;
+//	exit(1);
+//  // polynomial is of the form:
+//  // z^(2n) +
+//  // -c[0]z^(2n-1) +
+//  // c[1]z^(2n-2) +
+//  // -c[2]z^(2n-3) +
+//  // ... +
+//  // (-1)^n c[n-1]
+//  //std::vector<Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1>> coeffs(n,Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1>::Zero(numF, 1));
+//  //for (int i =0; i<n; ++i)
+//  //{
+//  //  int degree = i+1;
+//  //  Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1> Ck;
+//  //  getGeneralCoeffConstraints(isConstrained,
+//  //                             cfW,
+//  //                             i,
+//  //                             rootsIndex,
+//  //                             Ck);
+//
+//  //  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > DD;
+//  //  computeCoefficientLaplacian(degree, DD);
+//  //  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > f; f.resize(numF,1);
+//
+//  //  if (isConstrained.sum() == numF)
+//  //    coeffs[i] = Ck;
+//  //  else
+//  //    minQuadWithKnownMini(DD, f, isConstrained, Ck, coeffs[i]);
+//  //}
+//  //std::vector<Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 2> > pv;
+//  //setFieldFromGeneralCoefficients(coeffs, pv);
+//  //output.setZero(numF,3*n);
+//  //for (int fi=0; fi<numF; ++fi)
+//  //{
+//  //  const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &b1 = B1.row(fi);
+//  //  const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &b2 = B2.row(fi);
+//  //  for (int i=0; i<n; ++i)
+//  //    output.block(fi,3*i, 1, 3) = pv[i](fi,0)*b1 + pv[i](fi,1)*b2;
+//  //}
+//  return true;
+//}
+//
+//template<typename DerivedV, typename DerivedF>
+//IGL_INLINE void igl::GeneralPolyVectorFieldFinder<DerivedV, DerivedF>::setFieldFromGeneralCoefficients(const  std::vector<Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1>> &coeffs,
+//                                                            std::vector<Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 2>> &pv)
+//{
+//  pv.assign(n, Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 2>::Zero(numF, 2));
+//  for (int i = 0; i <numF; ++i)
+//  {
+//
+//    //    poly coefficients: 1, 0, -Acoeff, 0, Bcoeff
+//    //    matlab code from roots (given there are no trailing zeros in the polynomial coefficients)
+//    Eigen::Matrix<std::complex<DerivedV::Scalar>, Eigen::Dynamic,1> polyCoeff;
+//    polyCoeff.setZero(n+1,1);
+//    polyCoeff[0] = 1.;
+//    int sign = 1;
+//    for (int k =0; k<n; ++k)
+//    {
+//      sign = -sign;
+//      int degree = k+1;
+//      polyCoeff[degree] = (1.*sign)*coeffs[k](i);
+//    }
+//
+//    Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1> roots;
+//    igl::polyRoots<std::complex<typename DerivedV::Scalar>, typename DerivedV::Scalar >(polyCoeff,roots);
+//    for (int k=0; k<n; ++k)
+//    {
+//      pv[k](i,0) = real(roots[k]);
+//      pv[k](i,1) = imag(roots[k]);
+//    }
+//  }
+//
+//}
+//
+//
+//template<typename DerivedV, typename DerivedF>
+//IGL_INLINE void igl::GeneralPolyVectorFieldFinder<DerivedV, DerivedF>::computeCoefficientLaplacian(int n, Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &D)
+//{
+//  std::vector<Eigen::Triplet<std::complex<typename DerivedV::Scalar> >> tripletList;
+//
+//  // For every non-border edge
+//  for (unsigned eid=0; eid<numE; ++eid)
+//  {
+//    if (!isBorderEdge[eid])
+//    {
+//      int fid0 = E2F(eid,0);
+//      int fid1 = E2F(eid,1);
+//
+//      tripletList.push_back(Eigen::Triplet<std::complex<typename DerivedV::Scalar> >(fid0,
+//                                           fid0,
+//                                           std::complex<typename DerivedV::Scalar>(1.)));
+//      tripletList.push_back(Eigen::Triplet<std::complex<typename DerivedV::Scalar> >(fid1,
+//                                           fid1,
+//                                           std::complex<typename DerivedV::Scalar>(1.)));
+//      tripletList.push_back(Eigen::Triplet<std::complex<typename DerivedV::Scalar> >(fid0,
+//                                           fid1,
+//                                                                                     -1.*std::polar(1.,-1.*n*K[eid])));
+//      tripletList.push_back(Eigen::Triplet<std::complex<typename DerivedV::Scalar> >(fid1,
+//                                           fid0,
+//                                                                                     -1.*std::polar(1.,1.*n*K[eid])));
+//
+//    }
+//  }
+//  D.resize(numF,numF);
+//  D.setFromTriplets(tripletList.begin(), tripletList.end());
+//
+//
+//}
+//
+////this gives the coefficients without the (-1)^k that multiplies them
+//template<typename DerivedV, typename DerivedF>
+//IGL_INLINE void igl::GeneralPolyVectorFieldFinder<DerivedV, DerivedF>::getGeneralCoeffConstraints(const Eigen::VectorXi &isConstrained,
+//                                                       const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> &cfW,
+//                                                       int k,
+//                                                       const Eigen::VectorXi &rootsIndex,
+//                                                       Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1> &Ck)
+//{
+//  int numConstrained = isConstrained.sum();
+//  Ck.resize(numConstrained,1);
+//  // int n = rootsIndex.cols();
+//
+//  Eigen::MatrixXi allCombs;
+//  {
+//    Eigen::VectorXi V = Eigen::VectorXi::LinSpaced(n,0,n-1);
+//    igl::nchoosek(V,k+1,allCombs);
+//  }
+//
+//  int ind = 0;
+//  for (int fi = 0; fi <numF; ++fi)
+//  {
+//    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &b1 = B1.row(fi);
+//    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &b2 = B2.row(fi);
+//    if(isConstrained[fi])
+//    {
+//      std::complex<typename DerivedV::Scalar> ck(0);
+//
+//      for (int j = 0; j < allCombs.rows(); ++j)
+//      {
+//        std::complex<typename DerivedV::Scalar> tk(1.);
+//        //collect products
+//        for (int i = 0; i < allCombs.cols(); ++i)
+//        {
+//          int index = allCombs(j,i);
+//
+//          int ri = rootsIndex[index];
+//          Eigen::Matrix<typename DerivedV::Scalar, 1, 3> w;
+//          if (ri>0)
+//            w = cfW.block(fi,3*(ri-1),1,3);
+//          else
+//            w = -cfW.block(fi,3*(-ri-1),1,3);
+//          typename DerivedV::Scalar w0 = w.dot(b1);
+//          typename DerivedV::Scalar w1 = w.dot(b2);
+//          std::complex<typename DerivedV::Scalar> u(w0,w1);
+//          tk*= u;
+//        }
+//        //collect sum
+//        ck += tk;
+//      }
+//      Ck(ind) = ck;
+//      ind ++;
+//    }
+//  }
+//
+//
+//}
+//
+//template<typename DerivedV, typename DerivedF>
+//IGL_INLINE void igl::GeneralPolyVectorFieldFinder<DerivedV, DerivedF>::computek()
+//{
+//  K.setZero(numE);
+//  // For every non-border edge
+//  for (unsigned eid=0; eid<numE; ++eid)
+//  {
+//    if (!isBorderEdge[eid])
+//    {
+//      int fid0 = E2F(eid,0);
+//      int fid1 = E2F(eid,1);
+//
+//      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> N0 = FN.row(fid0);
+//      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> N1 = FN.row(fid1);
+//
+//      // find common edge on triangle 0 and 1
+//      int fid0_vc = -1;
+//      int fid1_vc = -1;
+//      for (unsigned i=0;i<3;++i)
+//      {
+//        if (F2E(fid0,i) == eid)
+//          fid0_vc = i;
+//        if (F2E(fid1,i) == eid)
+//          fid1_vc = i;
+//      }
+//      assert(fid0_vc != -1);
+//      assert(fid1_vc != -1);
+//
+//      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> common_edge = V.row(F(fid0,(fid0_vc+1)%3)) - V.row(F(fid0,fid0_vc));
+//      common_edge.normalize();
+//
+//      // Map the two triangles in a new space where the common edge is the x axis and the N0 the z axis
+//      Eigen::Matrix<typename DerivedV::Scalar, 3, 3> P;
+//      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> o = V.row(F(fid0,fid0_vc));
+//      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> tmp = -N0.cross(common_edge);
+//      P << common_edge, tmp, N0;
+////      P.transposeInPlace();
+//
+//
+//      Eigen::Matrix<typename DerivedV::Scalar, 3, 3> V0;
+//      V0.row(0) = V.row(F(fid0,0)) -o;
+//      V0.row(1) = V.row(F(fid0,1)) -o;
+//      V0.row(2) = V.row(F(fid0,2)) -o;
+//
+//      V0 = (P*V0.transpose()).transpose();
+//
+////      assert(V0(0,2) < 1e-10);
+////      assert(V0(1,2) < 1e-10);
+////      assert(V0(2,2) < 1e-10);
+//
+//      Eigen::Matrix<typename DerivedV::Scalar, 3, 3> V1;
+//      V1.row(0) = V.row(F(fid1,0)) -o;
+//      V1.row(1) = V.row(F(fid1,1)) -o;
+//      V1.row(2) = V.row(F(fid1,2)) -o;
+//      V1 = (P*V1.transpose()).transpose();
+//
+////      assert(V1(fid1_vc,2) < 10e-10);
+////      assert(V1((fid1_vc+1)%3,2) < 10e-10);
+//
+//      // compute rotation R such that R * N1 = N0
+//      // i.e. map both triangles to the same plane
+//      double alpha = -atan2(V1((fid1_vc+2)%3,2),V1((fid1_vc+2)%3,1));
+//
+//      Eigen::Matrix<typename DerivedV::Scalar, 3, 3> R;
+//      R << 1,          0,            0,
+//      0, cos(alpha), -sin(alpha) ,
+//      0, sin(alpha),  cos(alpha);
+//      V1 = (R*V1.transpose()).transpose();
+//
+////      assert(V1(0,2) < 1e-10);
+////      assert(V1(1,2) < 1e-10);
+////      assert(V1(2,2) < 1e-10);
+//
+//      // measure the angle between the reference frames
+//      // k_ij is the angle between the triangle on the left and the one on the right
+//      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> ref0 = V0.row(1) - V0.row(0);
+//      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> ref1 = V1.row(1) - V1.row(0);
+//
+//      ref0.normalize();
+//      ref1.normalize();
+//
+//      double ktemp = atan2(ref1(1),ref1(0)) - atan2(ref0(1),ref0(0));
+//
+//      // just to be sure, rotate ref0 using angle ktemp...
+//      Eigen::Matrix<typename DerivedV::Scalar, 2, 2> R2;
+//      R2 << cos(ktemp), -sin(ktemp), sin(ktemp), cos(ktemp);
+//
+//      Eigen::Matrix<typename DerivedV::Scalar, 1, 2> tmp1 = R2*(ref0.head(2)).transpose();
+//
+////      assert(tmp1(0) - ref1(0) < 1e-10);
+////      assert(tmp1(1) - ref1(1) < 1e-10);
+//
+//      K[eid] = ktemp;
+//    }
+//  }
+//
+//}
 
 
 IGL_INLINE void igl::n_polyvector_general(const Eigen::MatrixXd &V,
@@ -478,17 +475,19 @@ IGL_INLINE void igl::n_polyvector_general(const Eigen::MatrixXd &V,
                              const Eigen::VectorXi &I,
                              Eigen::MatrixXd &output)
 {
-  Eigen::VectorXi isConstrained = Eigen::VectorXi::Constant(F.rows(),0);
-  Eigen::MatrixXd cfW = Eigen::MatrixXd::Constant(F.rows(),bc.cols(),0);
-
-  for(unsigned i=0; i<b.size();++i)
-  {
-    isConstrained(b(i)) = 1;
-    cfW.row(b(i)) << bc.row(i);
-  }
-  int n = I.rows();
-  igl::GeneralPolyVectorFieldFinder<Eigen::MatrixXd, Eigen::MatrixXi> pvff(V,F,n);
-  pvff.solve(isConstrained, cfW, I, output);
+	// This functions is broken, please contact Olga Diamanti
+	assert(0);
+  //Eigen::VectorXi isConstrained = Eigen::VectorXi::Constant(F.rows(),0);
+  //Eigen::MatrixXd cfW = Eigen::MatrixXd::Constant(F.rows(),bc.cols(),0);
+
+  //for(unsigned i=0; i<b.size();++i)
+  //{
+  //  isConstrained(b(i)) = 1;
+  //  cfW.row(b(i)) << bc.row(i);
+  //}
+  //int n = I.rows();
+  //igl::GeneralPolyVectorFieldFinder<Eigen::MatrixXd, Eigen::MatrixXi> pvff(V,F,n);
+  //pvff.solve(isConstrained, cfW, I, output);
 }
 
 

+ 68 - 110
include/igl/point_simplex_squared_distance.cpp

@@ -12,6 +12,8 @@
 #include <limits>
 #include <cassert>
 
+
+
 template <
   int DIM,
   typename Derivedp,
@@ -20,129 +22,85 @@ template <
   typename Derivedsqr_d,
   typename Derivedc>
 IGL_INLINE void igl::point_simplex_squared_distance(
-  const Eigen::PlainObjectBase<Derivedp> & p,
-  const Eigen::PlainObjectBase<DerivedV> & V,
-  const Eigen::PlainObjectBase<DerivedEle> & Ele,
+  const Eigen::MatrixBase<Derivedp> & p,
+  const Eigen::MatrixBase<DerivedV> & V,
+  const Eigen::MatrixBase<DerivedEle> & Ele,
   const typename DerivedEle::Index primitive,
   Derivedsqr_d & sqr_d,
   Eigen::PlainObjectBase<Derivedc> & c)
 {
-  assert(p.size() == DIM);
-  assert(V.cols() == DIM);
-  assert(Ele.cols() <= DIM+1);
-  assert(Ele.cols() <= 3 && "Only simplices up to triangles are considered");
+  typedef typename Derivedp::Scalar Scalar;
+  typedef typename Eigen::Matrix<Scalar,1,DIM> Vector;
+  typedef Vector Point;
 
-  typedef Derivedsqr_d Scalar;
-  typedef typename Eigen::Matrix<Scalar,1,DIM> RowVectorDIMS;
-  sqr_d = std::numeric_limits<Scalar>::infinity();
-  const auto & set_min = 
-    [&sqr_d,&c](const Scalar & sqr_d_candidate, const RowVectorDIMS & c_candidate)
+  const auto & Dot = [](const Point & a, const Point & b)->Scalar
   {
-    if(sqr_d_candidate < sqr_d)
-    {
-      sqr_d = sqr_d_candidate;
-      c = c_candidate;
-    }
+    return a.dot(b);
   };
-
-  // Simplex size
-  const size_t ss = Ele.cols();
-  // Only one element per node
-  // plane unit normal
-  bool inside_triangle = false;
-  Scalar d_j = std::numeric_limits<Scalar>::infinity();
-  RowVectorDIMS pp;
-  // Only consider triangles, and non-degenerate triangles at that
-  if(ss == 3 && 
-      Ele(primitive,0) != Ele(primitive,1) && 
-      Ele(primitive,1) != Ele(primitive,2) && 
-      Ele(primitive,2) != Ele(primitive,0))
+  // Real-time collision detection, Ericson, Chapter 5
+  const auto & ClosestPtPointTriangle = 
+    [&Dot](Point p, Point a, Point b, Point c)->Point 
   {
-    assert(DIM == 3 && "Only implemented for 3D triangles");
-    typedef Eigen::Matrix<Scalar,1,3> RowVector3S;
-    // can't be const because of annoying DIM template
-    RowVector3S v10(0,0,0);
-    v10.head(DIM) = (V.row(Ele(primitive,1))- V.row(Ele(primitive,0)));
-    RowVector3S v20(0,0,0);
-    v20.head(DIM) = (V.row(Ele(primitive,2))- V.row(Ele(primitive,0)));
-    const RowVectorDIMS n = (v10.cross(v20)).head(DIM);
-    Scalar n_norm = n.norm();
-    if(n_norm > 0)
+    // Check if P in vertex region outside A
+    Vector ab = b - a;
+    Vector ac = c - a;
+    Vector ap = p - a;
+    Scalar d1 = Dot(ab, ap);
+    Scalar d2 = Dot(ac, ap);
+    if (d1 <= 0.0 && d2 <= 0.0) return a; // barycentric coordinates (1,0,0)
+    // Check if P in vertex region outside B
+    Vector bp = p - b;
+    Scalar d3 = Dot(ab, bp);
+    Scalar d4 = Dot(ac, bp);
+    if (d3 >= 0.0 && d4 <= d3) return b; // barycentric coordinates (0,1,0)
+    // Check if P in edge region of AB, if so return projection of P onto AB
+    Scalar vc = d1*d4 - d3*d2;
+    if( a != b)
     {
-      const RowVectorDIMS un = n/n.norm();
-      // vector to plane
-      const RowVectorDIMS bc = 
-        1./3.*
-        ( V.row(Ele(primitive,0))+
-          V.row(Ele(primitive,1))+
-          V.row(Ele(primitive,2)));
-      const auto & v = p-bc;
-      // projected point on plane
-      d_j = v.dot(un);
-      pp = p - d_j*un;
-      // determine if pp is inside triangle
-      Eigen::Matrix<Scalar,1,3> b;
-      barycentric_coordinates(
-            pp,
-            V.row(Ele(primitive,0)),
-            V.row(Ele(primitive,1)),
-            V.row(Ele(primitive,2)),
-            b);
-      inside_triangle = fabs(fabs(b(0)) + fabs(b(1)) + fabs(b(2)) - 1.) <= 1e-10;
-    }
-  }
-  const auto & point_point_squared_distance = [&](const RowVectorDIMS & s)
-  {
-    const Scalar sqr_d_s = (p-s).squaredNorm();
-    set_min(sqr_d_s,s);
-  };
-  if(inside_triangle)
-  {
-    // point-triangle squared distance
-    const Scalar sqr_d_j = d_j*d_j;
-    //cout<<"point-triangle..."<<endl;
-    set_min(sqr_d_j,pp);
-  }else
-  {
-    if(ss >= 2)
-    {
-      // point-segment distance
-      // number of edges
-      size_t ne = ss==3?3:1;
-      for(size_t x = 0;x<ne;x++)
-      {
-        const size_t e1 = Ele(primitive,(x+1)%ss);
-        const size_t e2 = Ele(primitive,(x+2)%ss);
-        const RowVectorDIMS & s = V.row(e1);
-        const RowVectorDIMS & d = V.row(e2);
-        // Degenerate edge
-        if(e1 == e2 || (s-d).squaredNorm()==0)
-        {
-          // only consider once
-          if(e1 < e2)
-          {
-            point_point_squared_distance(s);
-          }
-          continue;
-        }
-        Eigen::Matrix<Scalar,1,1> sqr_d_j_x(1,1);
-        Eigen::Matrix<Scalar,1,1> t(1,1);
-        project_to_line_segment(p,s,d,t,sqr_d_j_x);
-        const RowVectorDIMS q = s+t(0)*(d-s);
-        set_min(sqr_d_j_x(0),q);
+      if (vc <= 0.0 && d1 >= 0.0 && d3 <= 0.0) {
+        Scalar v = d1 / (d1 - d3);
+        return a + v * ab; // barycentric coordinates (1-v,v,0)
       }
-    }else
-    {
-      // So then Ele is just a list of points...
-      assert(ss == 1);
-      const RowVectorDIMS & s = V.row(Ele(primitive,0));
-      point_point_squared_distance(s);
     }
-  }
+    // Check if P in vertex region outside C
+    Vector cp = p - c;
+    Scalar d5 = Dot(ab, cp);
+    Scalar d6 = Dot(ac, cp);
+    if (d6 >= 0.0 && d5 <= d6) return c; // barycentric coordinates (0,0,1)
+    // Check if P in edge region of AC, if so return projection of P onto AC
+    Scalar vb = d5*d2 - d1*d6;
+    if (vb <= 0.0 && d2 >= 0.0 && d6 <= 0.0) {
+      Scalar w = d2 / (d2 - d6);
+      return a + w * ac; // barycentric coordinates (1-w,0,w)
+    }
+    // Check if P in edge region of BC, if so return projection of P onto BC
+    Scalar va = d3*d6 - d5*d4;
+    if (va <= 0.0 && (d4 - d3) >= 0.0 && (d5 - d6) >= 0.0) {
+      Scalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
+      return b + w * (c - b); // barycentric coordinates (0,1-w,w)
+    }
+    // P inside face region. Compute Q through its barycentric coordinates (u,v,w)
+    Scalar denom = 1.0 / (va + vb + vc);
+    Scalar v = vb * denom;
+    Scalar w = vc * denom;
+    return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = 1.0-v-w
+  };
+
+  assert(p.size() == DIM);
+  assert(V.cols() == DIM);
+  assert(Ele.cols() <= DIM+1);
+  assert(Ele.cols() <= 3 && "Only simplices up to triangles are considered");
+
+  c = ClosestPtPointTriangle(
+    p,
+    V.row(Ele(primitive,0)),
+    V.row(Ele(primitive,1%Ele.cols())),
+    V.row(Ele(primitive,2%Ele.cols())));
+  sqr_d = (p-c).squaredNorm();
 }
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instanciation
-template void igl::point_simplex_squared_distance<2, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 2, 1, 1, 2> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&);
-template void igl::point_simplex_squared_distance<3, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
+template void igl::point_simplex_squared_distance<3, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
+template void igl::point_simplex_squared_distance<2, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, 1, 2, 1, 1, 2> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&);
 #endif

+ 3 - 3
include/igl/point_simplex_squared_distance.h

@@ -30,9 +30,9 @@ namespace igl
     typename Derivedsqr_d,
     typename Derivedc>
   IGL_INLINE void point_simplex_squared_distance(
-    const Eigen::PlainObjectBase<Derivedp> & p,
-    const Eigen::PlainObjectBase<DerivedV> & V,
-    const Eigen::PlainObjectBase<DerivedEle> & Ele,
+    const Eigen::MatrixBase<Derivedp> & p,
+    const Eigen::MatrixBase<DerivedV> & V,
+    const Eigen::MatrixBase<DerivedEle> & Ele,
     const typename DerivedEle::Index i,
     Derivedsqr_d & sqr_d,
     Eigen::PlainObjectBase<Derivedc> & c);

+ 1 - 1
include/igl/polyvector_field_matchings.cpp

@@ -168,7 +168,7 @@ IGL_INLINE typename DerivedC::Scalar igl::polyvector_field_matchings(
   Eigen::MatrixXi E, E2F, F2E;
   igl::edge_topology(V,F,E,F2E,E2F);
 
-#warning "Poor templating of igl::polyvector_field_matchings forces FN to be DerivedV (this could cause issues if DerivedV has fixed number of rows)"
+//#warning "Poor templating of igl::polyvector_field_matchings forces FN to be DerivedV (this could cause issues if DerivedV has fixed number of rows)"
   DerivedV FN;
   igl::per_face_normals(V,F,FN);
 

+ 15 - 17
include/igl/project_to_line.cpp

@@ -10,16 +10,17 @@
 #include <Eigen/Core>
 
 template <
-  typename MatP,
-  typename MatL,
-  typename Matt,
-  typename MatsqrD>
+  typename DerivedP, 
+  typename DerivedS, 
+  typename DerivedD, 
+  typename Derivedt, 
+  typename DerivedsqrD>
 IGL_INLINE void igl::project_to_line(
-  const MatP & P,
-  const MatL & S,
-  const MatL & D,
-  Matt & t,
-  MatsqrD & sqrD)
+  const Eigen::MatrixBase<DerivedP> & P,
+  const Eigen::MatrixBase<DerivedS> & S,
+  const Eigen::MatrixBase<DerivedD> & D,
+  Eigen::PlainObjectBase<Derivedt> & t,
+  Eigen::PlainObjectBase<DerivedsqrD> & sqrD)
 {
   // http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
 
@@ -32,7 +33,7 @@ IGL_INLINE void igl::project_to_line(
   // number of points
   int np  = P.rows();
   // vector from source to destination
-  MatL DmS = D-S;
+  DerivedD DmS = D-S;
   double v_sqrlen = (double)(DmS.squaredNorm());
   assert(v_sqrlen != 0);
   // resize output
@@ -42,12 +43,12 @@ IGL_INLINE void igl::project_to_line(
 #pragma omp parallel for if (np>10000)
   for(int i = 0;i<np;i++)
   {
-    MatP Pi = P.row(i);
+    const typename DerivedP::ConstRowXpr Pi = P.row(i);
     // vector from point i to source
-    MatL SmPi = S-Pi;
+    const DerivedD SmPi = S-Pi;
     t(i) = -(DmS.array()*SmPi.array()).sum() / v_sqrlen;
     // P projected onto line
-    MatL projP = (1-t(i))*S + t(i)*D;
+    const DerivedD projP = (1-t(i))*S + t(i)*D;
     sqrD(i) = (Pi-projP).squaredNorm();
   }
 }
@@ -119,10 +120,7 @@ IGL_INLINE void igl::project_to_line(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
-template void igl::project_to_line<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::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, 1, 0, -1, 1> const&, 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>&);
 template void igl::project_to_line<double>(double, double, double, double, double, double, double, double, double, double&, double&);
 template void igl::project_to_line<double>(double, double, double, double, double, double, double, double, double, double&, double&,double&,double&, double&);
-template void igl::project_to_line<Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >, 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, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&);
-template void igl::project_to_line<Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >, 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, 2, 1, 1, 2> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&);
-template void igl::project_to_line<Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 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> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
+template void igl::project_to_line<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 1, 0, 1, 1>, Eigen::Matrix<double, 1, 1, 0, 1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&);
 #endif

+ 12 - 15
include/igl/project_to_line.h

@@ -8,6 +8,7 @@
 #ifndef IGL_PROJECT_TO_LINE_H
 #define IGL_PROJECT_TO_LINE_H
 #include "igl_inline.h"
+#include <Eigen/Core>
 
 namespace igl
 {
@@ -18,11 +19,6 @@ namespace igl
   //
   // [T,sqrD] = project_to_lines(P,S,D)
   //
-  // Templates:
-  //   MatP matrix template for P, implementing .cols(), .rows()
-  //   MatL matrix template for S and D, implementing .size(), .array(), .sum()
-  //   Matt matrix template for t 
-  //   MatsqrD matrix template for sqrD
   // Inputs:
   //   P  #P by dim list of points to be projected
   //   S  size dim start position of line vector
@@ -33,17 +29,18 @@ namespace igl
   //
   //
   template <
-    typename MatP, 
-    typename MatL, 
-    typename Matt, 
-    typename MatsqrD>
+    typename DerivedP, 
+    typename DerivedS, 
+    typename DerivedD, 
+    typename Derivedt, 
+    typename DerivedsqrD>
   IGL_INLINE void project_to_line(
-    const MatP & P,
-    const MatL & S,
-    const MatL & D,
-    Matt & t,
-    MatsqrD & sqrD);
-  
+    const Eigen::MatrixBase<DerivedP> & P,
+    const Eigen::MatrixBase<DerivedS> & S,
+    const Eigen::MatrixBase<DerivedD> & D,
+    Eigen::PlainObjectBase<Derivedt> & t,
+    Eigen::PlainObjectBase<DerivedsqrD> & sqrD);
+
   // Same as above but for a single query point
   template <typename Scalar>
   IGL_INLINE void project_to_line(

+ 4 - 6
include/igl/project_to_line_segment.cpp

@@ -16,9 +16,9 @@ template <
   typename Derivedt,
   typename DerivedsqrD>
 IGL_INLINE void igl::project_to_line_segment(
-  const Eigen::PlainObjectBase<DerivedP> & P,
-  const Eigen::PlainObjectBase<DerivedS> & S,
-  const Eigen::PlainObjectBase<DerivedD> & D,
+  const Eigen::MatrixBase<DerivedP> & P,
+  const Eigen::MatrixBase<DerivedS> & S,
+  const Eigen::MatrixBase<DerivedD> & D,
   Eigen::PlainObjectBase<Derivedt> & t,
   Eigen::PlainObjectBase<DerivedsqrD> & sqrD)
 {
@@ -43,7 +43,5 @@ IGL_INLINE void igl::project_to_line_segment(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
-template void igl::project_to_line_segment<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 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, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&);
-template void igl::project_to_line_segment<Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, 1, 1, 0, 1, 1>, Eigen::Matrix<double, 1, 1, 0, 1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&);
-template void igl::project_to_line_segment<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 3, 1, 0, 3, 1>, Eigen::Matrix<double, 3, 1, 0, 3, 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<double, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
+template void igl::project_to_line_segment<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 1, 0, 1, 1>, Eigen::Matrix<double, 1, 1, 0, 1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&);
 #endif

+ 3 - 3
include/igl/project_to_line_segment.h

@@ -35,9 +35,9 @@ namespace igl
     typename Derivedt, 
     typename DerivedsqrD>
   IGL_INLINE void project_to_line_segment(
-    const Eigen::PlainObjectBase<DerivedP> & P,
-    const Eigen::PlainObjectBase<DerivedS> & S,
-    const Eigen::PlainObjectBase<DerivedD> & D,
+    const Eigen::MatrixBase<DerivedP> & P,
+    const Eigen::MatrixBase<DerivedS> & S,
+    const Eigen::MatrixBase<DerivedD> & D,
     Eigen::PlainObjectBase<Derivedt> & t,
     Eigen::PlainObjectBase<DerivedsqrD> & sqrD);
 }

+ 3 - 3
include/igl/writeOBJ.cpp

@@ -33,7 +33,7 @@ IGL_INLINE bool igl::writeOBJ(
   // Loop over V
   for(int i = 0;i<(int)V.rows();i++)
   {
-    fprintf(obj_file,"v %0.15g %0.15g %0.15g\n",
+    fprintf(obj_file,"v %0.17g %0.17g %0.17g\n",
       V(i,0),
       V(i,1),
       V(i,2)
@@ -45,7 +45,7 @@ IGL_INLINE bool igl::writeOBJ(
   {
     for(int i = 0;i<(int)CN.rows();i++)
     {
-      fprintf(obj_file,"vn %0.15g %0.15g %0.15g\n",
+      fprintf(obj_file,"vn %0.17g %0.17g %0.17g\n",
               CN(i,0),
               CN(i,1),
               CN(i,2)
@@ -60,7 +60,7 @@ IGL_INLINE bool igl::writeOBJ(
   {
     for(int i = 0;i<(int)TC.rows();i++)
     {
-      fprintf(obj_file, "vt %0.15g %0.15g\n",TC(i,0),TC(i,1));
+      fprintf(obj_file, "vt %0.17g %0.17g\n",TC(i,0),TC(i,1));
     }
     fprintf(obj_file,"\n");
   }

+ 0 - 0
include/igl/xml/serialization_test.cpp → include/igl/xml/serialization_test.skip


+ 0 - 1
scripts/pre-commit.sh

@@ -9,7 +9,6 @@ NC='\033[0m'
 
 ## Throw error if any files contain "std::__1"
 
-
 # list of changed files
 CHANGED=$(git diff --cached --name-only --diff-filter=ACM)
 # Ignore this file!

+ 1 - 1
tutorial/705_MarchingCubes/main.cpp

@@ -65,7 +65,7 @@ int main(int argc, char * argv[])
 )";
   igl::viewer::Viewer viewer;
   viewer.data.set_mesh(SV,SF);
-  viewer.callback_key_down = 
+  viewer.callback_key_down =
     [&](igl::viewer::Viewer & viewer, unsigned char key, int mod)->bool
     {
       switch(key)