瀏覽代碼

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

Former-commit-id: 03a58d0b0cc6889bceb7707a7e70a8a6698c2762
Olga Diamanti 9 年之前
父節點
當前提交
b0f4367e2f
共有 100 個文件被更改,包括 4041 次插入2076 次删除
  1. 2 0
      .gitignore
  2. 2 2
      .travis.yml
  3. 4 3
      README.md
  4. 950 0
      include/igl/AABB.cpp
  5. 21 946
      include/igl/AABB.h
  6. 20 32
      include/igl/ambient_occlusion.cpp
  7. 107 0
      include/igl/cat.cpp
  8. 4 4
      include/igl/copyleft/cgal/SelfIntersectMesh.h
  9. 10 1
      include/igl/copyleft/cgal/half_space_box.cpp
  10. 70 54
      include/igl/copyleft/cgal/intersect_other.cpp
  11. 13 24
      include/igl/copyleft/cgal/intersect_other.h
  12. 40 7
      include/igl/copyleft/cgal/intersect_with_half_space.cpp
  13. 28 3
      include/igl/copyleft/cgal/intersect_with_half_space.h
  14. 2 0
      include/igl/copyleft/cgal/mesh_boolean.cpp
  15. 31 23
      include/igl/copyleft/cgal/point_mesh_squared_distance.cpp
  16. 31 15
      include/igl/copyleft/cgal/point_mesh_squared_distance.h
  17. 50 0
      include/igl/copyleft/cgal/point_solid_signed_squared_distance.cpp
  18. 48 0
      include/igl/copyleft/cgal/point_solid_signed_squared_distance.h
  19. 1 0
      include/igl/copyleft/cgal/propagate_winding_numbers.cpp
  20. 5 12
      include/igl/copyleft/cgal/remesh_intersections.cpp
  21. 0 7
      include/igl/copyleft/cgal/remesh_intersections.h
  22. 1 1
      include/igl/copyleft/cgal/string_to_mesh_boolean_type.cpp
  23. 106 0
      include/igl/copyleft/cgal/trim_with_solid.cpp
  24. 63 0
      include/igl/copyleft/cgal/trim_with_solid.h
  25. 49 0
      include/igl/copyleft/swept_volume.cpp
  26. 41 0
      include/igl/copyleft/swept_volume.h
  27. 16 22
      include/igl/doublearea.cpp
  28. 22 21
      include/igl/edge_lengths.cpp
  29. 1 0
      include/igl/embree/ambient_occlusion.cpp
  30. 1 1
      include/igl/embree/ambient_occlusion.h
  31. 26 25
      include/igl/embree/reorient_facets_raycast.cpp
  32. 24 8
      include/igl/extract_manifold_patches.cpp
  33. 6 0
      include/igl/extract_manifold_patches.h
  34. 2 1
      include/igl/fit_rotations.cpp
  35. 81 0
      include/igl/flood_fill.cpp
  36. 23 0
      include/igl/flood_fill.h
  37. 23 0
      include/igl/grid.cpp
  38. 20 0
      include/igl/grid.h
  39. 1 1
      include/igl/infinite_cost_stopping_condition.cpp
  40. 13 21
      include/igl/internal_angles.cpp
  41. 11 0
      include/igl/list_to_matrix.cpp
  42. 185 0
      include/igl/parallel_for.h
  43. 1 0
      include/igl/parula.cpp
  44. 23 11
      include/igl/per_vertex_normals.cpp
  45. 47 0
      include/igl/png/readPNG.cpp
  46. 39 0
      include/igl/png/readPNG.h
  47. 46 0
      include/igl/png/writePNG.cpp
  48. 41 0
      include/igl/png/writePNG.h
  49. 2 0
      include/igl/project_to_line.cpp
  50. 2 0
      include/igl/project_to_line_segment.cpp
  51. 6 6
      include/igl/random_dir.cpp
  52. 27 26
      include/igl/repdiag.cpp
  53. 1 0
      include/igl/resolve_duplicated_faces.cpp
  54. 5 5
      include/igl/round.cpp
  55. 2 0
      include/igl/slice.cpp
  56. 5 1
      include/igl/slice_mask.cpp
  57. 69 82
      include/igl/sort.cpp
  58. 20 0
      include/igl/swept_volume_bounding_box.cpp
  59. 31 0
      include/igl/swept_volume_bounding_box.h
  60. 113 0
      include/igl/swept_volume_signed_distance.cpp
  61. 57 0
      include/igl/swept_volume_signed_distance.h
  62. 1 1
      include/igl/triangle/triangulate.h
  63. 27 21
      include/igl/triangle_triangle_adjacency.cpp
  64. 5 3
      include/igl/uniformly_sample_two_manifold.h
  65. 5 0
      include/igl/unique.cpp
  66. 5 0
      include/igl/unique_edge_map.cpp
  67. 6 12
      include/igl/unique_simplices.cpp
  68. 1 0
      include/igl/unproject_onto_mesh.cpp
  69. 2 0
      include/igl/upsample.cpp
  70. 5 5
      include/igl/viewer/Viewer.cpp
  71. 5 3
      include/igl/viewer/ViewerData.cpp
  72. 4 1
      include/igl/viewer/ViewerData.h
  73. 51 0
      include/igl/voxel_grid.cpp
  74. 28 0
      include/igl/voxel_grid.h
  75. 2 0
      include/igl/writeMESH.cpp
  76. 2 0
      include/igl/writeSTL.cpp
  77. 2 0
      include/igl/writeWRL.cpp
  78. 2 0
      include/igl/write_triangle_mesh.cpp
  79. 25 10
      index.html
  80. 1 9
      optional/index.html
  81. 33 8
      python/CMakeLists.txt
  82. 2 2
      python/README.md
  83. 5 1
      python/iglhelpers.py
  84. 18 0
      python/modules/copyleft/py_igl_cgal.cpp
  85. 3 3
      python/modules/copyleft/py_igl_comiso.cpp
  86. 18 0
      python/modules/copyleft/py_igl_tetgen.cpp
  87. 18 0
      python/modules/py_igl_embree.cpp
  88. 16 0
      python/modules/py_igl_png.cpp
  89. 18 0
      python/modules/py_igl_triangle.cpp
  90. 17 1
      python/modules/py_igl_viewer.cpp
  91. 33 1
      python/modules/py_vector.cpp
  92. 644 481
      python/py_doc.cpp
  93. 67 52
      python/py_doc.h
  94. 110 96
      python/py_igl.cpp
  95. 107 0
      python/py_igl/copyleft/cgal/py_mesh_boolean.cpp
  96. 16 0
      python/py_igl/copyleft/tetgen/py_tetrahedralize.cpp
  97. 16 0
      python/py_igl/embree/py_ambient_occlusion.cpp
  98. 14 0
      python/py_igl/png/py_readPNG.cpp
  99. 15 0
      python/py_igl/png/py_writePNG.cpp
  100. 1 1
      python/py_igl/py_AABB.cpp

+ 2 - 0
.gitignore

@@ -93,3 +93,5 @@ tests/bin
 python/build3
 python/build3
 *.pyc
 *.pyc
 python/build4
 python/build4
+python/scripts/generated
+python/builddebug

+ 2 - 2
.travis.yml

@@ -11,13 +11,13 @@ matrix:
         - cd python
         - cd python
         - mkdir build
         - mkdir build
         - cd build
         - cd build
-        - cmake -DCMAKE_CXX_COMPILER=g++-4.8 -DCMAKE_C_COMPILER=gcc-4.8 -DLIBIGL_WITH_EMBREE=OFF ../
+        - cmake -DCMAKE_CXX_COMPILER=g++-4.8 -DCMAKE_C_COMPILER=gcc-4.8 -DLIBIGL_WITH_EMBREE=OFF -DLIBIGL_USE_STATIC_LIBRARY=ON ../
         - make -j 2
         - make -j 2
         - cd ../../
         - cd ../../
         - cd tutorial
         - cd tutorial
         - mkdir build
         - mkdir build
         - cd build
         - cd build
-        - cmake -DLIBIGL_USE_STATIC_LIBRARY=ON -DCMAKE_CXX_COMPILER=g++-4.8 -DCMAKE_C_COMPILER=gcc-4.8 -DLIBIGL_WITH_EMBREE=OFF ../
+        - cmake -DLIBIGL_USE_STATIC_LIBRARY=ON -DCMAKE_CXX_COMPILER=g++-4.8 -DCMAKE_C_COMPILER=gcc-4.8 ../
         - make -j 2
         - make -j 2
       addons:
       addons:
         apt:
         apt:

+ 4 - 3
README.md

@@ -23,8 +23,8 @@ It is **a header-only library**. You do not need to compile anything to use,
 just include igl headers (e.g. `#include <igl/cotmatrix.h>`) and run.  Each
 just include igl headers (e.g. `#include <igl/cotmatrix.h>`) and run.  Each
 header file contains a single function (e.g. `igl/cotmatrix.h` contains
 header file contains a single function (e.g. `igl/cotmatrix.h` contains
 `igl::cotmatrix()`). Most are tailored to operate on a generic triangle mesh
 `igl::cotmatrix()`). Most are tailored to operate on a generic triangle mesh
-stored in an n-by-3 matrix of vertex positions V and an m-by-3 matrix of
-triangle indices F.
+stored in an n-by-3 matrix of vertex positions `V` and an m-by-3 matrix of
+triangle indices `F`.
 
 
 _Optionally_ the library may also be [pre-compiled](optional/) into a statically
 _Optionally_ the library may also be [pre-compiled](optional/) into a statically
 linked library, for faster compile times with your projects. This only effects
 linked library, for faster compile times with your projects. This only effects
@@ -195,6 +195,7 @@ Eurographics/ACM Symposium on Geometry Processing software award. Here are a
 few labs/companies/institutions using libigl:
 few labs/companies/institutions using libigl:
 
 
  - [Adobe Research](http://www.adobe.com/technology/)  
  - [Adobe Research](http://www.adobe.com/technology/)  
+ - [Electronic Arts, Inc](http://www.ea.com)
  - [Mesh](http://meshconsultants.ca/), consultants, Canada
  - [Mesh](http://meshconsultants.ca/), consultants, Canada
  - [Pixar Research](http://graphics.pixar.com/research/)
  - [Pixar Research](http://graphics.pixar.com/research/)
  - [Spine by Esoteric Software](http://esotericsoftware.com/) is an animation tool dedicated to 2D characters.
  - [Spine by Esoteric Software](http://esotericsoftware.com/) is an animation tool dedicated to 2D characters.
@@ -243,7 +244,7 @@ page](https://github.com/libigl/libigl/issues).
 
 
 ## Copyright
 ## Copyright
 2016 Alec Jacobson, Daniele Panozzo, Christian Schüller, Olga Diamanti, Qingnan
 2016 Alec Jacobson, Daniele Panozzo, Christian Schüller, Olga Diamanti, Qingnan
-Zhou, Nico Pietroni, Stefan Brugger, Kenshi Takayama, Wenzel Jakob, Nikolas De
+Zhou, Sebastian Koch, Nico Pietroni, Stefan Brugger, Kenshi Takayama, Wenzel Jakob, Nikolas De
 Giorgis, Luigi Rocca, Leonardo Sacht, Kevin Walliman, Olga Sorkine-Hornung, and others.
 Giorgis, Luigi Rocca, Leonardo Sacht, Kevin Walliman, Olga Sorkine-Hornung, and others.
 
 
 Please see individual files for appropriate copyright notices.
 Please see individual files for appropriate copyright notices.

+ 950 - 0
include/igl/AABB.cpp

@@ -0,0 +1,950 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "AABB.h"
+#include "EPS.h"
+#include "barycenter.h"
+#include "barycentric_coordinates.h"
+#include "colon.h"
+#include "colon.h"
+#include "doublearea.h"
+#include "matlab_format.h"
+#include "point_simplex_squared_distance.h"
+#include "project_to_line_segment.h"
+#include "sort.h"
+#include "volume.h"
+#include "ray_box_intersect.h"
+#include "ray_mesh_intersect.h"
+#include <iostream>
+#include <iomanip>
+#include <limits>
+#include <list>
+#include <queue>
+#include <stack>
+
+template <typename DerivedV, int DIM>
+  template <typename Derivedbb_mins, typename Derivedbb_maxs>
+IGL_INLINE void igl::AABB<DerivedV,DIM>::init(
+    const Eigen::PlainObjectBase<DerivedV> & V,
+    const Eigen::MatrixXi & Ele, 
+    const Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
+    const Eigen::PlainObjectBase<Derivedbb_maxs> & bb_maxs,
+    const Eigen::VectorXi & elements,
+    const int i)
+{
+  using namespace std;
+  using namespace Eigen;
+  deinit();
+  if(bb_mins.size() > 0)
+  {
+    assert(bb_mins.rows() == bb_maxs.rows() && "Serial tree arrays must match");
+    assert(bb_mins.cols() == V.cols() && "Serial tree array dim must match V");
+    assert(bb_mins.cols() == bb_maxs.cols() && "Serial tree arrays must match");
+    assert(bb_mins.rows() == elements.rows() &&
+        "Serial tree arrays must match");
+    // construct from serialization
+    m_box.extend(bb_mins.row(i).transpose());
+    m_box.extend(bb_maxs.row(i).transpose());
+    m_primitive = elements(i);
+    // Not leaf then recurse
+    if(m_primitive == -1)
+    {
+      m_left = new AABB();
+      m_left->init( V,Ele,bb_mins,bb_maxs,elements,2*i+1);
+      m_right = new AABB();
+      m_right->init( V,Ele,bb_mins,bb_maxs,elements,2*i+2);
+      //m_depth = std::max( m_left->m_depth, m_right->m_depth)+1;
+    }
+  }else
+  {
+    VectorXi allI = colon<int>(0,Ele.rows()-1);
+    MatrixXDIMS BC;
+    if(Ele.cols() == 1)
+    {
+      // points
+      BC = V;
+    }else
+    {
+      // Simplices
+      barycenter(V,Ele,BC);
+    }
+    MatrixXi SI(BC.rows(),BC.cols());
+    {
+      MatrixXDIMS _;
+      MatrixXi IS;
+      igl::sort(BC,1,true,_,IS);
+      // Need SI(i) to tell which place i would be sorted into
+      const int dim = IS.cols();
+      for(int i = 0;i<IS.rows();i++)
+      {
+        for(int d = 0;d<dim;d++)
+        {
+          SI(IS(i,d),d) = i;
+        }
+      }
+    }
+    init(V,Ele,SI,allI);
+  }
+}
+
+  template <typename DerivedV, int DIM>
+void igl::AABB<DerivedV,DIM>::init(
+    const Eigen::PlainObjectBase<DerivedV> & V,
+    const Eigen::MatrixXi & Ele)
+{
+  using namespace Eigen;
+  // deinit will be immediately called...
+  return init(V,Ele,MatrixXDIMS(),MatrixXDIMS(),VectorXi(),0);
+}
+
+  template <typename DerivedV, int DIM>
+IGL_INLINE void igl::AABB<DerivedV,DIM>::init(
+    const Eigen::PlainObjectBase<DerivedV> & V,
+    const Eigen::MatrixXi & Ele, 
+    const Eigen::MatrixXi & SI,
+    const Eigen::VectorXi & I)
+{
+  using namespace Eigen;
+  using namespace std;
+  deinit();
+  if(V.size() == 0 || Ele.size() == 0 || I.size() == 0)
+  {
+    return;
+  }
+  assert(DIM == V.cols() && "V.cols() should matched declared dimension");
+  //const Scalar inf = numeric_limits<Scalar>::infinity();
+  m_box = AlignedBox<Scalar,DIM>();
+  // Compute bounding box
+  for(int i = 0;i<I.rows();i++)
+  {
+    for(int c = 0;c<Ele.cols();c++)
+    {
+      m_box.extend(V.row(Ele(I(i),c)).transpose());
+      m_box.extend(V.row(Ele(I(i),c)).transpose());
+    }
+  }
+  switch(I.size())
+  {
+    case 0:
+      {
+        assert(false);
+      }
+    case 1:
+      {
+        m_primitive = I(0);
+        break;
+      }
+    default:
+      {
+        // Compute longest direction
+        int max_d = -1;
+        m_box.diagonal().maxCoeff(&max_d);
+        // Can't use median on BC directly because many may have same value,
+        // but can use median on sorted BC indices
+        VectorXi SIdI(I.rows());
+        for(int i = 0;i<I.rows();i++)
+        {
+          SIdI(i) = SI(I(i),max_d);
+        }
+        // Since later I use <= I think I don't need to worry about odd/even
+        // Pass by copy to avoid changing input
+        const auto median = [](VectorXi A)->Scalar
+        {
+          size_t n = A.size()/2;
+          nth_element(A.data(),A.data()+n,A.data()+A.size());
+          if(A.rows() % 2 == 1)
+          {
+            return A(n);
+          }else
+          {
+            nth_element(A.data(),A.data()+n-1,A.data()+A.size());
+            return 0.5*(A(n)+A(n-1));
+          }
+        };
+        const Scalar med = median(SIdI);
+        VectorXi LI((I.rows()+1)/2),RI(I.rows()/2);
+        assert(LI.rows()+RI.rows() == I.rows());
+        // Distribute left and right
+        {
+          int li = 0;
+          int ri = 0;
+          for(int i = 0;i<I.rows();i++)
+          {
+            if(SIdI(i)<=med)
+            {
+              LI(li++) = I(i);
+            }else
+            {
+              RI(ri++) = I(i);
+            }
+          }
+        }
+        //m_depth = 0;
+        if(LI.rows()>0)
+        {
+          m_left = new AABB();
+          m_left->init(V,Ele,SI,LI);
+          //m_depth = std::max(m_depth, m_left->m_depth+1);
+        }
+        if(RI.rows()>0)
+        {
+          m_right = new AABB();
+          m_right->init(V,Ele,SI,RI);
+          //m_depth = std::max(m_depth, m_right->m_depth+1);
+        }
+      }
+  }
+}
+
+template <typename DerivedV, int DIM>
+IGL_INLINE bool igl::AABB<DerivedV,DIM>::is_leaf() const
+{
+  return m_primitive != -1;
+}
+
+template <typename DerivedV, int DIM>
+template <typename Derivedq>
+IGL_INLINE std::vector<int> igl::AABB<DerivedV,DIM>::find(
+    const Eigen::PlainObjectBase<DerivedV> & V,
+    const Eigen::MatrixXi & Ele, 
+    const Eigen::PlainObjectBase<Derivedq> & q,
+    const bool first) const
+{
+  using namespace std;
+  using namespace Eigen;
+  assert(q.size() == DIM && 
+      "Query dimension should match aabb dimension");
+  assert(Ele.cols() == V.cols()+1 && 
+      "AABB::find only makes sense for (d+1)-simplices");
+  const Scalar epsilon = igl::EPS<Scalar>();
+  // Check if outside bounding box
+  bool inside = m_box.contains(q.transpose());
+  if(!inside)
+  {
+    return std::vector<int>();
+  }
+  assert(m_primitive==-1 || (m_left == NULL && m_right == NULL));
+  if(is_leaf())
+  {
+    // Initialize to some value > -epsilon
+    Scalar a1=0,a2=0,a3=0,a4=0;
+    switch(DIM)
+    {
+      case 3:
+        {
+          // Barycentric coordinates
+          typedef Eigen::Matrix<Scalar,1,3> RowVector3S;
+          const RowVector3S V1 = V.row(Ele(m_primitive,0));
+          const RowVector3S V2 = V.row(Ele(m_primitive,1));
+          const RowVector3S V3 = V.row(Ele(m_primitive,2));
+          const RowVector3S V4 = V.row(Ele(m_primitive,3));
+          a1 = volume_single(V2,V4,V3,(RowVector3S)q);
+          a2 = volume_single(V1,V3,V4,(RowVector3S)q);
+          a3 = volume_single(V1,V4,V2,(RowVector3S)q);
+          a4 = volume_single(V1,V2,V3,(RowVector3S)q);
+          break;
+        }
+      case 2:
+        {
+          // Barycentric coordinates
+          typedef Eigen::Matrix<Scalar,2,1> Vector2S;
+          const Vector2S V1 = V.row(Ele(m_primitive,0));
+          const Vector2S V2 = V.row(Ele(m_primitive,1));
+          const Vector2S V3 = V.row(Ele(m_primitive,2));
+          // Hack for now to keep templates simple. If becomes bottleneck
+          // consider using std::enable_if_t 
+          const Vector2S q2 = q.head(2);
+          a1 = doublearea_single(V1,V2,q2);
+          a2 = doublearea_single(V2,V3,q2);
+          a3 = doublearea_single(V3,V1,q2);
+          break;
+        }
+      default:assert(false);
+    }
+    // Normalization is important for correcting sign
+    Scalar sum = a1+a2+a3+a4;
+    a1 /= sum;
+    a2 /= sum;
+    a3 /= sum;
+    a4 /= sum;
+    if(
+        a1>=-epsilon && 
+        a2>=-epsilon && 
+        a3>=-epsilon && 
+        a4>=-epsilon)
+    {
+      return std::vector<int>(1,m_primitive);
+    }else
+    {
+      return std::vector<int>();
+    }
+  }
+  std::vector<int> left = m_left->find(V,Ele,q,first);
+  if(first && !left.empty())
+  {
+    return left;
+  }
+  std::vector<int> right = m_right->find(V,Ele,q,first);
+  if(first)
+  {
+    return right;
+  }
+  left.insert(left.end(),right.begin(),right.end());
+  return left;
+}
+
+template <typename DerivedV, int DIM>
+IGL_INLINE int igl::AABB<DerivedV,DIM>::subtree_size() const
+{
+  // 1 for self
+  int n = 1;
+  int n_left = 0,n_right = 0;
+  if(m_left != NULL)
+  {
+    n_left = m_left->subtree_size();
+  }
+  if(m_right != NULL)
+  {
+    n_right = m_right->subtree_size();
+  }
+  n += 2*std::max(n_left,n_right);
+  return n;
+}
+
+
+template <typename DerivedV, int DIM>
+template <typename Derivedbb_mins, typename Derivedbb_maxs>
+IGL_INLINE void igl::AABB<DerivedV,DIM>::serialize(
+    Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
+    Eigen::PlainObjectBase<Derivedbb_maxs> & bb_maxs,
+    Eigen::VectorXi & elements,
+    const int i) const
+{
+  using namespace std;
+  using namespace Eigen;
+  // Calling for root then resize output
+  if(i==0)
+  {
+    const int m = subtree_size();
+    //cout<<"m: "<<m<<endl;
+    bb_mins.resize(m,DIM);
+    bb_maxs.resize(m,DIM);
+    elements.resize(m,1);
+  }
+  //cout<<i<<" ";
+  bb_mins.row(i) = m_box.min();
+  bb_maxs.row(i) = m_box.max();
+  elements(i) = m_primitive;
+  if(m_left != NULL)
+  {
+    m_left->serialize(bb_mins,bb_maxs,elements,2*i+1);
+  }
+  if(m_right != NULL)
+  {
+    m_right->serialize(bb_mins,bb_maxs,elements,2*i+2);
+  }
+}
+
+template <typename DerivedV, int DIM>
+IGL_INLINE typename igl::AABB<DerivedV,DIM>::Scalar 
+igl::AABB<DerivedV,DIM>::squared_distance(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::MatrixXi & Ele, 
+  const RowVectorDIMS & p,
+  int & i,
+  RowVectorDIMS & c) const
+{
+  return squared_distance(V,Ele,p,std::numeric_limits<Scalar>::infinity(),i,c);
+}
+
+
+template <typename DerivedV, int DIM>
+IGL_INLINE typename igl::AABB<DerivedV,DIM>::Scalar 
+igl::AABB<DerivedV,DIM>::squared_distance(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::MatrixXi & Ele, 
+  const RowVectorDIMS & p,
+  Scalar min_sqr_d,
+  int & i,
+  RowVectorDIMS & c) const
+{
+  using namespace Eigen;
+  using namespace std;
+  Scalar sqr_d = min_sqr_d;
+  //assert(DIM == 3 && "Code has only been tested for DIM == 3");
+  assert((Ele.cols() == 3 || Ele.cols() == 2 || Ele.cols() == 1)
+    && "Code has only been tested for simplex sizes 3,2,1");
+
+  assert(m_primitive==-1 || (m_left == NULL && m_right == NULL));
+  if(is_leaf())
+  {
+    leaf_squared_distance(V,Ele,p,sqr_d,i,c);
+  }else
+  {
+    bool looked_left = false;
+    bool looked_right = false;
+    const auto & look_left = [&]()
+    {
+      int i_left;
+      RowVectorDIMS c_left = c;
+      Scalar sqr_d_left = m_left->squared_distance(V,Ele,p,sqr_d,i_left,c_left);
+      set_min(p,sqr_d_left,i_left,c_left,sqr_d,i,c);
+      looked_left = true;
+    };
+    const auto & look_right = [&]()
+    {
+      int i_right;
+      RowVectorDIMS c_right = c;
+      Scalar sqr_d_right = m_right->squared_distance(V,Ele,p,sqr_d,i_right,c_right);
+      set_min(p,sqr_d_right,i_right,c_right,sqr_d,i,c);
+      looked_right = true;
+    };
+
+    // must look left or right if in box
+    if(m_left->m_box.contains(p.transpose()))
+    {
+      look_left();
+    }
+    if(m_right->m_box.contains(p.transpose()))
+    {
+      look_right();
+    }
+    // if haven't looked left and could be less than current min, then look
+    Scalar  left_min_sqr_d = m_left->m_box.squaredExteriorDistance(p.transpose());
+    Scalar right_min_sqr_d = m_right->m_box.squaredExteriorDistance(p.transpose());
+    if(left_min_sqr_d < right_min_sqr_d)
+    {
+      if(!looked_left && left_min_sqr_d<sqr_d)
+      {
+        look_left();
+      }
+      if( !looked_right && right_min_sqr_d<sqr_d)
+      {
+        look_right();
+      }
+    }else
+    {
+      if( !looked_right && right_min_sqr_d<sqr_d)
+      {
+        look_right();
+      }
+      if(!looked_left && left_min_sqr_d<sqr_d)
+      {
+        look_left();
+      }
+    }
+  }
+  return sqr_d;
+}
+
+template <typename DerivedV, int DIM>
+template <
+  typename DerivedP, 
+  typename DerivedsqrD, 
+  typename DerivedI, 
+  typename DerivedC>
+IGL_INLINE void igl::AABB<DerivedV,DIM>::squared_distance(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::MatrixXi & Ele, 
+  const Eigen::PlainObjectBase<DerivedP> & P,
+  Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
+  Eigen::PlainObjectBase<DerivedI> & I,
+  Eigen::PlainObjectBase<DerivedC> & C) const
+{
+  assert(P.cols() == V.cols() && "cols in P should match dim of cols in V");
+  sqrD.resize(P.rows(),1);
+  I.resize(P.rows(),1);
+  C.resize(P.rows(),P.cols());
+  for(int p = 0;p<P.rows();p++)
+  {
+    RowVectorDIMS Pp = P.row(p), c;
+    int Ip;
+    sqrD(p) = squared_distance(V,Ele,Pp,Ip,c);
+    I(p) = Ip;
+    C.row(p).head(DIM) = c;
+  }
+}
+
+template <typename DerivedV, int DIM>
+template < 
+  typename Derivedother_V,
+  typename DerivedsqrD, 
+  typename DerivedI, 
+  typename DerivedC>
+IGL_INLINE void igl::AABB<DerivedV,DIM>::squared_distance(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::MatrixXi & Ele, 
+  const AABB<Derivedother_V,DIM> & other,
+  const Eigen::PlainObjectBase<Derivedother_V> & other_V,
+  const Eigen::MatrixXi & other_Ele, 
+  Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
+  Eigen::PlainObjectBase<DerivedI> & I,
+  Eigen::PlainObjectBase<DerivedC> & C) const
+{
+  assert(other_Ele.cols() == 1 && 
+    "Only implemented for other as list of points");
+  assert(other_V.cols() == V.cols() && "other must match this dimension");
+  sqrD.setConstant(other_Ele.rows(),1,std::numeric_limits<double>::infinity());
+  I.resize(other_Ele.rows(),1);
+  C.resize(other_Ele.rows(),other_V.cols());
+  // All points in other_V currently think they need to check against root of
+  // this. The point of using another AABB is to quickly prune chunks of
+  // other_V so that most points just check some subtree of this.
+
+  // This holds a conservative estimate of max(sqr_D) where sqr_D is the
+  // current best minimum squared distance for all points in this subtree
+  double min_sqr_d = std::numeric_limits<double>::infinity();
+  squared_distance_helper(
+    V,Ele,&other,other_V,other_Ele,min_sqr_d,sqrD,I,C);
+}
+
+template <typename DerivedV, int DIM>
+template < 
+  typename Derivedother_V,
+  typename DerivedsqrD, 
+  typename DerivedI, 
+  typename DerivedC>
+IGL_INLINE typename igl::AABB<DerivedV,DIM>::Scalar igl::AABB<DerivedV,DIM>::squared_distance_helper(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::MatrixXi & Ele, 
+  const AABB<Derivedother_V,DIM> * other,
+  const Eigen::PlainObjectBase<Derivedother_V> & other_V,
+  const Eigen::MatrixXi & other_Ele, 
+  const Scalar /*min_sqr_d*/,
+  Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
+  Eigen::PlainObjectBase<DerivedI> & I,
+  Eigen::PlainObjectBase<DerivedC> & C) const
+{
+  using namespace std;
+  using namespace Eigen;
+
+  // This implementation is a bit disappointing. There's no major speed up. Any
+  // performance gains seem to come from accidental cache coherency and
+  // diminish for larger "other" (the opposite of what was intended).
+
+  // Base case
+  if(other->is_leaf() && this->is_leaf())
+  {
+    Scalar sqr_d = sqrD(other->m_primitive);
+    int i = I(other->m_primitive);
+    RowVectorDIMS c = C.row(      other->m_primitive);
+    RowVectorDIMS p = other_V.row(other->m_primitive);
+    leaf_squared_distance(V,Ele,p,sqr_d,i,c);
+    sqrD( other->m_primitive) = sqr_d;
+    I(    other->m_primitive) = i;
+    C.row(other->m_primitive) = c;
+    //cout<<"leaf: "<<sqr_d<<endl;
+    //other->m_max_sqr_d = sqr_d;
+    return sqr_d;
+  }
+
+  if(other->is_leaf())
+  {
+    Scalar sqr_d = sqrD(other->m_primitive);
+    int i = I(other->m_primitive);
+    RowVectorDIMS c = C.row(      other->m_primitive);
+    RowVectorDIMS p = other_V.row(other->m_primitive);
+    sqr_d = squared_distance(V,Ele,p,sqr_d,i,c);
+    sqrD( other->m_primitive) = sqr_d;
+    I(    other->m_primitive) = i;
+    C.row(other->m_primitive) = c;
+    //other->m_max_sqr_d = sqr_d;
+    return sqr_d;
+  }
+
+  //// Exact minimum squared distance between arbitary primitives inside this and
+  //// othre's bounding boxes
+  //const auto & min_squared_distance = [&](
+  //  const AABB<DerivedV,DIM> * A,
+  //  const AABB<Derivedother_V,DIM> * B)->Scalar
+  //{
+  //  return A->m_box.squaredExteriorDistance(B->m_box);
+  //};
+
+  if(this->is_leaf())
+  {
+    //if(min_squared_distance(this,other) < other->m_max_sqr_d)
+    if(true)
+    {
+      this->squared_distance_helper(
+        V,Ele,other->m_left,other_V,other_Ele,0,sqrD,I,C);
+      this->squared_distance_helper(
+        V,Ele,other->m_right,other_V,other_Ele,0,sqrD,I,C);
+    }else
+    {
+      // This is never reached...
+    }
+    //// we know other is not a leaf
+    //other->m_max_sqr_d = std::max(other->m_left->m_max_sqr_d,other->m_right->m_max_sqr_d);
+    return 0;
+  }
+
+  // FORCE DOWN TO OTHER LEAF EVAL
+  //if(min_squared_distance(this,other) < other->m_max_sqr_d)
+  if(true)
+  {
+    if(true)
+    {
+      this->squared_distance_helper(
+        V,Ele,other->m_left,other_V,other_Ele,0,sqrD,I,C);
+      this->squared_distance_helper(
+        V,Ele,other->m_right,other_V,other_Ele,0,sqrD,I,C);
+    }else // this direction never seems to be faster
+    {
+      this->m_left->squared_distance_helper(
+        V,Ele,other,other_V,other_Ele,0,sqrD,I,C);
+      this->m_right->squared_distance_helper(
+        V,Ele,other,other_V,other_Ele,0,sqrD,I,C);
+    }
+  }else
+  {
+    // this is never reached ... :-(
+  }
+  //// we know other is not a leaf
+  //other->m_max_sqr_d = std::max(other->m_left->m_max_sqr_d,other->m_right->m_max_sqr_d);
+
+  return 0;
+#if 0 // False
+
+  // _Very_ conservative approximation of maximum squared distance between
+  // primitives inside this and other's bounding boxes
+  const auto & max_squared_distance = [](
+    const AABB<DerivedV,DIM> * A,
+    const AABB<Derivedother_V,DIM> * B)->Scalar
+  {
+    AlignedBox<Scalar,DIM> combo = A->m_box;
+    combo.extend(B->m_box);
+    return combo.diagonal().squaredNorm();
+  };
+
+  //// other base-case
+  //if(other->is_leaf())
+  //{
+  //  double sqr_d = sqrD(other->m_primitive);
+  //  int i = I(other->m_primitive);
+  //  RowVectorDIMS c = C.row(m_primitive);
+  //  RowVectorDIMS p = other_V.row(m_primitive);
+  //  leaf_squared_distance(V,Ele,p,sqr_d,i,c);
+  //  sqrD(other->m_primitive) = sqr_d;
+  //  I(other->m_primitive) = i;
+  //  C.row(m_primitive) = c;
+  //  return;
+  //}
+  std::vector<const AABB<DerivedV,DIM> * > this_list;
+  if(this->is_leaf())
+  {
+    this_list.push_back(this);
+  }else
+  {
+    assert(this->m_left);
+    this_list.push_back(this->m_left);
+    assert(this->m_right);
+    this_list.push_back(this->m_right);
+  }
+  std::vector<AABB<Derivedother_V,DIM> *> other_list;
+  if(other->is_leaf())
+  {
+    other_list.push_back(other);
+  }else
+  {
+    assert(other->m_left);
+    other_list.push_back(other->m_left);
+    assert(other->m_right);
+    other_list.push_back(other->m_right);
+  }
+
+  //const std::function<Scalar(
+  //  const AABB<Derivedother_V,DIM> * other)
+  //    > max_sqr_d = [&sqrD,&max_sqr_d](const AABB<Derivedother_V,DIM> * other)->Scalar
+  //  {
+  //    if(other->is_leaf())
+  //    {
+  //      return sqrD(other->m_primitive);
+  //    }else
+  //    {
+  //      return std::max(max_sqr_d(other->m_left),max_sqr_d(other->m_right));
+  //    }
+  //  };
+
+  //// Potentially recurse on all pairs, if minimum distance is less than running
+  //// bound
+  //Eigen::Matrix<Scalar,Eigen::Dynamic,1> other_max_sqr_d =
+  //  Eigen::Matrix<Scalar,Eigen::Dynamic,1>::Constant(other_list.size(),1,min_sqr_d);
+  for(size_t child = 0;child<other_list.size();child++)
+  {
+    auto other_tree = other_list[child];
+
+    Eigen::Matrix<Scalar,Eigen::Dynamic,1> this_max_sqr_d(this_list.size(),1);
+    for(size_t t = 0;t<this_list.size();t++)
+    {
+      const auto this_tree = this_list[t];
+      this_max_sqr_d(t) = max_squared_distance(this_tree,other_tree);
+    }
+    if(this_list.size() ==2 &&
+      ( this_max_sqr_d(0) > this_max_sqr_d(1))
+      )
+    {
+      std::swap(this_list[0],this_list[1]);
+      //std::swap(this_max_sqr_d(0),this_max_sqr_d(1));
+    }
+    const Scalar sqr_d = this_max_sqr_d.minCoeff();
+
+
+    for(size_t t = 0;t<this_list.size();t++)
+    {
+      const auto this_tree = this_list[t];
+
+      //const auto mm = max_sqr_d(other_tree);
+      //const Scalar mc = other_max_sqr_d(child);
+      //assert(mc == mm);
+      // Only look left/right in this_list if can possible decrease somebody's
+      // distance in this_tree.
+      const Scalar min_this_other = min_squared_distance(this_tree,other_tree); 
+      if(
+          min_this_other < sqr_d && 
+          min_this_other < other_tree->m_max_sqr_d)
+      {
+        //cout<<"before: "<<other_max_sqr_d(child)<<endl;
+        //other_max_sqr_d(child) = std::min(
+        //  other_max_sqr_d(child),
+        //  this_tree->squared_distance_helper(
+        //    V,Ele,other_tree,other_V,other_Ele,other_max_sqr_d(child),sqrD,I,C));
+        //cout<<"after: "<<other_max_sqr_d(child)<<endl;
+          this_tree->squared_distance_helper(
+            V,Ele,other_tree,other_V,other_Ele,0,sqrD,I,C);
+      }
+    }
+  }
+  //const Scalar ret = other_max_sqr_d.maxCoeff();
+  //const auto mm = max_sqr_d(other);
+  //assert(mm == ret);
+  //cout<<"non-leaf: "<<ret<<endl;
+  //return ret;
+  if(!other->is_leaf())
+  {
+    other->m_max_sqr_d = std::max(other->m_left->m_max_sqr_d,other->m_right->m_max_sqr_d);
+  }
+  return 0;
+#endif
+}
+
+template <typename DerivedV, int DIM>
+IGL_INLINE void igl::AABB<DerivedV,DIM>::leaf_squared_distance(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::MatrixXi & Ele, 
+  const RowVectorDIMS & p,
+  Scalar & sqr_d,
+  int & i,
+  RowVectorDIMS & c) const
+{
+  using namespace Eigen;
+  using namespace std;
+  RowVectorDIMS c_candidate;
+  Scalar sqr_d_candidate;
+  igl::point_simplex_squared_distance<DIM>(
+    p,V,Ele,m_primitive,sqr_d_candidate,c_candidate);
+  set_min(p,sqr_d_candidate,m_primitive,c_candidate,sqr_d,i,c);
+}
+
+
+template <typename DerivedV, int DIM>
+IGL_INLINE void igl::AABB<DerivedV,DIM>::set_min(
+  const RowVectorDIMS & 
+#ifndef NDEBUG
+  p
+#endif
+  ,
+  const Scalar sqr_d_candidate,
+  const int i_candidate,
+  const RowVectorDIMS & c_candidate,
+  Scalar & sqr_d,
+  int & i,
+  RowVectorDIMS & c) const
+{
+#ifndef NDEBUG
+  //std::cout<<matlab_format(c_candidate,"c_candidate")<<std::endl;
+  const Scalar pc_norm = (p-c_candidate).squaredNorm();
+  const Scalar diff = fabs(sqr_d_candidate - pc_norm);
+  assert(diff<=1e-10 && "distance should match norm of difference");
+#endif
+  if(sqr_d_candidate < sqr_d)
+  {
+    i = i_candidate;
+    c = c_candidate;
+    sqr_d = sqr_d_candidate;
+  }
+}
+
+
+template <typename DerivedV, int DIM>
+IGL_INLINE bool 
+igl::AABB<DerivedV,DIM>::intersect_ray(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::MatrixXi & Ele, 
+  const RowVectorDIMS & origin,
+  const RowVectorDIMS & dir,
+  std::vector<igl::Hit> & hits) const
+{
+  hits.clear();
+  const Scalar t0 = 0;
+  const Scalar t1 = std::numeric_limits<Scalar>::infinity();
+  {
+    Scalar _1,_2;
+    if(!ray_box_intersect(origin,dir,m_box,t0,t1,_1,_2))
+    {
+      return false;
+    }
+  }
+  if(this->is_leaf())
+  {
+    // Actually process elements
+    assert((Ele.size() == 0 || Ele.cols() == 3) && "Elements should be triangles");
+    // Cheesecake way of hitting element
+    return ray_mesh_intersect(origin,dir,V,Ele.row(m_primitive),hits);
+  }
+  std::vector<igl::Hit> left_hits;
+  std::vector<igl::Hit> right_hits;
+  const bool left_ret = m_left->intersect_ray(V,Ele,origin,dir,left_hits);
+  const bool right_ret = m_right->intersect_ray(V,Ele,origin,dir,right_hits);
+  hits.insert(hits.end(),left_hits.begin(),left_hits.end());
+  hits.insert(hits.end(),right_hits.begin(),right_hits.end());
+  return left_ret || right_ret;
+}
+
+template <typename DerivedV, int DIM>
+IGL_INLINE bool 
+igl::AABB<DerivedV,DIM>::intersect_ray(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::MatrixXi & Ele, 
+  const RowVectorDIMS & origin,
+  const RowVectorDIMS & dir,
+  igl::Hit & hit) const
+{
+#if false
+  // BFS
+  std::queue<const AABB *> Q;
+  // Or DFS
+  //std::stack<const AABB *> Q;
+  Q.push(this);
+  bool any_hit = false;
+  hit.t = std::numeric_limits<Scalar>::infinity();
+  while(!Q.empty())
+  {
+    const AABB * tree = Q.front();
+    //const AABB * tree = Q.top();
+    Q.pop();
+    {
+      Scalar _1,_2;
+      if(!ray_box_intersect(
+        origin,dir,tree->m_box,Scalar(0),Scalar(hit.t),_1,_2))
+      {
+        continue;
+      }
+    }
+    if(tree->is_leaf())
+    {
+      // Actually process elements
+      assert((Ele.size() == 0 || Ele.cols() == 3) && "Elements should be triangles");
+      igl::Hit leaf_hit;
+      if(
+        ray_mesh_intersect(origin,dir,V,Ele.row(tree->m_primitive),leaf_hit)&&
+        leaf_hit.t < hit.t)
+      {
+        hit = leaf_hit;
+      }
+      continue;
+    }
+    // Add children to queue
+    Q.push(tree->m_left);
+    Q.push(tree->m_right);
+  }
+  return any_hit;
+#else
+  // DFS
+  return intersect_ray(
+    V,Ele,origin,dir,std::numeric_limits<Scalar>::infinity(),hit);
+#endif
+}
+
+template <typename DerivedV, int DIM>
+IGL_INLINE bool 
+igl::AABB<DerivedV,DIM>::intersect_ray(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::MatrixXi & Ele, 
+  const RowVectorDIMS & origin,
+  const RowVectorDIMS & dir,
+  const Scalar _min_t,
+  igl::Hit & hit) const
+{
+  //// Naive, slow
+  //std::vector<igl::Hit> hits;
+  //intersect_ray(V,Ele,origin,dir,hits);
+  //if(hits.size() > 0)
+  //{
+  //  hit = hits.front();
+  //  return true;
+  //}else
+  //{
+  //  return false;
+  //}
+  Scalar min_t = _min_t;
+  const Scalar t0 = 0;
+  {
+    Scalar _1,_2;
+    if(!ray_box_intersect(origin,dir,m_box,t0,min_t,_1,_2))
+    {
+      return false;
+    }
+  }
+  if(this->is_leaf())
+  {
+    // Actually process elements
+    assert((Ele.size() == 0 || Ele.cols() == 3) && "Elements should be triangles");
+    // Cheesecake way of hitting element
+    return ray_mesh_intersect(origin,dir,V,Ele.row(m_primitive),hit);
+  }
+
+  // Doesn't seem like smartly choosing left before/after right makes a
+  // differnce
+  igl::Hit left_hit;
+  igl::Hit right_hit;
+  bool left_ret = m_left->intersect_ray(V,Ele,origin,dir,min_t,left_hit);
+  if(left_ret && left_hit.t<min_t)
+  {
+    // It's scary that this line doesn't seem to matter....
+    min_t = left_hit.t;
+    hit = left_hit;
+    left_ret = true;
+  }else
+  {
+    left_ret = false;
+  }
+  bool right_ret = m_right->intersect_ray(V,Ele,origin,dir,min_t,right_hit);
+  if(right_ret && right_hit.t<min_t)
+  {
+    min_t = right_hit.t;
+    hit = right_hit;
+    right_ret = true;
+  }else
+  {
+    right_ret = false;
+  }
+  return left_ret || right_ret;
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template specialization
+// generated by autoexplicit.sh
+template void igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 3>::init(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&);
+template void igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 2>::init(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&);
+template void igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 3>::squared_distance<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::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&) const;
+template void igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 2>::squared_distance<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::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&) const;
+template double igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 3>::squared_distance(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, 1, 3, 1, 1, 3> const&, int&, Eigen::Matrix<double, 1, 3, 1, 1, 3>&) const;
+template double igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 2>::squared_distance(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, 1, 2, 1, 1, 2> const&, int&, Eigen::Matrix<double, 1, 2, 1, 1, 2>&) const;
+template void igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 2>::squared_distance<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::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&) const;
+template void igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 3>::squared_distance<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::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&) const;
+#endif

+ 21 - 946
include/igl/AABB.h

@@ -9,6 +9,7 @@
 #define IGL_AABB_H
 #define IGL_AABB_H
 
 
 #include "Hit.h"
 #include "Hit.h"
+#include "igl_inline.h"
 #include <Eigen/Core>
 #include <Eigen/Core>
 #include <Eigen/Geometry>
 #include <Eigen/Geometry>
 #include <vector>
 #include <vector>
@@ -81,7 +82,7 @@ public:
       }
       }
       // Seems like there should have been an elegant solution to this using
       // Seems like there should have been an elegant solution to this using
       // the copy-swap idiom above:
       // the copy-swap idiom above:
-      inline void deinit()
+      IGL_INLINE void deinit()
       {
       {
         m_primitive = -1;
         m_primitive = -1;
         m_box = Eigen::AlignedBox<Scalar,DIM>();
         m_box = Eigen::AlignedBox<Scalar,DIM>();
@@ -105,7 +106,7 @@ public:
       //   elements  max_tree list of element or (not leaf id) indices into Ele
       //   elements  max_tree list of element or (not leaf id) indices into Ele
       //   i  recursive call index {0}
       //   i  recursive call index {0}
       template <typename Derivedbb_mins, typename Derivedbb_maxs>
       template <typename Derivedbb_mins, typename Derivedbb_maxs>
-        inline void init(
+        IGL_INLINE void init(
             const Eigen::PlainObjectBase<DerivedV> & V,
             const Eigen::PlainObjectBase<DerivedV> & V,
             const Eigen::MatrixXi & Ele, 
             const Eigen::MatrixXi & Ele, 
             const Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
             const Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
@@ -113,7 +114,7 @@ public:
             const Eigen::VectorXi & elements,
             const Eigen::VectorXi & elements,
             const int i = 0);
             const int i = 0);
       // Wrapper for root with empty serialization
       // Wrapper for root with empty serialization
-      inline void init(
+      IGL_INLINE void init(
           const Eigen::PlainObjectBase<DerivedV> & V,
           const Eigen::PlainObjectBase<DerivedV> & V,
           const Eigen::MatrixXi & Ele);
           const Eigen::MatrixXi & Ele);
       // Build an Axis-Aligned Bounding Box tree for a given mesh.
       // Build an Axis-Aligned Bounding Box tree for a given mesh.
@@ -128,13 +129,13 @@ public:
       //   I  #I list of indices into Ele of elements to include (for recursive
       //   I  #I list of indices into Ele of elements to include (for recursive
       //     calls)
       //     calls)
       // 
       // 
-      inline void init(
+      IGL_INLINE void init(
           const Eigen::PlainObjectBase<DerivedV> & V,
           const Eigen::PlainObjectBase<DerivedV> & V,
           const Eigen::MatrixXi & Ele, 
           const Eigen::MatrixXi & Ele, 
           const Eigen::MatrixXi & SI,
           const Eigen::MatrixXi & SI,
           const Eigen::VectorXi & I);
           const Eigen::VectorXi & I);
       // Return whether at leaf node
       // Return whether at leaf node
-      inline bool is_leaf() const;
+      IGL_INLINE bool is_leaf() const;
       // Find the indices of elements containing given point: this makes sense
       // Find the indices of elements containing given point: this makes sense
       // when Ele is a co-dimension 0 simplex (tets in 3D, triangles in 2D).
       // when Ele is a co-dimension 0 simplex (tets in 3D, triangles in 2D).
       //
       //
@@ -148,7 +149,7 @@ public:
       // Returns:
       // Returns:
       //   list of indices of elements containing q
       //   list of indices of elements containing q
       template <typename Derivedq>
       template <typename Derivedq>
-      inline std::vector<int> find(
+      IGL_INLINE std::vector<int> find(
           const Eigen::PlainObjectBase<DerivedV> & V,
           const Eigen::PlainObjectBase<DerivedV> & V,
           const Eigen::MatrixXi & Ele, 
           const Eigen::MatrixXi & Ele, 
           const Eigen::PlainObjectBase<Derivedq> & q,
           const Eigen::PlainObjectBase<Derivedq> & q,
@@ -156,7 +157,7 @@ public:
 
 
       // If number of elements m then total tree size should be 2*h where h is
       // If number of elements m then total tree size should be 2*h where h is
       // the deepest depth 2^ceil(log(#Ele*2-1))
       // the deepest depth 2^ceil(log(#Ele*2-1))
-      inline int subtree_size() const;
+      IGL_INLINE int subtree_size() const;
 
 
       // Serialize this class into 3 arrays (so we can pass it pack to matlab)
       // Serialize this class into 3 arrays (so we can pass it pack to matlab)
       //
       //
@@ -166,7 +167,7 @@ public:
       //   elements  max_tree list of element or (not leaf id) indices into Ele
       //   elements  max_tree list of element or (not leaf id) indices into Ele
       //   i  recursive call index into these arrays {0}
       //   i  recursive call index into these arrays {0}
       template <typename Derivedbb_mins, typename Derivedbb_maxs>
       template <typename Derivedbb_mins, typename Derivedbb_maxs>
-        inline void serialize(
+        IGL_INLINE void serialize(
             Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
             Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
             Eigen::PlainObjectBase<Derivedbb_maxs> & bb_maxs,
             Eigen::PlainObjectBase<Derivedbb_maxs> & bb_maxs,
             Eigen::VectorXi & elements,
             Eigen::VectorXi & elements,
@@ -186,14 +187,14 @@ public:
       //
       //
       // Known bugs: currently assumes Elements are triangles regardless of
       // Known bugs: currently assumes Elements are triangles regardless of
       // dimension.
       // dimension.
-      inline Scalar squared_distance(
+      IGL_INLINE Scalar squared_distance(
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::MatrixXi & Ele, 
         const Eigen::MatrixXi & Ele, 
         const RowVectorDIMS & p,
         const RowVectorDIMS & p,
         int & i,
         int & i,
         RowVectorDIMS & c) const;
         RowVectorDIMS & c) const;
 //private:
 //private:
-      inline Scalar squared_distance(
+      IGL_INLINE Scalar squared_distance(
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::MatrixXi & Ele, 
         const Eigen::MatrixXi & Ele, 
         const RowVectorDIMS & p,
         const RowVectorDIMS & p,
@@ -201,21 +202,21 @@ public:
         int & i,
         int & i,
         RowVectorDIMS & c) const;
         RowVectorDIMS & c) const;
       // All hits
       // All hits
-      inline bool intersect_ray(
+      IGL_INLINE bool intersect_ray(
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::MatrixXi & Ele, 
         const Eigen::MatrixXi & Ele, 
         const RowVectorDIMS & origin,
         const RowVectorDIMS & origin,
         const RowVectorDIMS & dir,
         const RowVectorDIMS & dir,
         std::vector<igl::Hit> & hits) const;
         std::vector<igl::Hit> & hits) const;
       // First hit
       // First hit
-      inline bool intersect_ray(
+      IGL_INLINE bool intersect_ray(
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::MatrixXi & Ele, 
         const Eigen::MatrixXi & Ele, 
         const RowVectorDIMS & origin,
         const RowVectorDIMS & origin,
         const RowVectorDIMS & dir,
         const RowVectorDIMS & dir,
         igl::Hit & hit) const;
         igl::Hit & hit) const;
 //private:
 //private:
-      inline bool intersect_ray(
+      IGL_INLINE bool intersect_ray(
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::MatrixXi & Ele, 
         const Eigen::MatrixXi & Ele, 
         const RowVectorDIMS & origin,
         const RowVectorDIMS & origin,
@@ -230,7 +231,7 @@ public:
         typename DerivedsqrD, 
         typename DerivedsqrD, 
         typename DerivedI, 
         typename DerivedI, 
         typename DerivedC>
         typename DerivedC>
-      inline void squared_distance(
+      IGL_INLINE void squared_distance(
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::MatrixXi & Ele, 
         const Eigen::MatrixXi & Ele, 
         const Eigen::PlainObjectBase<DerivedP> & P,
         const Eigen::PlainObjectBase<DerivedP> & P,
@@ -243,7 +244,7 @@ public:
         typename DerivedsqrD, 
         typename DerivedsqrD, 
         typename DerivedI, 
         typename DerivedI, 
         typename DerivedC>
         typename DerivedC>
-      inline void squared_distance(
+      IGL_INLINE void squared_distance(
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::MatrixXi & Ele, 
         const Eigen::MatrixXi & Ele, 
         const AABB<Derivedother_V,DIM> & other,
         const AABB<Derivedother_V,DIM> & other,
@@ -258,7 +259,7 @@ private:
         typename DerivedsqrD, 
         typename DerivedsqrD, 
         typename DerivedI, 
         typename DerivedI, 
         typename DerivedC>
         typename DerivedC>
-      inline Scalar squared_distance_helper(
+      IGL_INLINE Scalar squared_distance_helper(
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::MatrixXi & Ele, 
         const Eigen::MatrixXi & Ele, 
         const AABB<Derivedother_V,DIM> * other,
         const AABB<Derivedother_V,DIM> * other,
@@ -269,14 +270,14 @@ private:
         Eigen::PlainObjectBase<DerivedI> & I,
         Eigen::PlainObjectBase<DerivedI> & I,
         Eigen::PlainObjectBase<DerivedC> & C) const;
         Eigen::PlainObjectBase<DerivedC> & C) const;
       // Helper function for leaves: works in-place on sqr_d
       // Helper function for leaves: works in-place on sqr_d
-      inline void leaf_squared_distance(
+      IGL_INLINE void leaf_squared_distance(
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::MatrixXi & Ele, 
         const Eigen::MatrixXi & Ele, 
         const RowVectorDIMS & p,
         const RowVectorDIMS & p,
         Scalar & sqr_d,
         Scalar & sqr_d,
         int & i,
         int & i,
         RowVectorDIMS & c) const;
         RowVectorDIMS & c) const;
-      inline void set_min(
+      IGL_INLINE void set_min(
         const RowVectorDIMS & p,
         const RowVectorDIMS & p,
         const Scalar sqr_d_candidate,
         const Scalar sqr_d_candidate,
         const int i_candidate,
         const int i_candidate,
@@ -289,935 +290,9 @@ public:
     };
     };
 }
 }
 
 
-// Implementation
-#include "EPS.h"
-#include "barycenter.h"
-#include "barycentric_coordinates.h"
-#include "colon.h"
-#include "colon.h"
-#include "doublearea.h"
-#include "matlab_format.h"
-#include "point_simplex_squared_distance.h"
-#include "project_to_line_segment.h"
-#include "sort.h"
-#include "volume.h"
-#include "ray_box_intersect.h"
-#include "ray_mesh_intersect.h"
-#include <iostream>
-#include <iomanip>
-#include <limits>
-#include <list>
-#include <queue>
-#include <stack>
 
 
-template <typename DerivedV, int DIM>
-  template <typename Derivedbb_mins, typename Derivedbb_maxs>
-inline void igl::AABB<DerivedV,DIM>::init(
-    const Eigen::PlainObjectBase<DerivedV> & V,
-    const Eigen::MatrixXi & Ele, 
-    const Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
-    const Eigen::PlainObjectBase<Derivedbb_maxs> & bb_maxs,
-    const Eigen::VectorXi & elements,
-    const int i)
-{
-  using namespace std;
-  using namespace Eigen;
-  deinit();
-  if(bb_mins.size() > 0)
-  {
-    assert(bb_mins.rows() == bb_maxs.rows() && "Serial tree arrays must match");
-    assert(bb_mins.cols() == V.cols() && "Serial tree array dim must match V");
-    assert(bb_mins.cols() == bb_maxs.cols() && "Serial tree arrays must match");
-    assert(bb_mins.rows() == elements.rows() &&
-        "Serial tree arrays must match");
-    // construct from serialization
-    m_box.extend(bb_mins.row(i).transpose());
-    m_box.extend(bb_maxs.row(i).transpose());
-    m_primitive = elements(i);
-    // Not leaf then recurse
-    if(m_primitive == -1)
-    {
-      m_left = new AABB();
-      m_left->init( V,Ele,bb_mins,bb_maxs,elements,2*i+1);
-      m_right = new AABB();
-      m_right->init( V,Ele,bb_mins,bb_maxs,elements,2*i+2);
-      //m_depth = std::max( m_left->m_depth, m_right->m_depth)+1;
-    }
-  }else
-  {
-    VectorXi allI = colon<int>(0,Ele.rows()-1);
-    MatrixXDIMS BC;
-    if(Ele.cols() == 1)
-    {
-      // points
-      BC = V;
-    }else
-    {
-      // Simplices
-      barycenter(V,Ele,BC);
-    }
-    MatrixXi SI(BC.rows(),BC.cols());
-    {
-      MatrixXDIMS _;
-      MatrixXi IS;
-      igl::sort(BC,1,true,_,IS);
-      // Need SI(i) to tell which place i would be sorted into
-      const int dim = IS.cols();
-      for(int i = 0;i<IS.rows();i++)
-      {
-        for(int d = 0;d<dim;d++)
-        {
-          SI(IS(i,d),d) = i;
-        }
-      }
-    }
-    init(V,Ele,SI,allI);
-  }
-}
-
-  template <typename DerivedV, int DIM>
-inline void igl::AABB<DerivedV,DIM>::init(
-    const Eigen::PlainObjectBase<DerivedV> & V,
-    const Eigen::MatrixXi & Ele)
-{
-  using namespace Eigen;
-  // deinit will be immediately called...
-  return init(V,Ele,MatrixXDIMS(),MatrixXDIMS(),VectorXi(),0);
-}
-
-  template <typename DerivedV, int DIM>
-inline void igl::AABB<DerivedV,DIM>::init(
-    const Eigen::PlainObjectBase<DerivedV> & V,
-    const Eigen::MatrixXi & Ele, 
-    const Eigen::MatrixXi & SI,
-    const Eigen::VectorXi & I)
-{
-  using namespace Eigen;
-  using namespace std;
-  deinit();
-  if(V.size() == 0 || Ele.size() == 0 || I.size() == 0)
-  {
-    return;
-  }
-  assert(DIM == V.cols() && "V.cols() should matched declared dimension");
-  //const Scalar inf = numeric_limits<Scalar>::infinity();
-  m_box = AlignedBox<Scalar,DIM>();
-  // Compute bounding box
-  for(int i = 0;i<I.rows();i++)
-  {
-    for(int c = 0;c<Ele.cols();c++)
-    {
-      m_box.extend(V.row(Ele(I(i),c)).transpose());
-      m_box.extend(V.row(Ele(I(i),c)).transpose());
-    }
-  }
-  switch(I.size())
-  {
-    case 0:
-      {
-        assert(false);
-      }
-    case 1:
-      {
-        m_primitive = I(0);
-        break;
-      }
-    default:
-      {
-        // Compute longest direction
-        int max_d = -1;
-        m_box.diagonal().maxCoeff(&max_d);
-        // Can't use median on BC directly because many may have same value,
-        // but can use median on sorted BC indices
-        VectorXi SIdI(I.rows());
-        for(int i = 0;i<I.rows();i++)
-        {
-          SIdI(i) = SI(I(i),max_d);
-        }
-        // Since later I use <= I think I don't need to worry about odd/even
-        // Pass by copy to avoid changing input
-        const auto median = [](VectorXi A)->Scalar
-        {
-          size_t n = A.size()/2;
-          nth_element(A.data(),A.data()+n,A.data()+A.size());
-          if(A.rows() % 2 == 1)
-          {
-            return A(n);
-          }else
-          {
-            nth_element(A.data(),A.data()+n-1,A.data()+A.size());
-            return 0.5*(A(n)+A(n-1));
-          }
-        };
-        const Scalar med = median(SIdI);
-        VectorXi LI((I.rows()+1)/2),RI(I.rows()/2);
-        assert(LI.rows()+RI.rows() == I.rows());
-        // Distribute left and right
-        {
-          int li = 0;
-          int ri = 0;
-          for(int i = 0;i<I.rows();i++)
-          {
-            if(SIdI(i)<=med)
-            {
-              LI(li++) = I(i);
-            }else
-            {
-              RI(ri++) = I(i);
-            }
-          }
-        }
-        //m_depth = 0;
-        if(LI.rows()>0)
-        {
-          m_left = new AABB();
-          m_left->init(V,Ele,SI,LI);
-          //m_depth = std::max(m_depth, m_left->m_depth+1);
-        }
-        if(RI.rows()>0)
-        {
-          m_right = new AABB();
-          m_right->init(V,Ele,SI,RI);
-          //m_depth = std::max(m_depth, m_right->m_depth+1);
-        }
-      }
-  }
-}
-
-template <typename DerivedV, int DIM>
-inline bool igl::AABB<DerivedV,DIM>::is_leaf() const
-{
-  return m_primitive != -1;
-}
-
-template <typename DerivedV, int DIM>
-template <typename Derivedq>
-inline std::vector<int> igl::AABB<DerivedV,DIM>::find(
-    const Eigen::PlainObjectBase<DerivedV> & V,
-    const Eigen::MatrixXi & Ele, 
-    const Eigen::PlainObjectBase<Derivedq> & q,
-    const bool first) const
-{
-  using namespace std;
-  using namespace Eigen;
-  assert(q.size() == DIM && 
-      "Query dimension should match aabb dimension");
-  assert(Ele.cols() == V.cols()+1 && 
-      "AABB::find only makes sense for (d+1)-simplices");
-  const Scalar epsilon = igl::EPS<Scalar>();
-  // Check if outside bounding box
-  bool inside = m_box.contains(q.transpose());
-  if(!inside)
-  {
-    return std::vector<int>();
-  }
-  assert(m_primitive==-1 || (m_left == NULL && m_right == NULL));
-  if(is_leaf())
-  {
-    // Initialize to some value > -epsilon
-    Scalar a1=0,a2=0,a3=0,a4=0;
-    switch(DIM)
-    {
-      case 3:
-        {
-          // Barycentric coordinates
-          typedef Eigen::Matrix<Scalar,1,3> RowVector3S;
-          const RowVector3S V1 = V.row(Ele(m_primitive,0));
-          const RowVector3S V2 = V.row(Ele(m_primitive,1));
-          const RowVector3S V3 = V.row(Ele(m_primitive,2));
-          const RowVector3S V4 = V.row(Ele(m_primitive,3));
-          a1 = volume_single(V2,V4,V3,(RowVector3S)q);
-          a2 = volume_single(V1,V3,V4,(RowVector3S)q);
-          a3 = volume_single(V1,V4,V2,(RowVector3S)q);
-          a4 = volume_single(V1,V2,V3,(RowVector3S)q);
-          break;
-        }
-      case 2:
-        {
-          // Barycentric coordinates
-          typedef Eigen::Matrix<Scalar,2,1> Vector2S;
-          const Vector2S V1 = V.row(Ele(m_primitive,0));
-          const Vector2S V2 = V.row(Ele(m_primitive,1));
-          const Vector2S V3 = V.row(Ele(m_primitive,2));
-          // Hack for now to keep templates simple. If becomes bottleneck
-          // consider using std::enable_if_t 
-          const Vector2S q2 = q.head(2);
-          a1 = doublearea_single(V1,V2,q2);
-          a2 = doublearea_single(V2,V3,q2);
-          a3 = doublearea_single(V3,V1,q2);
-          break;
-        }
-      default:assert(false);
-    }
-    // Normalization is important for correcting sign
-    Scalar sum = a1+a2+a3+a4;
-    a1 /= sum;
-    a2 /= sum;
-    a3 /= sum;
-    a4 /= sum;
-    if(
-        a1>=-epsilon && 
-        a2>=-epsilon && 
-        a3>=-epsilon && 
-        a4>=-epsilon)
-    {
-      return std::vector<int>(1,m_primitive);
-    }else
-    {
-      return std::vector<int>();
-    }
-  }
-  std::vector<int> left = m_left->find(V,Ele,q,first);
-  if(first && !left.empty())
-  {
-    return left;
-  }
-  std::vector<int> right = m_right->find(V,Ele,q,first);
-  if(first)
-  {
-    return right;
-  }
-  left.insert(left.end(),right.begin(),right.end());
-  return left;
-}
-
-template <typename DerivedV, int DIM>
-inline int igl::AABB<DerivedV,DIM>::subtree_size() const
-{
-  // 1 for self
-  int n = 1;
-  int n_left = 0,n_right = 0;
-  if(m_left != NULL)
-  {
-    n_left = m_left->subtree_size();
-  }
-  if(m_right != NULL)
-  {
-    n_right = m_right->subtree_size();
-  }
-  n += 2*std::max(n_left,n_right);
-  return n;
-}
-
-
-template <typename DerivedV, int DIM>
-template <typename Derivedbb_mins, typename Derivedbb_maxs>
-inline void igl::AABB<DerivedV,DIM>::serialize(
-    Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
-    Eigen::PlainObjectBase<Derivedbb_maxs> & bb_maxs,
-    Eigen::VectorXi & elements,
-    const int i) const
-{
-  using namespace std;
-  using namespace Eigen;
-  // Calling for root then resize output
-  if(i==0)
-  {
-    const int m = subtree_size();
-    //cout<<"m: "<<m<<endl;
-    bb_mins.resize(m,DIM);
-    bb_maxs.resize(m,DIM);
-    elements.resize(m,1);
-  }
-  //cout<<i<<" ";
-  bb_mins.row(i) = m_box.min();
-  bb_maxs.row(i) = m_box.max();
-  elements(i) = m_primitive;
-  if(m_left != NULL)
-  {
-    m_left->serialize(bb_mins,bb_maxs,elements,2*i+1);
-  }
-  if(m_right != NULL)
-  {
-    m_right->serialize(bb_mins,bb_maxs,elements,2*i+2);
-  }
-}
-
-template <typename DerivedV, int DIM>
-inline typename igl::AABB<DerivedV,DIM>::Scalar 
-igl::AABB<DerivedV,DIM>::squared_distance(
-  const Eigen::PlainObjectBase<DerivedV> & V,
-  const Eigen::MatrixXi & Ele, 
-  const RowVectorDIMS & p,
-  int & i,
-  RowVectorDIMS & c) const
-{
-  return squared_distance(V,Ele,p,std::numeric_limits<Scalar>::infinity(),i,c);
-}
-
-
-template <typename DerivedV, int DIM>
-inline typename igl::AABB<DerivedV,DIM>::Scalar 
-igl::AABB<DerivedV,DIM>::squared_distance(
-  const Eigen::PlainObjectBase<DerivedV> & V,
-  const Eigen::MatrixXi & Ele, 
-  const RowVectorDIMS & p,
-  Scalar min_sqr_d,
-  int & i,
-  RowVectorDIMS & c) const
-{
-  using namespace Eigen;
-  using namespace std;
-  Scalar sqr_d = min_sqr_d;
-  //assert(DIM == 3 && "Code has only been tested for DIM == 3");
-  assert((Ele.cols() == 3 || Ele.cols() == 2 || Ele.cols() == 1)
-    && "Code has only been tested for simplex sizes 3,2,1");
-
-  assert(m_primitive==-1 || (m_left == NULL && m_right == NULL));
-  if(is_leaf())
-  {
-    leaf_squared_distance(V,Ele,p,sqr_d,i,c);
-  }else
-  {
-    bool looked_left = false;
-    bool looked_right = false;
-    const auto & look_left = [&]()
-    {
-      int i_left;
-      RowVectorDIMS c_left = c;
-      Scalar sqr_d_left = m_left->squared_distance(V,Ele,p,sqr_d,i_left,c_left);
-      set_min(p,sqr_d_left,i_left,c_left,sqr_d,i,c);
-      looked_left = true;
-    };
-    const auto & look_right = [&]()
-    {
-      int i_right;
-      RowVectorDIMS c_right = c;
-      Scalar sqr_d_right = m_right->squared_distance(V,Ele,p,sqr_d,i_right,c_right);
-      set_min(p,sqr_d_right,i_right,c_right,sqr_d,i,c);
-      looked_right = true;
-    };
-
-    // must look left or right if in box
-    if(m_left->m_box.contains(p.transpose()))
-    {
-      look_left();
-    }
-    if(m_right->m_box.contains(p.transpose()))
-    {
-      look_right();
-    }
-    // if haven't looked left and could be less than current min, then look
-    Scalar  left_min_sqr_d = m_left->m_box.squaredExteriorDistance(p.transpose());
-    Scalar right_min_sqr_d = m_right->m_box.squaredExteriorDistance(p.transpose());
-    if(left_min_sqr_d < right_min_sqr_d)
-    {
-      if(!looked_left && left_min_sqr_d<sqr_d)
-      {
-        look_left();
-      }
-      if( !looked_right && right_min_sqr_d<sqr_d)
-      {
-        look_right();
-      }
-    }else
-    {
-      if( !looked_right && right_min_sqr_d<sqr_d)
-      {
-        look_right();
-      }
-      if(!looked_left && left_min_sqr_d<sqr_d)
-      {
-        look_left();
-      }
-    }
-  }
-  return sqr_d;
-}
-
-template <typename DerivedV, int DIM>
-template <
-  typename DerivedP, 
-  typename DerivedsqrD, 
-  typename DerivedI, 
-  typename DerivedC>
-inline void igl::AABB<DerivedV,DIM>::squared_distance(
-  const Eigen::PlainObjectBase<DerivedV> & V,
-  const Eigen::MatrixXi & Ele, 
-  const Eigen::PlainObjectBase<DerivedP> & P,
-  Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
-  Eigen::PlainObjectBase<DerivedI> & I,
-  Eigen::PlainObjectBase<DerivedC> & C) const
-{
-  assert(P.cols() == V.cols() && "cols in P should match dim of cols in V");
-  sqrD.resize(P.rows(),1);
-  I.resize(P.rows(),1);
-  C.resize(P.rows(),P.cols());
-  for(int p = 0;p<P.rows();p++)
-  {
-    RowVectorDIMS Pp = P.row(p), c;
-    int Ip;
-    sqrD(p) = squared_distance(V,Ele,Pp,Ip,c);
-    I(p) = Ip;
-    C.row(p).head(DIM) = c;
-  }
-}
-
-template <typename DerivedV, int DIM>
-template < 
-  typename Derivedother_V,
-  typename DerivedsqrD, 
-  typename DerivedI, 
-  typename DerivedC>
-inline void igl::AABB<DerivedV,DIM>::squared_distance(
-  const Eigen::PlainObjectBase<DerivedV> & V,
-  const Eigen::MatrixXi & Ele, 
-  const AABB<Derivedother_V,DIM> & other,
-  const Eigen::PlainObjectBase<Derivedother_V> & other_V,
-  const Eigen::MatrixXi & other_Ele, 
-  Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
-  Eigen::PlainObjectBase<DerivedI> & I,
-  Eigen::PlainObjectBase<DerivedC> & C) const
-{
-  assert(other_Ele.cols() == 1 && 
-    "Only implemented for other as list of points");
-  assert(other_V.cols() == V.cols() && "other must match this dimension");
-  sqrD.setConstant(other_Ele.rows(),1,std::numeric_limits<double>::infinity());
-  I.resize(other_Ele.rows(),1);
-  C.resize(other_Ele.rows(),other_V.cols());
-  // All points in other_V currently think they need to check against root of
-  // this. The point of using another AABB is to quickly prune chunks of
-  // other_V so that most points just check some subtree of this.
-
-  // This holds a conservative estimate of max(sqr_D) where sqr_D is the
-  // current best minimum squared distance for all points in this subtree
-  double min_sqr_d = std::numeric_limits<double>::infinity();
-  squared_distance_helper(
-    V,Ele,&other,other_V,other_Ele,min_sqr_d,sqrD,I,C);
-}
-
-template <typename DerivedV, int DIM>
-template < 
-  typename Derivedother_V,
-  typename DerivedsqrD, 
-  typename DerivedI, 
-  typename DerivedC>
-inline typename igl::AABB<DerivedV,DIM>::Scalar igl::AABB<DerivedV,DIM>::squared_distance_helper(
-  const Eigen::PlainObjectBase<DerivedV> & V,
-  const Eigen::MatrixXi & Ele, 
-  const AABB<Derivedother_V,DIM> * other,
-  const Eigen::PlainObjectBase<Derivedother_V> & other_V,
-  const Eigen::MatrixXi & other_Ele, 
-  const Scalar /*min_sqr_d*/,
-  Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
-  Eigen::PlainObjectBase<DerivedI> & I,
-  Eigen::PlainObjectBase<DerivedC> & C) const
-{
-  using namespace std;
-  using namespace Eigen;
-
-  // This implementation is a bit disappointing. There's no major speed up. Any
-  // performance gains seem to come from accidental cache coherency and
-  // diminish for larger "other" (the opposite of what was intended).
-
-  // Base case
-  if(other->is_leaf() && this->is_leaf())
-  {
-    Scalar sqr_d = sqrD(other->m_primitive);
-    int i = I(other->m_primitive);
-    RowVectorDIMS c = C.row(      other->m_primitive);
-    RowVectorDIMS p = other_V.row(other->m_primitive);
-    leaf_squared_distance(V,Ele,p,sqr_d,i,c);
-    sqrD( other->m_primitive) = sqr_d;
-    I(    other->m_primitive) = i;
-    C.row(other->m_primitive) = c;
-    //cout<<"leaf: "<<sqr_d<<endl;
-    //other->m_max_sqr_d = sqr_d;
-    return sqr_d;
-  }
-
-  if(other->is_leaf())
-  {
-    Scalar sqr_d = sqrD(other->m_primitive);
-    int i = I(other->m_primitive);
-    RowVectorDIMS c = C.row(      other->m_primitive);
-    RowVectorDIMS p = other_V.row(other->m_primitive);
-    sqr_d = squared_distance(V,Ele,p,sqr_d,i,c);
-    sqrD( other->m_primitive) = sqr_d;
-    I(    other->m_primitive) = i;
-    C.row(other->m_primitive) = c;
-    //other->m_max_sqr_d = sqr_d;
-    return sqr_d;
-  }
-
-  //// Exact minimum squared distance between arbitary primitives inside this and
-  //// othre's bounding boxes
-  //const auto & min_squared_distance = [&](
-  //  const AABB<DerivedV,DIM> * A,
-  //  const AABB<Derivedother_V,DIM> * B)->Scalar
-  //{
-  //  return A->m_box.squaredExteriorDistance(B->m_box);
-  //};
-
-  if(this->is_leaf())
-  {
-    //if(min_squared_distance(this,other) < other->m_max_sqr_d)
-    if(true)
-    {
-      this->squared_distance_helper(
-        V,Ele,other->m_left,other_V,other_Ele,0,sqrD,I,C);
-      this->squared_distance_helper(
-        V,Ele,other->m_right,other_V,other_Ele,0,sqrD,I,C);
-    }else
-    {
-      // This is never reached...
-    }
-    //// we know other is not a leaf
-    //other->m_max_sqr_d = std::max(other->m_left->m_max_sqr_d,other->m_right->m_max_sqr_d);
-    return 0;
-  }
-
-  // FORCE DOWN TO OTHER LEAF EVAL
-  //if(min_squared_distance(this,other) < other->m_max_sqr_d)
-  if(true)
-  {
-    if(true)
-    {
-      this->squared_distance_helper(
-        V,Ele,other->m_left,other_V,other_Ele,0,sqrD,I,C);
-      this->squared_distance_helper(
-        V,Ele,other->m_right,other_V,other_Ele,0,sqrD,I,C);
-    }else // this direction never seems to be faster
-    {
-      this->m_left->squared_distance_helper(
-        V,Ele,other,other_V,other_Ele,0,sqrD,I,C);
-      this->m_right->squared_distance_helper(
-        V,Ele,other,other_V,other_Ele,0,sqrD,I,C);
-    }
-  }else
-  {
-    // this is never reached ... :-(
-  }
-  //// we know other is not a leaf
-  //other->m_max_sqr_d = std::max(other->m_left->m_max_sqr_d,other->m_right->m_max_sqr_d);
-
-  return 0;
-#if 0 // False
-
-  // _Very_ conservative approximation of maximum squared distance between
-  // primitives inside this and other's bounding boxes
-  const auto & max_squared_distance = [](
-    const AABB<DerivedV,DIM> * A,
-    const AABB<Derivedother_V,DIM> * B)->Scalar
-  {
-    AlignedBox<Scalar,DIM> combo = A->m_box;
-    combo.extend(B->m_box);
-    return combo.diagonal().squaredNorm();
-  };
-
-  //// other base-case
-  //if(other->is_leaf())
-  //{
-  //  double sqr_d = sqrD(other->m_primitive);
-  //  int i = I(other->m_primitive);
-  //  RowVectorDIMS c = C.row(m_primitive);
-  //  RowVectorDIMS p = other_V.row(m_primitive);
-  //  leaf_squared_distance(V,Ele,p,sqr_d,i,c);
-  //  sqrD(other->m_primitive) = sqr_d;
-  //  I(other->m_primitive) = i;
-  //  C.row(m_primitive) = c;
-  //  return;
-  //}
-  std::vector<const AABB<DerivedV,DIM> * > this_list;
-  if(this->is_leaf())
-  {
-    this_list.push_back(this);
-  }else
-  {
-    assert(this->m_left);
-    this_list.push_back(this->m_left);
-    assert(this->m_right);
-    this_list.push_back(this->m_right);
-  }
-  std::vector<AABB<Derivedother_V,DIM> *> other_list;
-  if(other->is_leaf())
-  {
-    other_list.push_back(other);
-  }else
-  {
-    assert(other->m_left);
-    other_list.push_back(other->m_left);
-    assert(other->m_right);
-    other_list.push_back(other->m_right);
-  }
-
-  //const std::function<Scalar(
-  //  const AABB<Derivedother_V,DIM> * other)
-  //    > max_sqr_d = [&sqrD,&max_sqr_d](const AABB<Derivedother_V,DIM> * other)->Scalar
-  //  {
-  //    if(other->is_leaf())
-  //    {
-  //      return sqrD(other->m_primitive);
-  //    }else
-  //    {
-  //      return std::max(max_sqr_d(other->m_left),max_sqr_d(other->m_right));
-  //    }
-  //  };
-
-  //// Potentially recurse on all pairs, if minimum distance is less than running
-  //// bound
-  //Eigen::Matrix<Scalar,Eigen::Dynamic,1> other_max_sqr_d =
-  //  Eigen::Matrix<Scalar,Eigen::Dynamic,1>::Constant(other_list.size(),1,min_sqr_d);
-  for(size_t child = 0;child<other_list.size();child++)
-  {
-    auto other_tree = other_list[child];
-
-    Eigen::Matrix<Scalar,Eigen::Dynamic,1> this_max_sqr_d(this_list.size(),1);
-    for(size_t t = 0;t<this_list.size();t++)
-    {
-      const auto this_tree = this_list[t];
-      this_max_sqr_d(t) = max_squared_distance(this_tree,other_tree);
-    }
-    if(this_list.size() ==2 &&
-      ( this_max_sqr_d(0) > this_max_sqr_d(1))
-      )
-    {
-      std::swap(this_list[0],this_list[1]);
-      //std::swap(this_max_sqr_d(0),this_max_sqr_d(1));
-    }
-    const Scalar sqr_d = this_max_sqr_d.minCoeff();
-
-
-    for(size_t t = 0;t<this_list.size();t++)
-    {
-      const auto this_tree = this_list[t];
-
-      //const auto mm = max_sqr_d(other_tree);
-      //const Scalar mc = other_max_sqr_d(child);
-      //assert(mc == mm);
-      // Only look left/right in this_list if can possible decrease somebody's
-      // distance in this_tree.
-      const Scalar min_this_other = min_squared_distance(this_tree,other_tree); 
-      if(
-          min_this_other < sqr_d && 
-          min_this_other < other_tree->m_max_sqr_d)
-      {
-        //cout<<"before: "<<other_max_sqr_d(child)<<endl;
-        //other_max_sqr_d(child) = std::min(
-        //  other_max_sqr_d(child),
-        //  this_tree->squared_distance_helper(
-        //    V,Ele,other_tree,other_V,other_Ele,other_max_sqr_d(child),sqrD,I,C));
-        //cout<<"after: "<<other_max_sqr_d(child)<<endl;
-          this_tree->squared_distance_helper(
-            V,Ele,other_tree,other_V,other_Ele,0,sqrD,I,C);
-      }
-    }
-  }
-  //const Scalar ret = other_max_sqr_d.maxCoeff();
-  //const auto mm = max_sqr_d(other);
-  //assert(mm == ret);
-  //cout<<"non-leaf: "<<ret<<endl;
-  //return ret;
-  if(!other->is_leaf())
-  {
-    other->m_max_sqr_d = std::max(other->m_left->m_max_sqr_d,other->m_right->m_max_sqr_d);
-  }
-  return 0;
-#endif
-}
-
-template <typename DerivedV, int DIM>
-inline void igl::AABB<DerivedV,DIM>::leaf_squared_distance(
-  const Eigen::PlainObjectBase<DerivedV> & V,
-  const Eigen::MatrixXi & Ele, 
-  const RowVectorDIMS & p,
-  Scalar & sqr_d,
-  int & i,
-  RowVectorDIMS & c) const
-{
-  using namespace Eigen;
-  using namespace std;
-  RowVectorDIMS c_candidate;
-  Scalar sqr_d_candidate;
-  igl::point_simplex_squared_distance<DIM>(
-    p,V,Ele,m_primitive,sqr_d_candidate,c_candidate);
-  set_min(p,sqr_d_candidate,m_primitive,c_candidate,sqr_d,i,c);
-}
-
-
-template <typename DerivedV, int DIM>
-inline void igl::AABB<DerivedV,DIM>::set_min(
-  const RowVectorDIMS & 
-#ifndef NDEBUG
-  p
-#endif
-  ,
-  const Scalar sqr_d_candidate,
-  const int i_candidate,
-  const RowVectorDIMS & c_candidate,
-  Scalar & sqr_d,
-  int & i,
-  RowVectorDIMS & c) const
-{
-#ifndef NDEBUG
-  //std::cout<<matlab_format(c_candidate,"c_candidate")<<std::endl;
-  const Scalar pc_norm = (p-c_candidate).squaredNorm();
-  const Scalar diff = fabs(sqr_d_candidate - pc_norm);
-  assert(diff<=1e-10 && "distance should match norm of difference");
+#ifndef IGL_STATIC_LIBRARY
+#  include "AABB.cpp"
 #endif
 #endif
-  if(sqr_d_candidate < sqr_d)
-  {
-    i = i_candidate;
-    c = c_candidate;
-    sqr_d = sqr_d_candidate;
-  }
-}
-
-
-template <typename DerivedV, int DIM>
-inline bool 
-igl::AABB<DerivedV,DIM>::intersect_ray(
-  const Eigen::PlainObjectBase<DerivedV> & V,
-  const Eigen::MatrixXi & Ele, 
-  const RowVectorDIMS & origin,
-  const RowVectorDIMS & dir,
-  std::vector<igl::Hit> & hits) const
-{
-  hits.clear();
-  const Scalar t0 = 0;
-  const Scalar t1 = std::numeric_limits<Scalar>::infinity();
-  {
-    Scalar _1,_2;
-    if(!ray_box_intersect(origin,dir,m_box,t0,t1,_1,_2))
-    {
-      return false;
-    }
-  }
-  if(this->is_leaf())
-  {
-    // Actually process elements
-    assert((Ele.size() == 0 || Ele.cols() == 3) && "Elements should be triangles");
-    // Cheesecake way of hitting element
-    return ray_mesh_intersect(origin,dir,V,Ele.row(m_primitive),hits);
-  }
-  std::vector<igl::Hit> left_hits;
-  std::vector<igl::Hit> right_hits;
-  const bool left_ret = m_left->intersect_ray(V,Ele,origin,dir,left_hits);
-  const bool right_ret = m_right->intersect_ray(V,Ele,origin,dir,right_hits);
-  hits.insert(hits.end(),left_hits.begin(),left_hits.end());
-  hits.insert(hits.end(),right_hits.begin(),right_hits.end());
-  return left_ret || right_ret;
-}
-
-template <typename DerivedV, int DIM>
-inline bool 
-igl::AABB<DerivedV,DIM>::intersect_ray(
-  const Eigen::PlainObjectBase<DerivedV> & V,
-  const Eigen::MatrixXi & Ele, 
-  const RowVectorDIMS & origin,
-  const RowVectorDIMS & dir,
-  igl::Hit & hit) const
-{
-#if false
-  // BFS
-  std::queue<const AABB *> Q;
-  // Or DFS
-  //std::stack<const AABB *> Q;
-  Q.push(this);
-  bool any_hit = false;
-  hit.t = std::numeric_limits<Scalar>::infinity();
-  while(!Q.empty())
-  {
-    const AABB * tree = Q.front();
-    //const AABB * tree = Q.top();
-    Q.pop();
-    {
-      Scalar _1,_2;
-      if(!ray_box_intersect(
-        origin,dir,tree->m_box,Scalar(0),Scalar(hit.t),_1,_2))
-      {
-        continue;
-      }
-    }
-    if(tree->is_leaf())
-    {
-      // Actually process elements
-      assert((Ele.size() == 0 || Ele.cols() == 3) && "Elements should be triangles");
-      igl::Hit leaf_hit;
-      if(
-        ray_mesh_intersect(origin,dir,V,Ele.row(tree->m_primitive),leaf_hit)&&
-        leaf_hit.t < hit.t)
-      {
-        hit = leaf_hit;
-      }
-      continue;
-    }
-    // Add children to queue
-    Q.push(tree->m_left);
-    Q.push(tree->m_right);
-  }
-  return any_hit;
-#else
-  // DFS
-  return intersect_ray(
-    V,Ele,origin,dir,std::numeric_limits<Scalar>::infinity(),hit);
-#endif
-}
-
-template <typename DerivedV, int DIM>
-inline bool 
-igl::AABB<DerivedV,DIM>::intersect_ray(
-  const Eigen::PlainObjectBase<DerivedV> & V,
-  const Eigen::MatrixXi & Ele, 
-  const RowVectorDIMS & origin,
-  const RowVectorDIMS & dir,
-  const Scalar _min_t,
-  igl::Hit & hit) const
-{
-  //// Naive, slow
-  //std::vector<igl::Hit> hits;
-  //intersect_ray(V,Ele,origin,dir,hits);
-  //if(hits.size() > 0)
-  //{
-  //  hit = hits.front();
-  //  return true;
-  //}else
-  //{
-  //  return false;
-  //}
-  Scalar min_t = _min_t;
-  const Scalar t0 = 0;
-  {
-    Scalar _1,_2;
-    if(!ray_box_intersect(origin,dir,m_box,t0,min_t,_1,_2))
-    {
-      return false;
-    }
-  }
-  if(this->is_leaf())
-  {
-    // Actually process elements
-    assert((Ele.size() == 0 || Ele.cols() == 3) && "Elements should be triangles");
-    // Cheesecake way of hitting element
-    return ray_mesh_intersect(origin,dir,V,Ele.row(m_primitive),hit);
-  }
-
-  // Doesn't seem like smartly choosing left before/after right makes a
-  // differnce
-  igl::Hit left_hit;
-  igl::Hit right_hit;
-  bool left_ret = m_left->intersect_ray(V,Ele,origin,dir,min_t,left_hit);
-  if(left_ret && left_hit.t<min_t)
-  {
-    // It's scary that this line doesn't seem to matter....
-    min_t = left_hit.t;
-    hit = left_hit;
-    left_ret = true;
-  }else
-  {
-    left_ret = false;
-  }
-  bool right_ret = m_right->intersect_ray(V,Ele,origin,dir,min_t,right_hit);
-  if(right_ret && right_hit.t<min_t)
-  {
-    min_t = right_hit.t;
-    hit = right_hit;
-    right_ret = true;
-  }else
-  {
-    right_ret = false;
-  }
-  return left_ret || right_ret;
-}
 
 
 #endif
 #endif

+ 20 - 32
include/igl/ambient_occlusion.cpp

@@ -10,7 +10,7 @@
 #include "ray_mesh_intersect.h"
 #include "ray_mesh_intersect.h"
 #include "EPS.h"
 #include "EPS.h"
 #include "Hit.h"
 #include "Hit.h"
-#include <thread>
+#include "parallel_for.h"
 #include <functional>
 #include <functional>
 #include <vector>
 #include <vector>
 #include <algorithm>
 #include <algorithm>
@@ -38,40 +38,27 @@ IGL_INLINE void igl::ambient_occlusion(
   // Embree seems to be parallel when constructing but not when tracing rays
   // Embree seems to be parallel when constructing but not when tracing rays
   const MatrixXf D = random_dir_stratified(num_samples).cast<float>();
   const MatrixXf D = random_dir_stratified(num_samples).cast<float>();
 
 
-  const size_t nthreads = n<1000?1:std::thread::hardware_concurrency();
+  const auto & inner = [&P,&N,&num_samples,&D,&S,&shoot_ray](const int p)
   {
   {
-    std::vector<std::thread> threads(nthreads);
-    for(int t = 0;t<nthreads;t++)
+    const Vector3f origin = P.row(p).template cast<float>();
+    const Vector3f normal = N.row(p).template cast<float>();
+    int num_hits = 0;
+    for(int s = 0;s<num_samples;s++)
     {
     {
-      threads[t] = std::thread(std::bind(
-        [&P,&N,&shoot_ray,&S,&num_samples,&D](const int bi, const int ei, const int t)
-        {
-          // loop over mesh vertices in this chunk
-          for(int p = bi;p<ei;p++)
-          {
-            const Vector3f origin = P.row(p).template cast<float>();
-            const Vector3f normal = N.row(p).template cast<float>();
-            int num_hits = 0;
-            for(int s = 0;s<num_samples;s++)
-            {
-              Vector3f d = D.row(s);
-              if(d.dot(normal) < 0)
-              {
-                // reverse ray
-                d *= -1;
-              }
-              if(shoot_ray(origin,d))
-              {
-                num_hits++;
-              }
-            }
-            S(p) = (double)num_hits/(double)num_samples;
-          }
-        },t*n/nthreads,(t+1)==nthreads?n:(t+1)*n/nthreads,t));
+      Vector3f d = D.row(s);
+      if(d.dot(normal) < 0)
+      {
+        // reverse ray
+        d *= -1;
+      }
+      if(shoot_ray(origin,d))
+      {
+        num_hits++;
+      }
     }
     }
-    std::for_each(threads.begin(),threads.end(),[](std::thread& x){x.join();});
-  }
-
+    S(p) = (double)num_hits/(double)num_samples;
+  };
+  parallel_for(n,inner,1000);
 }
 }
 
 
 template <
 template <
@@ -147,4 +134,5 @@ template void igl::ambient_occlusion<Eigen::Matrix<double, -1, -1, 0, -1, -1>, E
 template void igl::ambient_occlusion<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(std::function<bool (Eigen::Matrix<float, 3, 1, 0, 3, 1> const&, Eigen::Matrix<float, 3, 1, 0, 3, 1> const&)> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 template void igl::ambient_occlusion<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(std::function<bool (Eigen::Matrix<float, 3, 1, 0, 3, 1> const&, Eigen::Matrix<float, 3, 1, 0, 3, 1> const&)> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 // generated by autoexplicit.sh
 // generated by autoexplicit.sh
 template void igl::ambient_occlusion<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(std::function<bool (Eigen::Matrix<float, 3, 1, 0, 3, 1> const&, Eigen::Matrix<float, 3, 1, 0, 3, 1> const&)> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 template void igl::ambient_occlusion<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(std::function<bool (Eigen::Matrix<float, 3, 1, 0, 3, 1> const&, Eigen::Matrix<float, 3, 1, 0, 3, 1> const&)> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
+template void igl::ambient_occlusion<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(std::function<bool (Eigen::Matrix<float, 3, 1, 0, 3, 1> const&, Eigen::Matrix<float, 3, 1, 0, 3, 1> const&)> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 #endif
 #endif

+ 107 - 0
include/igl/cat.cpp

@@ -6,12 +6,14 @@
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can 
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can 
 // obtain one at http://mozilla.org/MPL/2.0/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "cat.h"
 #include "cat.h"
+
 #include <cstdio>
 #include <cstdio>
 
 
 // Bug in unsupported/Eigen/SparseExtra needs iostream first
 // Bug in unsupported/Eigen/SparseExtra needs iostream first
 #include <iostream>
 #include <iostream>
 #include <unsupported/Eigen/SparseExtra>
 #include <unsupported/Eigen/SparseExtra>
 
 
+
 // Sparse matrices need to be handled carefully. Because C++ does not 
 // Sparse matrices need to be handled carefully. Because C++ does not 
 // Template:
 // Template:
 //   Scalar  sparse matrix scalar type, e.g. double
 //   Scalar  sparse matrix scalar type, e.g. double
@@ -22,6 +24,7 @@ IGL_INLINE void igl::cat(
     const Eigen::SparseMatrix<Scalar> & B, 
     const Eigen::SparseMatrix<Scalar> & B, 
     Eigen::SparseMatrix<Scalar> & C)
     Eigen::SparseMatrix<Scalar> & C)
 {
 {
+
   assert(dim == 1 || dim == 2);
   assert(dim == 1 || dim == 2);
   using namespace Eigen;
   using namespace Eigen;
   // Special case if B or A is empty
   // Special case if B or A is empty
@@ -36,6 +39,7 @@ IGL_INLINE void igl::cat(
     return;
     return;
   }
   }
 
 
+#if false
   // This **must** be DynamicSparseMatrix, otherwise this implementation is
   // This **must** be DynamicSparseMatrix, otherwise this implementation is
   // insanely slow
   // insanely slow
   DynamicSparseMatrix<Scalar, RowMajor> dyn_C;
   DynamicSparseMatrix<Scalar, RowMajor> dyn_C;
@@ -77,6 +81,109 @@ IGL_INLINE void igl::cat(
   }
   }
 
 
   C = SparseMatrix<Scalar>(dyn_C);
   C = SparseMatrix<Scalar>(dyn_C);
+#elif false
+  std::vector<Triplet<Scalar> > CIJV;
+  CIJV.reserve(A.nonZeros() + B.nonZeros());
+  {
+    // Iterate over outside of A
+    for(int k=0; k<A.outerSize(); ++k)
+    {
+      // Iterate over inside
+      for(typename SparseMatrix<Scalar>::InnerIterator it (A,k); it; ++it)
+      {
+        CIJV.emplace_back(it.row(),it.col(),it.value());
+      }
+    }
+    // Iterate over outside of B
+    for(int k=0; k<B.outerSize(); ++k)
+    {
+      // Iterate over inside
+      for(typename SparseMatrix<Scalar>::InnerIterator it (B,k); it; ++it)
+      {
+        int r = (dim == 1 ? A.rows()+it.row() : it.row());
+        int c = (dim == 2 ? A.cols()+it.col() : it.col());
+        CIJV.emplace_back(r,c,it.value());
+      }
+    }
+
+  }
+
+  C = SparseMatrix<Scalar>( 
+      dim == 1 ? A.rows()+B.rows() : A.rows(),
+      dim == 1 ? A.cols()          : A.cols()+B.cols());
+  C.reserve(A.nonZeros() + B.nonZeros());
+  C.setFromTriplets(CIJV.begin(),CIJV.end());
+#else
+  C = SparseMatrix<Scalar>( 
+      dim == 1 ? A.rows()+B.rows() : A.rows(),
+      dim == 1 ? A.cols()          : A.cols()+B.cols());
+  Eigen::VectorXi per_col = Eigen::VectorXi::Zero(C.cols());
+  if(dim == 1)
+  {
+    assert(A.outerSize() == B.outerSize());
+    for(int k = 0;k<A.outerSize();++k)
+    {
+      for(typename SparseMatrix<Scalar>::InnerIterator it (A,k); it; ++it)
+      {
+        per_col(k)++;
+      }
+      for(typename SparseMatrix<Scalar>::InnerIterator it (B,k); it; ++it)
+      {
+        per_col(k)++;
+      }
+    }
+  }else
+  {
+    for(int k = 0;k<A.outerSize();++k)
+    {
+      for(typename SparseMatrix<Scalar>::InnerIterator it (A,k); it; ++it)
+      {
+        per_col(k)++;
+      }
+    }
+    for(int k = 0;k<B.outerSize();++k)
+    {
+      for(typename SparseMatrix<Scalar>::InnerIterator it (B,k); it; ++it)
+      {
+        per_col(A.cols() + k)++;
+      }
+    }
+  }
+  C.reserve(per_col);
+  if(dim == 1)
+  {
+    for(int k = 0;k<A.outerSize();++k)
+    {
+      for(typename SparseMatrix<Scalar>::InnerIterator it (A,k); it; ++it)
+      {
+        C.insert(it.row(),k) = it.value();
+      }
+      for(typename SparseMatrix<Scalar>::InnerIterator it (B,k); it; ++it)
+      {
+        C.insert(A.rows()+it.row(),k) = it.value();
+      }
+    }
+  }else
+  {
+    for(int k = 0;k<A.outerSize();++k)
+    {
+      for(typename SparseMatrix<Scalar>::InnerIterator it (A,k); it; ++it)
+      {
+        C.insert(it.row(),k) = it.value();
+      }
+    }
+    for(int k = 0;k<B.outerSize();++k)
+    {
+      for(typename SparseMatrix<Scalar>::InnerIterator it (B,k); it; ++it)
+      {
+        C.insert(it.row(),A.cols()+k) = it.value();
+      }
+    }
+  }
+  C.makeCompressed();
+
+#endif
+
 }
 }
 
 
 template <typename Derived, class MatC>
 template <typename Derived, class MatC>

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

@@ -109,7 +109,7 @@ namespace igl
           // Make a short name for the edge map
           // Make a short name for the edge map
           typedef std::map<EMK,EMV> EdgeMap;
           typedef std::map<EMK,EMV> EdgeMap;
           // Maps edges of offending faces to all incident offending faces
           // Maps edges of offending faces to all incident offending faces
-          EdgeMap edge2faces;
+          //EdgeMap edge2faces;
           std::vector<std::pair<const Box, const Box> > candidate_box_pairs;
           std::vector<std::pair<const Box, const Box> > candidate_box_pairs;
 
 
         public:
         public:
@@ -330,7 +330,7 @@ inline igl::copyleft::cgal::SelfIntersectMesh<
   T(),
   T(),
   lIF(),
   lIF(),
   offending(),
   offending(),
-  edge2faces(),
+  //edge2faces(),
   params(params)
   params(params)
 {
 {
   using namespace std;
   using namespace std;
@@ -427,7 +427,7 @@ inline igl::copyleft::cgal::SelfIntersectMesh<
   }
   }
 
 
   remesh_intersections(
   remesh_intersections(
-    V,F,T,offending,edge2faces,params.stitch_all,VV,FF,J,IM);
+    V,F,T,offending,params.stitch_all,VV,FF,J,IM);
 
 
 #ifdef IGL_SELFINTERSECTMESH_DEBUG
 #ifdef IGL_SELFINTERSECTMESH_DEBUG
   log_time("remesh_intersection");
   log_time("remesh_intersection");
@@ -477,7 +477,7 @@ inline void igl::copyleft::cgal::SelfIntersectMesh<
       // append face to edge's list
       // append face to edge's list
       Index i = F(f,(e+1)%3) < F(f,(e+2)%3) ? F(f,(e+1)%3) : F(f,(e+2)%3);
       Index i = F(f,(e+1)%3) < F(f,(e+2)%3) ? F(f,(e+1)%3) : F(f,(e+2)%3);
       Index j = F(f,(e+1)%3) < F(f,(e+2)%3) ? F(f,(e+2)%3) : F(f,(e+1)%3);
       Index j = F(f,(e+1)%3) < F(f,(e+2)%3) ? F(f,(e+2)%3) : F(f,(e+1)%3);
-      edge2faces[EMK(i,j)].push_back(f);
+      //edge2faces[EMK(i,j)].push_back(f);
     }
     }
   }
   }
 }
 }

+ 10 - 1
include/igl/copyleft/cgal/half_space_box.cpp

@@ -14,7 +14,10 @@ IGL_INLINE void igl::copyleft::cgal::half_space_box(
   typedef CGAL::Point_3<CGAL::Epeck> Point;
   typedef CGAL::Point_3<CGAL::Epeck> Point;
   typedef CGAL::Vector_3<CGAL::Epeck> Vector;
   typedef CGAL::Vector_3<CGAL::Epeck> Vector;
   typedef CGAL::Epeck::FT EScalar;
   typedef CGAL::Epeck::FT EScalar;
-  Eigen::RowVector3d avg = V.colwise().mean();
+  Eigen::Matrix<typename DerivedV::Scalar,1,3> avg(0,0,0);
+  for(int v = 0;v<V.rows();v++) for(int c = 0;c<V.cols();c++) avg(c) += V(v,c);
+  avg /= V.rows();
+
   Point o3(avg(0),avg(1),avg(2));
   Point o3(avg(0),avg(1),avg(2));
   Point o2 = P.projection(o3);
   Point o2 = P.projection(o3);
   Vector u;
   Vector u;
@@ -109,5 +112,11 @@ IGL_INLINE void igl::copyleft::cgal::half_space_box(
 }
 }
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // Explicit template specialization
+// generated by autoexplicit.sh
+template void igl::copyleft::cgal::half_space_box<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 4, 1, 1, 4>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 4, 1, 1, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 8, 3, 0, 8, 3>&, Eigen::Matrix<int, 12, 3, 0, 12, 3>&);
+// generated by autoexplicit.sh
+template void igl::copyleft::cgal::half_space_box<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 4, 1, 1, 4>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 4, 0, -1, 4> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 4, 1, 1, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 4, 0, -1, 4> > const&, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 8, 3, 0, 8, 3>&, Eigen::Matrix<int, 12, 3, 0, 12, 3>&);
+// generated by autoexplicit.sh
+template void igl::copyleft::cgal::half_space_box<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 4, 1, 1, 4>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 4, 1, 1, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 8, 3, 0, 8, 3>&, Eigen::Matrix<int, 12, 3, 0, 12, 3>&);
 template void igl::copyleft::cgal::half_space_box<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::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> > const&, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 8, 3, 0, 8, 3>&, Eigen::Matrix<int, 12, 3, 0, 12, 3>&);
 template void igl::copyleft::cgal::half_space_box<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::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> > const&, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 8, 3, 0, 8, 3>&, Eigen::Matrix<int, 12, 3, 0, 12, 3>&);
 #endif
 #endif

+ 70 - 54
include/igl/copyleft/cgal/intersect_other.cpp

@@ -9,6 +9,8 @@
 #include "CGAL_includes.hpp"
 #include "CGAL_includes.hpp"
 #include "mesh_to_cgal_triangle_list.h"
 #include "mesh_to_cgal_triangle_list.h"
 #include "remesh_intersections.h"
 #include "remesh_intersections.h"
+#include "../../slice_mask.h"
+#include "../../remove_unreferenced.h"
 
 
 #ifndef IGL_FIRST_HIT_EXCEPTION
 #ifndef IGL_FIRST_HIT_EXCEPTION
 #define IGL_FIRST_HIT_EXCEPTION 10
 #define IGL_FIRST_HIT_EXCEPTION 10
@@ -30,10 +32,10 @@ namespace igl
         std::map<
         std::map<
           typename DerivedF::Index,
           typename DerivedF::Index,
           std::vector<std::pair<typename DerivedF::Index, CGAL::Object> > > &
           std::vector<std::pair<typename DerivedF::Index, CGAL::Object> > > &
-          offending,
-        std::map<
-          std::pair<typename DerivedF::Index,typename DerivedF::Index>,
-          std::vector<typename DerivedF::Index> > & edge2faces)
+          offending)
+        //std::map<
+        //  std::pair<typename DerivedF::Index,typename DerivedF::Index>,
+        //  std::vector<typename DerivedF::Index> > & edge2faces)
       {
       {
         typedef typename DerivedF::Index Index;
         typedef typename DerivedF::Index Index;
         typedef std::pair<Index,Index> EMK;
         typedef std::pair<Index,Index> EMK;
@@ -46,7 +48,7 @@ namespace igl
             // append face to edge's list
             // append face to edge's list
             Index i = F(f,(e+1)%3) < F(f,(e+2)%3) ? F(f,(e+1)%3) : F(f,(e+2)%3);
             Index i = F(f,(e+1)%3) < F(f,(e+2)%3) ? F(f,(e+1)%3) : F(f,(e+2)%3);
             Index j = F(f,(e+1)%3) < F(f,(e+2)%3) ? F(f,(e+2)%3) : F(f,(e+1)%3);
             Index j = F(f,(e+1)%3) < F(f,(e+2)%3) ? F(f,(e+2)%3) : F(f,(e+1)%3);
-            edge2faces[EMK(i,j)].push_back(f);
+            //edge2faces[EMK(i,j)].push_back(f);
           }
           }
         }
         }
         offending[f].push_back({f_other,result});
         offending[f].push_back({f_other,result});
@@ -58,14 +60,10 @@ namespace igl
         typename DerivedVB,
         typename DerivedVB,
         typename DerivedFB,
         typename DerivedFB,
         typename DerivedIF,
         typename DerivedIF,
-        typename DerivedVVA,
-        typename DerivedFFA,
-        typename DerivedJA,
-        typename DerivedIMA,
-        typename DerivedVVB,
-        typename DerivedFFB,
-        typename DerivedJB,
-        typename DerivedIMB>
+        typename DerivedVVAB,
+        typename DerivedFFAB,
+        typename DerivedJAB,
+        typename DerivedIMAB>
       static IGL_INLINE bool intersect_other_helper(
       static IGL_INLINE bool intersect_other_helper(
         const Eigen::PlainObjectBase<DerivedVA> & VA,
         const Eigen::PlainObjectBase<DerivedVA> & VA,
         const Eigen::PlainObjectBase<DerivedFA> & FA,
         const Eigen::PlainObjectBase<DerivedFA> & FA,
@@ -73,14 +71,10 @@ namespace igl
         const Eigen::PlainObjectBase<DerivedFB> & FB,
         const Eigen::PlainObjectBase<DerivedFB> & FB,
         const RemeshSelfIntersectionsParam & params,
         const RemeshSelfIntersectionsParam & params,
         Eigen::PlainObjectBase<DerivedIF> & IF,
         Eigen::PlainObjectBase<DerivedIF> & IF,
-        Eigen::PlainObjectBase<DerivedVVA> & VVA,
-        Eigen::PlainObjectBase<DerivedFFA> & FFA,
-        Eigen::PlainObjectBase<DerivedJA>  & JA,
-        Eigen::PlainObjectBase<DerivedIMA> & IMA,
-        Eigen::PlainObjectBase<DerivedVVB> & VVB,
-        Eigen::PlainObjectBase<DerivedFFB> & FFB,
-        Eigen::PlainObjectBase<DerivedJB>  & JB,
-        Eigen::PlainObjectBase<DerivedIMB> & IMB)
+        Eigen::PlainObjectBase<DerivedVVAB> & VVAB,
+        Eigen::PlainObjectBase<DerivedFFAB> & FFAB,
+        Eigen::PlainObjectBase<DerivedJAB>  & JAB,
+        Eigen::PlainObjectBase<DerivedIMAB> & IMAB)
       {
       {
 
 
         using namespace std;
         using namespace std;
@@ -139,7 +133,7 @@ namespace igl
         box_up(TA,A_boxes);
         box_up(TA,A_boxes);
         box_up(TB,B_boxes);
         box_up(TB,B_boxes);
         OffendingMap offendingA,offendingB;
         OffendingMap offendingA,offendingB;
-        EdgeMap edge2facesA,edge2facesB;
+        //EdgeMap edge2facesA,edge2facesB;
 
 
         std::list<int> lIF;
         std::list<int> lIF;
         const auto cb = [&](const Box &a, const Box &b) -> void
         const auto cb = [&](const Box &a, const Box &b) -> void
@@ -163,8 +157,8 @@ namespace igl
             {
             {
               CGAL::Object result = CGAL::intersection(A,B);
               CGAL::Object result = CGAL::intersection(A,B);
 
 
-              push_result(FA,fa,fb,result,offendingA,edge2facesA);
-              push_result(FB,fb,fa,result,offendingB,edge2facesB);
+              push_result(FA,fa,fb,result,offendingA);
+              push_result(FB,fb,fa,result,offendingB);
             }
             }
           }
           }
         };
         };
@@ -202,8 +196,38 @@ namespace igl
         }
         }
         if(!params.detect_only)
         if(!params.detect_only)
         {
         {
-          remesh_intersections(VA,FA,TA,offendingA,edge2facesA,VVA,FFA,JA,IMA);
-          remesh_intersections(VB,FB,TB,offendingB,edge2facesB,VVB,FFB,JB,IMB);
+          // Obsolete, now remesh_intersections expects a single mesh
+          // remesh_intersections(VA,FA,TA,offendingA,VVA,FFA,JA,IMA);
+          // remesh_intersections(VB,FB,TB,offendingB,VVB,FFB,JB,IMB);
+          // Combine mesh and offending maps
+          DerivedVA VAB(VA.rows()+VB.rows(),3);
+          VAB<<VA,VB;
+          DerivedFA FAB(FA.rows()+FB.rows(),3);
+          FAB<<FA,(FB.array()+VA.rows());
+          Triangles TAB;
+          TAB.reserve(TA.size()+TB.size());
+          TAB.insert(TAB.end(),TA.begin(),TA.end());
+          TAB.insert(TAB.end(),TB.begin(),TB.end());
+          OffendingMap offending;
+          //offending.reserve(offendingA.size() + offendingB.size());
+          for (const auto itr : offendingA)
+          {
+            // Remap offenders in FB to FAB
+            auto offenders = itr.second;
+            for(auto & offender : offenders)
+            {
+              offender.first += FA.rows();
+            }
+            offending[itr.first] = offenders;
+          }
+          for (const auto itr : offendingB)
+          {
+            // Store offenders for FB according to place in FAB
+            offending[FA.rows() + itr.first] = itr.second;
+          }
+
+          remesh_intersections(
+            VAB,FAB,TAB,offending,params.stitch_all,VVAB,FFAB,JAB,IMAB);
         }
         }
 
 
         return IF.rows() > 0;
         return IF.rows() > 0;
@@ -218,38 +242,30 @@ template <
   typename DerivedVB,
   typename DerivedVB,
   typename DerivedFB,
   typename DerivedFB,
   typename DerivedIF,
   typename DerivedIF,
-  typename DerivedVVA,
-  typename DerivedFFA,
-  typename DerivedJA,
-  typename DerivedIMA,
-  typename DerivedVVB,
-  typename DerivedFFB,
-  typename DerivedJB,
-  typename DerivedIMB>
+  typename DerivedVVAB,
+  typename DerivedFFAB,
+  typename DerivedJAB,
+  typename DerivedIMAB>
 IGL_INLINE bool igl::copyleft::cgal::intersect_other(
 IGL_INLINE bool igl::copyleft::cgal::intersect_other(
-  const Eigen::PlainObjectBase<DerivedVA> & VA,
-  const Eigen::PlainObjectBase<DerivedFA> & FA,
-  const Eigen::PlainObjectBase<DerivedVB> & VB,
-  const Eigen::PlainObjectBase<DerivedFB> & FB,
-  const RemeshSelfIntersectionsParam & params,
-  Eigen::PlainObjectBase<DerivedIF> & IF,
-  Eigen::PlainObjectBase<DerivedVVA> & VVA,
-  Eigen::PlainObjectBase<DerivedFFA> & FFA,
-  Eigen::PlainObjectBase<DerivedJA>  & JA,
-  Eigen::PlainObjectBase<DerivedIMA> & IMA,
-  Eigen::PlainObjectBase<DerivedVVB> & VVB,
-  Eigen::PlainObjectBase<DerivedFFB> & FFB,
-  Eigen::PlainObjectBase<DerivedJB>  & JB,
-  Eigen::PlainObjectBase<DerivedIMB> & IMB)
+    const Eigen::PlainObjectBase<DerivedVA> & VA,
+    const Eigen::PlainObjectBase<DerivedFA> & FA,
+    const Eigen::PlainObjectBase<DerivedVB> & VB,
+    const Eigen::PlainObjectBase<DerivedFB> & FB,
+    const RemeshSelfIntersectionsParam & params,
+    Eigen::PlainObjectBase<DerivedIF> & IF,
+    Eigen::PlainObjectBase<DerivedVVAB> & VVAB,
+    Eigen::PlainObjectBase<DerivedFFAB> & FFAB,
+    Eigen::PlainObjectBase<DerivedJAB>  & JAB,
+    Eigen::PlainObjectBase<DerivedIMAB> & IMAB)
 {
 {
   if(params.detect_only)
   if(params.detect_only)
   {
   {
     return intersect_other_helper<CGAL::Epick>
     return intersect_other_helper<CGAL::Epick>
-      (VA,FA,VB,FB,params,IF,VVA,FFA,JA,IMA,VVB,FFB,JB,IMB);
+      (VA,FA,VB,FB,params,IF,VVAB,FFAB,JAB,IMAB);
   }else
   }else
   {
   {
     return intersect_other_helper<CGAL::Epeck>
     return intersect_other_helper<CGAL::Epeck>
-      (VA,FA,VB,FB,params,IF,VVA,FFA,JA,IMA,VVB,FFB,JB,IMB);
+      (VA,FA,VB,FB,params,IF,VVAB,FFAB,JAB,IMAB);
   }
   }
 }
 }
 
 
@@ -261,11 +277,11 @@ IGL_INLINE bool igl::copyleft::cgal::intersect_other(
   const bool first_only,
   const bool first_only,
   Eigen::MatrixXi & IF)
   Eigen::MatrixXi & IF)
 {
 {
-  Eigen::MatrixXd VVA,VVB;
-  Eigen::MatrixXi FFA,FFB;
-  Eigen::VectorXi JA,JB,IMA,IMB;
+  Eigen::MatrixXd VVAB;
+  Eigen::MatrixXi FFAB;
+  Eigen::VectorXi JAB,IMAB;
   return intersect_other(
   return intersect_other(
-    VA,FA,VB,FB,{true,first_only},IF,VVA,FFA,JA,IMA,VVB,FFB,JB,IMB);
+    VA,FA,VB,FB,{true,first_only},IF,VVAB,FFAB,JAB,IMAB);
 }
 }
 
 
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY

+ 13 - 24
include/igl/copyleft/cgal/intersect_other.h

@@ -39,28 +39,21 @@ namespace igl
       // Outputs:
       // Outputs:
       //   IF  #intersecting face pairs by 2 list of intersecting face pairs,
       //   IF  #intersecting face pairs by 2 list of intersecting face pairs,
       //     indexing FA and FB
       //     indexing FA and FB
-      //   VVA  #VVA by 3 list of vertex positions
-      //   FFA  #FFA by 3 list of triangle indices into VVA
-      //   JA  #FFA list of indices into FA denoting birth triangle
-      //   IMA  #VVA list of indices into VVA of unique vertices.
-      //   VVB  #VVB by 3 list of vertex positions
-      //   FFB  #FFB by 3 list of triangle indices into VVB
-      //   JB  #FFB list of indices into FB denoting birth triangle
-      //   IMB  #VVB list of indices into VVB of unique vertices.
+      //   VVAB  #VVAB by 3 list of vertex positions
+      //   FFAB  #FFAB by 3 list of triangle indices into VVA
+      //   JAB  #FFAB list of indices into [FA;FB] denoting birth triangle
+      //   IMAB  #VVAB list of indices stitching duplicates (resulting from
+      //     mesh intersections) together
       template <
       template <
         typename DerivedVA,
         typename DerivedVA,
         typename DerivedFA,
         typename DerivedFA,
         typename DerivedVB,
         typename DerivedVB,
         typename DerivedFB,
         typename DerivedFB,
         typename DerivedIF,
         typename DerivedIF,
-        typename DerivedVVA,
-        typename DerivedFFA,
-        typename DerivedJA,
-        typename DerivedIMA,
-        typename DerivedVVB,
-        typename DerivedFFB,
-        typename DerivedJB,
-        typename DerivedIMB>
+        typename DerivedVVAB,
+        typename DerivedFFAB,
+        typename DerivedJAB,
+        typename DerivedIMAB>
       IGL_INLINE bool intersect_other(
       IGL_INLINE bool intersect_other(
         const Eigen::PlainObjectBase<DerivedVA> & VA,
         const Eigen::PlainObjectBase<DerivedVA> & VA,
         const Eigen::PlainObjectBase<DerivedFA> & FA,
         const Eigen::PlainObjectBase<DerivedFA> & FA,
@@ -68,14 +61,10 @@ namespace igl
         const Eigen::PlainObjectBase<DerivedFB> & FB,
         const Eigen::PlainObjectBase<DerivedFB> & FB,
         const RemeshSelfIntersectionsParam & params,
         const RemeshSelfIntersectionsParam & params,
         Eigen::PlainObjectBase<DerivedIF> & IF,
         Eigen::PlainObjectBase<DerivedIF> & IF,
-        Eigen::PlainObjectBase<DerivedVVA> & VVA,
-        Eigen::PlainObjectBase<DerivedFFA> & FFA,
-        Eigen::PlainObjectBase<DerivedJA>  & JA,
-        Eigen::PlainObjectBase<DerivedIMA> & IMA,
-        Eigen::PlainObjectBase<DerivedVVB> & VVB,
-        Eigen::PlainObjectBase<DerivedFFB> & FFB,
-        Eigen::PlainObjectBase<DerivedJB>  & JB,
-        Eigen::PlainObjectBase<DerivedIMB> & IMB);
+        Eigen::PlainObjectBase<DerivedVVAB> & VVAB,
+        Eigen::PlainObjectBase<DerivedFFAB> & FFAB,
+        Eigen::PlainObjectBase<DerivedJAB>  & JAB,
+        Eigen::PlainObjectBase<DerivedIMAB> & IMAB);
       // Legacy wrapper for detect only using common types.
       // Legacy wrapper for detect only using common types.
       //
       //
       // Inputs:
       // Inputs:

+ 40 - 7
include/igl/copyleft/cgal/intersect_with_half_space.cpp

@@ -19,11 +19,11 @@ IGL_INLINE bool igl::copyleft::cgal::intersect_with_half_space(
   Eigen::PlainObjectBase<DerivedFC > & FC,
   Eigen::PlainObjectBase<DerivedFC > & FC,
   Eigen::PlainObjectBase<DerivedJ > & J)
   Eigen::PlainObjectBase<DerivedJ > & J)
 {
 {
-  Eigen::Matrix<CGAL::Epeck::FT,8,3> BV;
-  Eigen::Matrix<int,12,3> BF;
-  half_space_box(p,n,V,BV,BF);
-  // Disturbingly, (BV,BF) must be first argument
-  return mesh_boolean(BV,BF,V,F,MESH_BOOLEAN_TYPE_INTERSECT,VC,FC,J);
+  typedef CGAL::Plane_3<CGAL::Epeck> Plane;
+  typedef CGAL::Point_3<CGAL::Epeck> Point;
+  typedef CGAL::Vector_3<CGAL::Epeck> Vector;
+  Plane P(Point(p(0),p(1),p(2)),Vector(n(0),n(1),n(2)));
+  return intersect_with_half_space(V,F,P,VC,FC,J);
 }
 }
 
 
 template <
 template <
@@ -40,15 +40,48 @@ IGL_INLINE bool igl::copyleft::cgal::intersect_with_half_space(
   Eigen::PlainObjectBase<DerivedVC > & VC,
   Eigen::PlainObjectBase<DerivedVC > & VC,
   Eigen::PlainObjectBase<DerivedFC > & FC,
   Eigen::PlainObjectBase<DerivedFC > & FC,
   Eigen::PlainObjectBase<DerivedJ > & J)
   Eigen::PlainObjectBase<DerivedJ > & J)
+{
+  typedef CGAL::Plane_3<CGAL::Epeck> Plane;
+  Plane P(equ(0),equ(1),equ(2),equ(3));
+  return intersect_with_half_space(V,F,P,VC,FC,J);
+}
+
+template <
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedVC,
+  typename DerivedFC,
+  typename DerivedJ>
+IGL_INLINE bool igl::copyleft::cgal::intersect_with_half_space(
+  const Eigen::PlainObjectBase<DerivedV > & V,
+  const Eigen::PlainObjectBase<DerivedF > & F,
+  const CGAL::Plane_3<CGAL::Epeck> & P,
+  Eigen::PlainObjectBase<DerivedVC > & VC,
+  Eigen::PlainObjectBase<DerivedFC > & FC,
+  Eigen::PlainObjectBase<DerivedJ > & J)
 {
 {
   Eigen::Matrix<CGAL::Epeck::FT,8,3> BV;
   Eigen::Matrix<CGAL::Epeck::FT,8,3> BV;
   Eigen::Matrix<int,12,3> BF;
   Eigen::Matrix<int,12,3> BF;
-  half_space_box(equ,V,BV,BF);
+  half_space_box(P,V,BV,BF);
   // Disturbingly, (BV,BF) must be first argument
   // Disturbingly, (BV,BF) must be first argument
-  return mesh_boolean(BV,BF,V,F,MESH_BOOLEAN_TYPE_INTERSECT,VC,FC,J);
+  const bool ret = mesh_boolean(BV,BF,V,F,MESH_BOOLEAN_TYPE_INTERSECT,VC,FC,J);
+  // But now J is wrong...
+  std::for_each(
+    J.data(),
+    J.data()+J.size(),
+    [&BF,&F](typename DerivedJ::Scalar & j)
+      {j = (j<BF.rows()?F.rows()+j:j-BF.rows());}
+    );
+  return ret;
 }
 }
 
 
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // Explicit template specialization
+// generated by autoexplicit.sh
+template bool igl::copyleft::cgal::intersect_with_half_space<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 4, 1, 1, 4>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 4, 1, 1, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+// generated by autoexplicit.sh
+template bool igl::copyleft::cgal::intersect_with_half_space<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 4, 0, -1, 4>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 4, 1, 1, 4>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 4, 0, -1, 4>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 4, 0, -1, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 4, 1, 1, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 4, 0, -1, 4> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+// generated by autoexplicit.sh
+template bool igl::copyleft::cgal::intersect_with_half_space<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 4, 1, 1, 4>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 4, 1, 1, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template bool igl::copyleft::cgal::intersect_with_half_space<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, 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<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 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<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template bool igl::copyleft::cgal::intersect_with_half_space<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, 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<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 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<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 #endif
 #endif

+ 28 - 3
include/igl/copyleft/cgal/intersect_with_half_space.h

@@ -2,6 +2,8 @@
 #define IGL_COPYLEFT_CGAL_INTERSECT_WITH_HALF_SPACE_H
 #define IGL_COPYLEFT_CGAL_INTERSECT_WITH_HALF_SPACE_H
 #include "../../igl_inline.h"
 #include "../../igl_inline.h"
 #include <Eigen/Core>
 #include <Eigen/Core>
+#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+#include <CGAL/Plane_3.h>
 
 
 namespace igl
 namespace igl
 {
 {
@@ -19,7 +21,8 @@ namespace igl
       // Outputs:
       // Outputs:
       //   VC  #VC by 3 list of vertex positions of boolean result mesh
       //   VC  #VC by 3 list of vertex positions of boolean result mesh
       //   FC  #FC by 3 list of triangle indices into VC
       //   FC  #FC by 3 list of triangle indices into VC
-      //   J  #FC list of indices into [F;F.rows()+[1;2]] revealing "birth" facet
+      //   J  #FC list of indices into [F;F.rows()+[1;2]] revealing "birth"
+      //     facet
       template <
       template <
         typename DerivedV,
         typename DerivedV,
         typename DerivedF,
         typename DerivedF,
@@ -36,12 +39,12 @@ namespace igl
         Eigen::PlainObjectBase<DerivedVC > & VC,
         Eigen::PlainObjectBase<DerivedVC > & VC,
         Eigen::PlainObjectBase<DerivedFC > & FC,
         Eigen::PlainObjectBase<DerivedFC > & FC,
         Eigen::PlainObjectBase<DerivedJ > & J);
         Eigen::PlainObjectBase<DerivedJ > & J);
-
       // Intersect a PWN mesh with a half-space. Plane equation.
       // Intersect a PWN mesh with a half-space. Plane equation.
       //
       //
       // Inputs:
       // Inputs:
       //   V  #V by 3 list of mesh vertex positions
       //   V  #V by 3 list of mesh vertex positions
-      //   equ  plane equation: a*x+b*y+c*z + d = 0
+      //   equ  plane equation: P(x,y,z) = a*x+b*y+c*z + d = 0, P(x,y,z) < 0 is
+      //     _inside_.
       // Outputs:
       // Outputs:
       //   VC  #VC by 3 list of vertex positions of boolean result mesh
       //   VC  #VC by 3 list of vertex positions of boolean result mesh
       //   FC  #FC by 3 list of triangle indices into VC
       //   FC  #FC by 3 list of triangle indices into VC
@@ -60,6 +63,28 @@ namespace igl
         Eigen::PlainObjectBase<DerivedVC > & VC,
         Eigen::PlainObjectBase<DerivedVC > & VC,
         Eigen::PlainObjectBase<DerivedFC > & FC,
         Eigen::PlainObjectBase<DerivedFC > & FC,
         Eigen::PlainObjectBase<DerivedJ > & J);
         Eigen::PlainObjectBase<DerivedJ > & J);
+      // Intersect a PWN mesh with a half-space. CGAL Plane.
+      //
+      // Inputs:
+      //   V  #V by 3 list of mesh vertex positions
+      //   P  plane 
+      // Outputs:
+      //   VC  #VC by 3 list of vertex positions of boolean result mesh
+      //   FC  #FC by 3 list of triangle indices into VC
+      //   J  #FC list of indices into [F;F.rows()+[1;2]] revealing "birth" facet
+      template <
+        typename DerivedV,
+        typename DerivedF,
+        typename DerivedVC,
+        typename DerivedFC,
+        typename DerivedJ>
+      IGL_INLINE bool intersect_with_half_space(
+        const Eigen::PlainObjectBase<DerivedV > & V,
+        const Eigen::PlainObjectBase<DerivedF > & F,
+        const CGAL::Plane_3<CGAL::Epeck> & P,
+        Eigen::PlainObjectBase<DerivedVC > & VC,
+        Eigen::PlainObjectBase<DerivedFC > & FC,
+        Eigen::PlainObjectBase<DerivedJ > & J);
     }
     }
   }
   }
 }
 }

+ 2 - 0
include/igl/copyleft/cgal/mesh_boolean.cpp

@@ -443,6 +443,8 @@ template bool igl::copyleft::cgal::mesh_boolean<Eigen::Matrix<CGAL::Lazy_exact_n
 template bool igl::copyleft::cgal::mesh_boolean<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(std::vector<Eigen::Matrix<double, -1, -1, 0, -1, -1>, std::allocator<Eigen::Matrix<double, -1, -1, 0, -1, -1> > > const&, std::vector<Eigen::Matrix<int, -1, -1, 0, -1, -1>, std::allocator<Eigen::Matrix<int, -1, -1, 0, -1, -1> > > const&, std::function<int (Eigen::Matrix<int, 1, -1, 1, 1, -1>)> const&, std::function<int (int, int)> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template bool igl::copyleft::cgal::mesh_boolean<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(std::vector<Eigen::Matrix<double, -1, -1, 0, -1, -1>, std::allocator<Eigen::Matrix<double, -1, -1, 0, -1, -1> > > const&, std::vector<Eigen::Matrix<int, -1, -1, 0, -1, -1>, std::allocator<Eigen::Matrix<int, -1, -1, 0, -1, -1> > > const&, std::function<int (Eigen::Matrix<int, 1, -1, 1, 1, -1>)> const&, std::function<int (int, int)> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template bool igl::copyleft::cgal::mesh_boolean<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template bool igl::copyleft::cgal::mesh_boolean<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template bool igl::copyleft::cgal::mesh_boolean<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 8, 3, 0, 8, 3>, Eigen::Matrix<int, 12, 3, 0, 12, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 8, 3, 0, 8, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, 12, 3, 0, 12, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, igl::MeshBooleanType const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template bool igl::copyleft::cgal::mesh_boolean<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 8, 3, 0, 8, 3>, Eigen::Matrix<int, 12, 3, 0, 12, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 8, 3, 0, 8, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, 12, 3, 0, 12, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, igl::MeshBooleanType const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+template bool igl::copyleft::cgal::mesh_boolean<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template bool igl::copyleft::cgal::mesh_boolean<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, igl::MeshBooleanType const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 #undef IGL_STATIC_LIBRARY
 #undef IGL_STATIC_LIBRARY
 #include "../../remove_unreferenced.cpp"
 #include "../../remove_unreferenced.cpp"
 template void igl::remove_unreferenced<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::remove_unreferenced<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);

+ 31 - 23
include/igl/copyleft/cgal/point_mesh_squared_distance.cpp

@@ -8,14 +8,21 @@
 #include "point_mesh_squared_distance.h"
 #include "point_mesh_squared_distance.h"
 #include "mesh_to_cgal_triangle_list.h"
 #include "mesh_to_cgal_triangle_list.h"
 
 
-template <typename Kernel>
+template <
+  typename Kernel,
+  typename DerivedP,
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedsqrD,
+  typename DerivedI,
+  typename DerivedC>
 IGL_INLINE void igl::copyleft::cgal::point_mesh_squared_distance(
 IGL_INLINE void igl::copyleft::cgal::point_mesh_squared_distance(
-  const Eigen::MatrixXd & P,
-  const Eigen::MatrixXd & V,
-  const Eigen::MatrixXi & F,
-  Eigen::VectorXd & sqrD,
-  Eigen::VectorXi & I,
-  Eigen::MatrixXd & C)
+  const Eigen::PlainObjectBase<DerivedP> & P,
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::PlainObjectBase<DerivedF> & F,
+        Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
+        Eigen::PlainObjectBase<DerivedI> & I,
+        Eigen::PlainObjectBase<DerivedC> & C)
 {
 {
   using namespace std;
   using namespace std;
   typedef CGAL::Triangle_3<Kernel> Triangle_3; 
   typedef CGAL::Triangle_3<Kernel> Triangle_3; 
@@ -29,10 +36,10 @@ IGL_INLINE void igl::copyleft::cgal::point_mesh_squared_distance(
   return point_mesh_squared_distance(P,tree,T,sqrD,I,C);
   return point_mesh_squared_distance(P,tree,T,sqrD,I,C);
 }
 }
 
 
-template <typename Kernel>
+template <typename Kernel, typename DerivedV, typename DerivedF>
 IGL_INLINE void igl::copyleft::cgal::point_mesh_squared_distance_precompute(
 IGL_INLINE void igl::copyleft::cgal::point_mesh_squared_distance_precompute(
-  const Eigen::MatrixXd & V,
-  const Eigen::MatrixXi & F,
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::PlainObjectBase<DerivedF> & F,
   CGAL::AABB_tree<
   CGAL::AABB_tree<
     CGAL::AABB_traits<Kernel, 
     CGAL::AABB_traits<Kernel, 
       CGAL::AABB_triangle_primitive<Kernel, 
       CGAL::AABB_triangle_primitive<Kernel, 
@@ -77,9 +84,14 @@ IGL_INLINE void igl::copyleft::cgal::point_mesh_squared_distance_precompute(
   tree.closest_point_and_primitive(Point_3(0,0,0));
   tree.closest_point_and_primitive(Point_3(0,0,0));
 }
 }
 
 
-template <typename Kernel>
+template <
+  typename Kernel,
+  typename DerivedP,
+  typename DerivedsqrD,
+  typename DerivedI,
+  typename DerivedC>
 IGL_INLINE void igl::copyleft::cgal::point_mesh_squared_distance(
 IGL_INLINE void igl::copyleft::cgal::point_mesh_squared_distance(
-  const Eigen::MatrixXd & P,
+  const Eigen::PlainObjectBase<DerivedP> & P,
   const CGAL::AABB_tree<
   const CGAL::AABB_tree<
     CGAL::AABB_traits<Kernel, 
     CGAL::AABB_traits<Kernel, 
       CGAL::AABB_triangle_primitive<Kernel, 
       CGAL::AABB_triangle_primitive<Kernel, 
@@ -88,9 +100,9 @@ IGL_INLINE void igl::copyleft::cgal::point_mesh_squared_distance(
     >
     >
   > & tree,
   > & tree,
   const std::vector<CGAL::Triangle_3<Kernel> > & T,
   const std::vector<CGAL::Triangle_3<Kernel> > & T,
-  Eigen::VectorXd & sqrD,
-  Eigen::VectorXi & I,
-  Eigen::MatrixXd & C)
+  Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
+  Eigen::PlainObjectBase<DerivedI> & I,
+  Eigen::PlainObjectBase<DerivedC> & C)
 {
 {
   typedef CGAL::Triangle_3<Kernel> Triangle_3; 
   typedef CGAL::Triangle_3<Kernel> Triangle_3; 
   typedef typename std::vector<Triangle_3>::iterator Iterator;
   typedef typename std::vector<Triangle_3>::iterator Iterator;
@@ -110,18 +122,14 @@ IGL_INLINE void igl::copyleft::cgal::point_mesh_squared_distance(
     // Find closest point and primitive id
     // Find closest point and primitive id
     Point_and_primitive_id pp = tree.closest_point_and_primitive(query);
     Point_and_primitive_id pp = tree.closest_point_and_primitive(query);
     Point_3 closest_point = pp.first;
     Point_3 closest_point = pp.first;
-    C(p,0) = CGAL::to_double(closest_point[0]);
-    C(p,1) = CGAL::to_double(closest_point[1]);
-    C(p,2) = CGAL::to_double(closest_point[2]);
-    sqrD(p) = CGAL::to_double((closest_point-query).squared_length());
+    assign_scalar(closest_point[0],C(p,0));
+    assign_scalar(closest_point[1],C(p,1));
+    assign_scalar(closest_point[2],C(p,2));
+    assign_scalar((closest_point-query).squared_length(),sqrD(p));
     I(p) = pp.second - T.begin();
     I(p) = pp.second - T.begin();
   }
   }
 }
 }
 
 
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // Explicit template specialization
-template void igl::copyleft::cgal::point_mesh_squared_distance_precompute<CGAL::Epick>(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, CGAL::AABB_tree<CGAL::AABB_traits<CGAL::Epick, CGAL::AABB_triangle_primitive<CGAL::Epick, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > >::iterator, CGAL::Boolean_tag<false> > > >&, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > >&);
-template void igl::copyleft::cgal::point_mesh_squared_distance<CGAL::Epeck>( const Eigen::MatrixXd & P, const Eigen::MatrixXd & V, const Eigen::MatrixXi & F, Eigen::VectorXd & sqrD, Eigen::VectorXi & I, Eigen::MatrixXd & C);
-template void igl::copyleft::cgal::point_mesh_squared_distance<CGAL::Epick>(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, 1, 0, -1, 1>&, Eigen::Matrix<int, -1, 1, 0, -1, 1>&, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
-template void igl::copyleft::cgal::point_mesh_squared_distance<CGAL::Simple_cartesian<double> >(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, 1, 0, -1, 1>&, Eigen::Matrix<int, -1, 1, 0, -1, 1>&, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
 #endif
 #endif

+ 31 - 15
include/igl/copyleft/cgal/point_mesh_squared_distance.h

@@ -33,24 +33,35 @@ namespace igl
       //
       //
       // Known bugs: This only computes distances to triangles. So unreferenced
       // Known bugs: This only computes distances to triangles. So unreferenced
       // vertices and degenerate triangles (segments) are ignored.
       // vertices and degenerate triangles (segments) are ignored.
-      template <typename Kernel>
+      template <
+        typename Kernel,
+        typename DerivedP,
+        typename DerivedV,
+        typename DerivedF,
+        typename DerivedsqrD,
+        typename DerivedI,
+        typename DerivedC>
       IGL_INLINE void point_mesh_squared_distance(
       IGL_INLINE void point_mesh_squared_distance(
-        const Eigen::MatrixXd & P,
-        const Eigen::MatrixXd & V,
-        const Eigen::MatrixXi & F,
-        Eigen::VectorXd & sqrD,
-        Eigen::VectorXi & I,
-        Eigen::MatrixXd & C);
+        const Eigen::PlainObjectBase<DerivedP> & P,
+        const Eigen::PlainObjectBase<DerivedV> & V,
+        const Eigen::PlainObjectBase<DerivedF> & F,
+              Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
+              Eigen::PlainObjectBase<DerivedI> & I,
+              Eigen::PlainObjectBase<DerivedC> & C);
       // Probably can do this in a way that we don't pass around `tree` and `T`
       // Probably can do this in a way that we don't pass around `tree` and `T`
       //
       //
       // Outputs:
       // Outputs:
       //   tree  CGAL's AABB tree
       //   tree  CGAL's AABB tree
       //   T  list of CGAL triangles in order of F (for determining which was found
       //   T  list of CGAL triangles in order of F (for determining which was found
       //     in computation)
       //     in computation)
-      template <typename Kernel>
+      template <
+        typename Kernel,
+        typename DerivedV,
+        typename DerivedF
+        >
       IGL_INLINE void point_mesh_squared_distance_precompute(
       IGL_INLINE void point_mesh_squared_distance_precompute(
-        const Eigen::MatrixXd & V,
-        const Eigen::MatrixXi & F,
+        const Eigen::PlainObjectBase<DerivedV> & V,
+        const Eigen::PlainObjectBase<DerivedF> & F,
         CGAL::AABB_tree<
         CGAL::AABB_tree<
           CGAL::AABB_traits<Kernel, 
           CGAL::AABB_traits<Kernel, 
             CGAL::AABB_triangle_primitive<Kernel, 
             CGAL::AABB_triangle_primitive<Kernel, 
@@ -63,9 +74,14 @@ namespace igl
       //  see above
       //  see above
       // Outputs:
       // Outputs:
       //  see above
       //  see above
-      template <typename Kernel>
+      template <
+        typename Kernel,
+        typename DerivedP,
+        typename DerivedsqrD,
+        typename DerivedI,
+        typename DerivedC>
       IGL_INLINE void point_mesh_squared_distance(
       IGL_INLINE void point_mesh_squared_distance(
-        const Eigen::MatrixXd & P,
+        const Eigen::PlainObjectBase<DerivedP> & P,
         const CGAL::AABB_tree<
         const CGAL::AABB_tree<
           CGAL::AABB_traits<Kernel, 
           CGAL::AABB_traits<Kernel, 
             CGAL::AABB_triangle_primitive<Kernel, 
             CGAL::AABB_triangle_primitive<Kernel, 
@@ -74,9 +90,9 @@ namespace igl
           >
           >
         > & tree,
         > & tree,
         const std::vector<CGAL::Triangle_3<Kernel> > & T,
         const std::vector<CGAL::Triangle_3<Kernel> > & T,
-        Eigen::VectorXd & sqrD,
-        Eigen::VectorXi & I,
-        Eigen::MatrixXd & C);
+        Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
+        Eigen::PlainObjectBase<DerivedI> & I,
+        Eigen::PlainObjectBase<DerivedC> & C);
     }
     }
   }
   }
 }
 }

+ 50 - 0
include/igl/copyleft/cgal/point_solid_signed_squared_distance.cpp

@@ -0,0 +1,50 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "point_solid_signed_squared_distance.h"
+#include "points_inside_component.h"
+#include "point_mesh_squared_distance.h"
+#include "../../list_to_matrix.h"
+#include "../../slice_mask.h"
+#include <vector>
+#include <Eigen/Core>
+
+template <
+  typename DerivedQ,
+  typename DerivedVB,
+  typename DerivedFB,
+  typename DerivedD>
+IGL_INLINE void igl::copyleft::cgal::point_solid_signed_squared_distance(
+  const Eigen::PlainObjectBase<DerivedQ> & Q,
+  const Eigen::PlainObjectBase<DerivedVB> & VB,
+  const Eigen::PlainObjectBase<DerivedFB> & FB,
+  Eigen::PlainObjectBase<DerivedD> & D)
+{
+  // compute unsigned distances
+  Eigen::VectorXi I;
+  DerivedVB C;
+  point_mesh_squared_distance<CGAL::Epeck>(Q,VB,FB,D,I,C);
+  // Collect queries that have non-zero distance
+  Eigen::Array<bool,Eigen::Dynamic,1> NZ = D.array()!=0;
+  // Compute sign for non-zero distance queries
+  DerivedQ QNZ;
+  slice_mask(Q,NZ,1,QNZ);
+  Eigen::Array<bool,Eigen::Dynamic,1> DNZ;
+  igl::copyleft::cgal::points_inside_component(VB,FB,QNZ,DNZ);
+  // Apply sign to distances
+  DerivedD S = DerivedD::Zero(Q.rows(),1);
+  {
+    int k = 0;
+    for(int q = 0;q<Q.rows();q++)
+    {
+      if(NZ(q))
+      {
+        D(q) *= DNZ(k++) ? -1. : 1.;
+      }
+    }
+  }
+}

+ 48 - 0
include/igl/copyleft/cgal/point_solid_signed_squared_distance.h

@@ -0,0 +1,48 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_COPYLEFT_CGAL_POINT_SOLID_SIGNED_SQUARED_DISTANCE_H
+#define IGL_COPYLEFT_CGAL_POINT_SOLID_SIGNED_SQUARED_DISTANCE_H
+#include "../../igl_inline.h"
+#include <Eigen/Core>
+
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // POINT_SOLID_SIGNED_SQUARED_DISTANCE Given a set of points (Q) and the
+      // boundary mesh (VB,FB) of a solid (as defined in [Zhou et al. 2016],
+      // determine the signed squared distance for each point q in Q so that d(q,B) is
+      // negative if inside and positive if outside.
+      //
+      // Inputs:
+      //   Q  #Q by 3 list of query point positions
+      //   VB  #VB by 3 list of mesh vertex positions of B
+      //   FB  #FB by 3 list of mesh triangle indices into VB
+      // Outputs:
+      //   D
+      template <
+        typename DerivedQ,
+        typename DerivedVB,
+        typename DerivedFB,
+        typename DerivedD>
+      IGL_INLINE void point_solid_signed_squared_distance(
+        const Eigen::PlainObjectBase<DerivedQ> & Q,
+        const Eigen::PlainObjectBase<DerivedVB> & VB,
+        const Eigen::PlainObjectBase<DerivedFB> & FB,
+        Eigen::PlainObjectBase<DerivedD> & D);
+    }
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "point_solid_signed_squared_distance.cpp"
+#endif
+
+#endif

+ 1 - 0
include/igl/copyleft/cgal/propagate_winding_numbers.cpp

@@ -119,6 +119,7 @@ IGL_INLINE bool igl::copyleft::cgal::propagate_winding_numbers(
   bool valid = true;
   bool valid = true;
   if (!piecewise_constant_winding_number(F, uE, uE2E)) 
   if (!piecewise_constant_winding_number(F, uE, uE2E)) 
   {
   {
+    assert(false && "Input mesh is not orientable");
     std::cerr << "Input mesh is not orientable!" << std::endl;
     std::cerr << "Input mesh is not orientable!" << std::endl;
     valid = false;
     valid = false;
   }
   }

文件差異過大導致無法顯示
+ 5 - 12
include/igl/copyleft/cgal/remesh_intersections.cpp


+ 0 - 7
include/igl/copyleft/cgal/remesh_intersections.h

@@ -30,7 +30,6 @@ namespace igl
       //   offending #offending map taking face indices into F to pairs of order
       //   offending #offending map taking face indices into F to pairs of order
       //     of first finding and list of intersection objects from all
       //     of first finding and list of intersection objects from all
       //     intersections
       //     intersections
-      //   edge2faces  #edges <= #offending*3 to incident offending faces 
       //   stitch_all  if true, merge all vertices with thte same coordiante.
       //   stitch_all  if true, merge all vertices with thte same coordiante.
       // Outputs:
       // Outputs:
       //   VV  #VV by 3 list of vertex positions, if stitch_all = false then
       //   VV  #VV by 3 list of vertex positions, if stitch_all = false then
@@ -58,9 +57,6 @@ namespace igl
           typename DerivedF::Index,
           typename DerivedF::Index,
             std::vector<
             std::vector<
             std::pair<typename DerivedF::Index, CGAL::Object> > > & offending,
             std::pair<typename DerivedF::Index, CGAL::Object> > > & offending,
-        const std::map<
-          std::pair<typename DerivedF::Index,typename DerivedF::Index>,
-          std::vector<typename DerivedF::Index> > & edge2faces,
         bool stitch_all,
         bool stitch_all,
         Eigen::PlainObjectBase<DerivedVV> & VV,
         Eigen::PlainObjectBase<DerivedVV> & VV,
         Eigen::PlainObjectBase<DerivedFF> & FF,
         Eigen::PlainObjectBase<DerivedFF> & FF,
@@ -83,9 +79,6 @@ namespace igl
           typename DerivedF::Index,
           typename DerivedF::Index,
             std::vector<
             std::vector<
             std::pair<typename DerivedF::Index, CGAL::Object> > > & offending,
             std::pair<typename DerivedF::Index, CGAL::Object> > > & offending,
-        const std::map<
-          std::pair<typename DerivedF::Index,typename DerivedF::Index>,
-          std::vector<typename DerivedF::Index> > & edge2faces,
         Eigen::PlainObjectBase<DerivedVV> & VV,
         Eigen::PlainObjectBase<DerivedVV> & VV,
         Eigen::PlainObjectBase<DerivedFF> & FF,
         Eigen::PlainObjectBase<DerivedFF> & FF,
         Eigen::PlainObjectBase<DerivedJ> & J,
         Eigen::PlainObjectBase<DerivedJ> & J,

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

@@ -1,4 +1,4 @@
-#include "string_to_mesh_boolean_type.h"
+#include "string_to_mesh_boolean_type.h"
 #include <algorithm>
 #include <algorithm>
 #include <cassert>
 #include <cassert>
 #include <vector>
 #include <vector>

+ 106 - 0
include/igl/copyleft/cgal/trim_with_solid.cpp

@@ -0,0 +1,106 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "trim_with_solid.h"
+#include "assign_scalar.h"
+#include "intersect_other.h"
+#include "point_solid_signed_squared_distance.h"
+
+#include "../../extract_manifold_patches.h"
+#include "../../list_to_matrix.h"
+#include "../../remove_unreferenced.h"
+#include "../../slice_mask.h"
+
+#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+
+#include <vector>
+
+template <
+  typename DerivedVA,
+  typename DerivedFA,
+  typename DerivedVB,
+  typename DerivedFB,
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedD,
+  typename DerivedJ>
+IGL_INLINE void igl::copyleft::cgal::trim_with_solid(
+  const Eigen::PlainObjectBase<DerivedVA> & VA,
+  const Eigen::PlainObjectBase<DerivedFA> & FA,
+  const Eigen::PlainObjectBase<DerivedVB> & VB,
+  const Eigen::PlainObjectBase<DerivedFB> & FB,
+  Eigen::PlainObjectBase<DerivedV> & Vd,
+  Eigen::PlainObjectBase<DerivedF> & F,
+  Eigen::PlainObjectBase<DerivedD> & D,
+  Eigen::PlainObjectBase<DerivedJ> & J)
+{
+  // resolve intersections using exact representation
+  typedef Eigen::Matrix<CGAL::Epeck::FT,Eigen::Dynamic,3> MatrixX3E;
+  typedef Eigen::Matrix<CGAL::Epeck::FT,Eigen::Dynamic,1> VectorXE;
+  typedef Eigen::Matrix<CGAL::Epeck::FT,1,3> RowVector3E;
+  MatrixX3E V;
+  Eigen::MatrixXi _1;
+  Eigen::VectorXi _2;
+  // Intersect A and B meshes and stitch together new faces
+  igl::copyleft::cgal::intersect_other(
+    VA,FA,VB,FB,{false,false,true},_1,V,F,J,_2);
+  // Partition result into manifold patches
+  Eigen::VectorXi P;
+  const size_t num_patches = igl::extract_manifold_patches(F,P);
+  // only keep faces from A
+  Eigen::Matrix<bool,Eigen::Dynamic,1> A = J.array()< FA.rows();
+  igl::slice_mask(Eigen::MatrixXi(F),A,1,F);
+  igl::slice_mask(Eigen::VectorXi(P),A,1,P);
+  igl::slice_mask(Eigen::VectorXi(J),A,1,J);
+  // Agregate representative query points for each patch
+  std::vector<bool> flag(num_patches);
+  std::vector<std::vector<CGAL::Epeck::FT> > vQ;
+  Eigen::VectorXi P2Q(num_patches);
+  for(int f = 0;f<P.rows();f++)
+  {
+    const auto p = P(f);
+    // if not yet processed this patch
+    if(!flag[p])
+    {
+      P2Q(p) = vQ.size();
+      std::vector<CGAL::Epeck::FT> q = {
+        (V(F(f,0),0)+ V(F(f,1),0)+ V(F(f,2),0))/3.,
+        (V(F(f,0),1)+ V(F(f,1),1)+ V(F(f,2),1))/3.,
+        (V(F(f,0),2)+ V(F(f,1),2)+ V(F(f,2),2))/3.};
+      vQ.emplace_back(q);
+      flag[p] = true;
+    }
+  }
+  MatrixX3E Q;
+  igl::list_to_matrix(vQ,Q);
+  VectorXE SP;
+  point_solid_signed_squared_distance(Q,VB,FB,SP);
+  Eigen::Matrix<bool,Eigen::Dynamic,1> DP = SP.array()>0;
+  // distribute flag to all faces
+  D.resize(F.rows());
+  for(int f = 0;f<F.rows();f++)
+  {
+    D(f) = DP(P2Q(P(f)));
+  }
+  Eigen::VectorXi _;
+  igl::remove_unreferenced(MatrixX3E(V),DerivedF(F),V,F,_);
+  const auto & assign = [](
+    const MatrixX3E & V, 
+    Eigen::PlainObjectBase<DerivedV> & Vd)
+  {
+    Vd.resize(V.rows(),3);
+    for(int v = 0;v<V.rows();v++)
+    {
+      for(int d = 0;d<3;d++) 
+      {
+        igl::copyleft::cgal::assign_scalar(V(v,d),Vd(v,d));
+      }
+    }
+  };
+  assign(V,Vd);
+}
+

+ 63 - 0
include/igl/copyleft/cgal/trim_with_solid.h

@@ -0,0 +1,63 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_COPYLEFT_CGAL_TRIM_WITH_SOLID_H
+#define IGL_COPYLEFT_CGAL_TRIM_WITH_SOLID_H
+
+#include "../../igl_inline.h"
+#include <Eigen/Core>
+
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // TRIM_WITH_SOLID Given an arbitrary mesh (VA,FA) and the boundary mesh
+      // (VB,FB) of a solid (as defined in [Zhou et al. 2016]), Resolve intersections
+      // between A and B subdividing faces of A so that intersections with B exists
+      // only along edges and vertices (and coplanar faces). Then determine whether
+      // each of these faces is inside or outside of B. This can be used to extract
+      // the part of A inside or outside of B.
+      //
+      // Inputs:
+      //   VA  #VA by 3 list of mesh vertex positions of A
+      //   FA  #FA by 3 list of mesh triangle indices into VA
+      //   VB  #VB by 3 list of mesh vertex positions of B
+      //   FB  #FB by 3 list of mesh triangle indices into VB
+      // Outputs:
+      //   V  #V by 3 list of mesh vertex positions of output
+      //   F  #F by 3 list of mesh triangle indices into V
+      //   D  #F list of bools whether face is inside B
+      //   J  #F list of indices into FA revealing birth parent
+      //
+      template <
+        typename DerivedVA,
+        typename DerivedFA,
+        typename DerivedVB,
+        typename DerivedFB,
+        typename DerivedV,
+        typename DerivedF,
+        typename DerivedD,
+        typename DerivedJ>
+      IGL_INLINE void trim_with_solid(
+        const Eigen::PlainObjectBase<DerivedVA> & VA,
+        const Eigen::PlainObjectBase<DerivedFA> & FA,
+        const Eigen::PlainObjectBase<DerivedVB> & VB,
+        const Eigen::PlainObjectBase<DerivedFB> & FB,
+        Eigen::PlainObjectBase<DerivedV> & Vd,
+        Eigen::PlainObjectBase<DerivedF> & F,
+        Eigen::PlainObjectBase<DerivedD> & D,
+        Eigen::PlainObjectBase<DerivedJ> & J);
+    }
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "trim_with_solid.cpp"
+#endif
+#endif

+ 49 - 0
include/igl/copyleft/swept_volume.cpp

@@ -0,0 +1,49 @@
+#include "swept_volume.h"
+#include "../swept_volume_bounding_box.h"
+#include "../swept_volume_signed_distance.h"
+#include "../voxel_grid.h"
+#include "marching_cubes.h"
+#include <iostream>
+
+IGL_INLINE void igl::copyleft::swept_volume(
+  const Eigen::MatrixXd & V,
+  const Eigen::MatrixXi & F,
+  const std::function<Eigen::Affine3d(const double t)> & transform,
+  const size_t steps,
+  const size_t grid_res,
+  const size_t isolevel_grid,
+  Eigen::MatrixXd & SV,
+  Eigen::MatrixXi & SF)
+{
+  using namespace std;
+  using namespace Eigen;
+  using namespace igl;
+  using namespace igl::copyleft;
+
+  const auto & Vtransform = 
+    [&V,&transform](const size_t vi,const double t)->RowVector3d
+  {
+    Vector3d Vvi = V.row(vi).transpose();
+    return (transform(t)*Vvi).transpose();
+  };
+  AlignedBox3d Mbox;
+  swept_volume_bounding_box(V.rows(),Vtransform,steps,Mbox);
+
+  // Amount of padding: pad*h should be >= isolevel
+  const int pad = isolevel_grid+1;
+  // number of vertices on the largest side
+  const int s = grid_res+2*pad;
+  const double h = Mbox.diagonal().maxCoeff()/(double)(s-2.*pad-1.);
+  const double isolevel = isolevel_grid*h;
+
+  // create grid
+  RowVector3i res;
+  MatrixXd GV;
+  voxel_grid(Mbox,s,pad,GV,res);
+
+  // compute values
+  VectorXd S;
+  swept_volume_signed_distance(V,F,transform,steps,GV,res,h,isolevel,S);
+  S.array()-=isolevel;
+  marching_cubes(S,GV,res(0),res(1),res(2),SV,SF);
+}

+ 41 - 0
include/igl/copyleft/swept_volume.h

@@ -0,0 +1,41 @@
+#ifndef IGL_COPYLEFT_SWEPT_VOLUME_H
+#define IGL_COPYLEFT_SWEPT_VOLUME_H
+#include "../igl_inline.h"
+#include <Eigen/Core>
+#include <Eigen/Geometry>
+namespace igl
+{
+  namespace copyleft
+  {
+    // Compute the surface of the swept volume of a solid object with surface
+    // (V,F) mesh under going rigid motion.
+    // 
+    // Inputs:
+    //   V  #V by 3 list of mesh positions in reference pose
+    //   F  #F by 3 list of mesh indices into V
+    //   transform  function handle so that transform(t) returns the rigid
+    //     transformation at time t∈[0,1]
+    //   steps  number of time steps: steps=3 --> t∈{0,0.5,1}
+    //   grid_res  number of grid cells on the longest side containing the
+    //     motion (isolevel+1 cells will also be added on each side as padding)
+    //   isolevel  distance level to be contoured as swept volume
+    // Outputs:
+    //   SV  #SV by 3 list of mesh positions of the swept surface
+    //   SF  #SF by 3 list of mesh faces into SV
+    IGL_INLINE void swept_volume(
+      const Eigen::MatrixXd & V,
+      const Eigen::MatrixXi & F,
+      const std::function<Eigen::Affine3d(const double t)> & transform,
+      const size_t steps,
+      const size_t grid_res,
+      const size_t isolevel,
+      Eigen::MatrixXd & SV,
+      Eigen::MatrixXi & SF);
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "swept_volume.cpp"
+#endif
+
+#endif

+ 16 - 22
include/igl/doublearea.cpp

@@ -7,6 +7,7 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "doublearea.h"
 #include "doublearea.h"
 #include "edge_lengths.h"
 #include "edge_lengths.h"
+#include "parallel_for.h"
 #include "sort.h"
 #include "sort.h"
 #include <cassert>
 #include <cassert>
 #include <iostream>
 #include <iostream>
@@ -148,28 +149,21 @@ IGL_INLINE void igl::doublearea(
   assert((Index)s.rows() == m);
   assert((Index)s.rows() == m);
   // resize output
   // resize output
   dblA.resize(l.rows(),1);
   dblA.resize(l.rows(),1);
-  // Minimum number of iterms per openmp thread
-  #ifndef IGL_OMP_MIN_VALUE
-  #  define IGL_OMP_MIN_VALUE 1000
-  #endif
-  #pragma omp parallel for if (m>IGL_OMP_MIN_VALUE)
-  for(Index i = 0;i<m;i++)
-  {
-    //// Heron's formula for area
-    //const typename Derivedl::Scalar arg =
-    //  s(i)*(s(i)-l(i,0))*(s(i)-l(i,1))*(s(i)-l(i,2));
-    //assert(arg>=0);
-    //dblA(i) = 2.0*sqrt(arg);
-    // Kahan's Heron's formula
-    const typename Derivedl::Scalar arg =
-      (l(i,0)+(l(i,1)+l(i,2)))*
-      (l(i,2)-(l(i,0)-l(i,1)))*
-      (l(i,2)+(l(i,0)-l(i,1)))*
-      (l(i,0)+(l(i,1)-l(i,2)));
-    dblA(i) = 2.0*0.25*sqrt(arg);
-    assert( l(i,2) - (l(i,0)-l(i,1)) && "FAILED KAHAN'S ASSERTION");
-    assert(dblA(i) == dblA(i) && "DOUBLEAREA() PRODUCED NaN");
-  }
+  parallel_for(
+    m,
+    [&l,&dblA](const int i)
+    {
+      // Kahan's Heron's formula
+      const typename Derivedl::Scalar arg =
+        (l(i,0)+(l(i,1)+l(i,2)))*
+        (l(i,2)-(l(i,0)-l(i,1)))*
+        (l(i,2)+(l(i,0)-l(i,1)))*
+        (l(i,0)+(l(i,1)-l(i,2)));
+      dblA(i) = 2.0*0.25*sqrt(arg);
+      assert( l(i,2) - (l(i,0)-l(i,1)) && "FAILED KAHAN'S ASSERTION");
+      assert(dblA(i) == dblA(i) && "DOUBLEAREA() PRODUCED NaN");
+    },
+    1000l);
 }
 }
 
 
 template <typename DerivedV, typename DerivedF, typename DeriveddblA>
 template <typename DerivedV, typename DerivedF, typename DeriveddblA>

+ 22 - 21
include/igl/edge_lengths.cpp

@@ -6,6 +6,7 @@
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can
 // obtain one at http://mozilla.org/MPL/2.0/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "edge_lengths.h"
 #include "edge_lengths.h"
+#include "parallel_for.h"
 #include <iostream>
 #include <iostream>
 
 
 template <typename DerivedV, typename DerivedF, typename DerivedL>
 template <typename DerivedV, typename DerivedF, typename DerivedL>
@@ -16,10 +17,6 @@ IGL_INLINE void igl::edge_lengths(
 {
 {
   using namespace std;
   using namespace std;
   const int m = F.rows();
   const int m = F.rows();
-  // Minimum number of iterms per openmp thread
-#ifndef IGL_OMP_MIN_VALUE
-#  define IGL_OMP_MIN_VALUE 1000
-#endif
   switch(F.cols())
   switch(F.cols())
   {
   {
     case 2:
     case 2:
@@ -35,29 +32,33 @@ IGL_INLINE void igl::edge_lengths(
     {
     {
       L.resize(m,3);
       L.resize(m,3);
       // loop over faces
       // loop over faces
-      #pragma omp parallel for if (m>IGL_OMP_MIN_VALUE)
-      for(int i = 0;i<m;i++)
-      {
-        L(i,0) = (V.row(F(i,1))-V.row(F(i,2))).norm();
-        L(i,1) = (V.row(F(i,2))-V.row(F(i,0))).norm();
-        L(i,2) = (V.row(F(i,0))-V.row(F(i,1))).norm();
-      }
+      parallel_for(
+        m,
+        [&V,&F,&L](const int i)
+        {
+          L(i,0) = (V.row(F(i,1))-V.row(F(i,2))).norm();
+          L(i,1) = (V.row(F(i,2))-V.row(F(i,0))).norm();
+          L(i,2) = (V.row(F(i,0))-V.row(F(i,1))).norm();
+        },
+        1000);
       break;
       break;
     }
     }
     case 4:
     case 4:
     {
     {
       L.resize(m,6);
       L.resize(m,6);
       // loop over faces
       // loop over faces
-      #pragma omp parallel for if (m>IGL_OMP_MIN_VALUE)
-      for(int i = 0;i<m;i++)
-      {
-        L(i,0) = (V.row(F(i,3))-V.row(F(i,0))).norm();
-        L(i,1) = (V.row(F(i,3))-V.row(F(i,1))).norm();
-        L(i,2) = (V.row(F(i,3))-V.row(F(i,2))).norm();
-        L(i,3) = (V.row(F(i,1))-V.row(F(i,2))).norm();
-        L(i,4) = (V.row(F(i,2))-V.row(F(i,0))).norm();
-        L(i,5) = (V.row(F(i,0))-V.row(F(i,1))).norm();
-      }
+      parallel_for(
+        m,
+        [&V,&F,&L](const int i)
+        {
+          L(i,0) = (V.row(F(i,3))-V.row(F(i,0))).norm();
+          L(i,1) = (V.row(F(i,3))-V.row(F(i,1))).norm();
+          L(i,2) = (V.row(F(i,3))-V.row(F(i,2))).norm();
+          L(i,3) = (V.row(F(i,1))-V.row(F(i,2))).norm();
+          L(i,4) = (V.row(F(i,2))-V.row(F(i,0))).norm();
+          L(i,5) = (V.row(F(i,0))-V.row(F(i,1))).norm();
+        },
+        1000);
       break;
       break;
     }
     }
     default:
     default:

+ 1 - 0
include/igl/embree/ambient_occlusion.cpp

@@ -58,4 +58,5 @@ template void igl::embree::ambient_occlusion<Eigen::Matrix<double, -1, -1, 0, -1
 template void igl::embree::ambient_occlusion<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(igl::embree::EmbreeIntersector const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 template void igl::embree::ambient_occlusion<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(igl::embree::EmbreeIntersector const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 template void igl::embree::ambient_occlusion<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 template void igl::embree::ambient_occlusion<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 template void igl::embree::ambient_occlusion<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 template void igl::embree::ambient_occlusion<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
+template void igl::embree::ambient_occlusion<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 #endif
 #endif

+ 1 - 1
include/igl/embree/ambient_occlusion.h

@@ -7,7 +7,7 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #ifndef IGL_EMBREE_AMBIENT_OCCLUSION_H
 #ifndef IGL_EMBREE_AMBIENT_OCCLUSION_H
 #define IGL_EMBREE_AMBIENT_OCCLUSION_H
 #define IGL_EMBREE_AMBIENT_OCCLUSION_H
-#include <igl/igl_inline.h>
+#include "../igl_inline.h"
 #include <Eigen/Core>
 #include <Eigen/Core>
 namespace igl
 namespace igl
 {
 {

+ 26 - 25
include/igl/embree/reorient_facets_raycast.cpp

@@ -1,9 +1,9 @@
 // This file is part of libigl, a simple c++ geometry processing library.
 // This file is part of libigl, a simple c++ geometry processing library.
-// 
+//
 // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
 // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
 // obtain one at http://mozilla.org/MPL/2.0/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "reorient_facets_raycast.h"
 #include "reorient_facets_raycast.h"
 #include "../per_face_normals.h"
 #include "../per_face_normals.h"
@@ -17,8 +17,8 @@
 #include <limits>
 #include <limits>
 
 
 template <
 template <
-  typename DerivedV, 
-  typename DerivedF, 
+  typename DerivedV,
+  typename DerivedF,
   typename DerivedI,
   typename DerivedI,
   typename DerivedC>
   typename DerivedC>
 IGL_INLINE void igl::embree::reorient_facets_raycast(
 IGL_INLINE void igl::embree::reorient_facets_raycast(
@@ -36,37 +36,37 @@ IGL_INLINE void igl::embree::reorient_facets_raycast(
   using namespace std;
   using namespace std;
   assert(F.cols() == 3);
   assert(F.cols() == 3);
   assert(V.cols() == 3);
   assert(V.cols() == 3);
-  
+
   // number of faces
   // number of faces
   const int m = F.rows();
   const int m = F.rows();
-  
+
   MatrixXi FF = F;
   MatrixXi FF = F;
   if (facet_wise) {
   if (facet_wise) {
     C.resize(m);
     C.resize(m);
     for (int i = 0; i < m; ++i) C(i) = i;
     for (int i = 0; i < m; ++i) C(i) = i;
-  
+
   } else {
   } else {
     if (is_verbose) cout << "extracting patches... ";
     if (is_verbose) cout << "extracting patches... ";
     bfs_orient(F,FF,C);
     bfs_orient(F,FF,C);
   }
   }
   if (is_verbose) cout << (C.maxCoeff() + 1)  << " components. ";
   if (is_verbose) cout << (C.maxCoeff() + 1)  << " components. ";
-  
+
   // number of patches
   // number of patches
   const int num_cc = C.maxCoeff()+1;
   const int num_cc = C.maxCoeff()+1;
-  
+
   // Init Embree
   // Init Embree
   EmbreeIntersector ei;
   EmbreeIntersector ei;
   ei.init(V.template cast<float>(),FF);
   ei.init(V.template cast<float>(),FF);
-  
+
   // face normal
   // face normal
   MatrixXd N;
   MatrixXd N;
   per_face_normals(V,FF,N);
   per_face_normals(V,FF,N);
-  
+
   // face area
   // face area
   Matrix<typename DerivedV::Scalar,Dynamic,1> A;
   Matrix<typename DerivedV::Scalar,Dynamic,1> A;
   doublearea(V,FF,A);
   doublearea(V,FF,A);
   double area_total = A.sum();
   double area_total = A.sum();
-  
+
   // determine number of rays per component according to its area
   // determine number of rays per component according to its area
   VectorXd area_per_component;
   VectorXd area_per_component;
   area_per_component.setZero(num_cc);
   area_per_component.setZero(num_cc);
@@ -80,7 +80,7 @@ IGL_INLINE void igl::embree::reorient_facets_raycast(
     num_rays_per_component(c) = max<int>(static_cast<int>(rays_total * area_per_component(c) / area_total), rays_minimum);
     num_rays_per_component(c) = max<int>(static_cast<int>(rays_total * area_per_component(c) / area_total), rays_minimum);
   }
   }
   rays_total = num_rays_per_component.sum();
   rays_total = num_rays_per_component.sum();
-  
+
   // generate all the rays
   // generate all the rays
   if (is_verbose) cout << "generating rays... ";
   if (is_verbose) cout << "generating rays... ";
   uniform_real_distribution<float> rdist;
   uniform_real_distribution<float> rdist;
@@ -147,12 +147,12 @@ IGL_INLINE void igl::embree::reorient_facets_raycast(
     }
     }
   }
   }
   if (is_verbose) cout << ray_face.size()  << " rays. ";
   if (is_verbose) cout << ray_face.size()  << " rays. ";
-  
+
   // per component voting: first=front, second=back
   // per component voting: first=front, second=back
   vector<pair<float, float>> C_vote_distance(num_cc, make_pair(0, 0));      // sum of distance between ray origin and intersection
   vector<pair<float, float>> C_vote_distance(num_cc, make_pair(0, 0));      // sum of distance between ray origin and intersection
   vector<pair<int  , int  >> C_vote_infinity(num_cc, make_pair(0, 0));      // number of rays reaching infinity
   vector<pair<int  , int  >> C_vote_infinity(num_cc, make_pair(0, 0));      // number of rays reaching infinity
   vector<pair<int  , int  >> C_vote_parity(num_cc, make_pair(0, 0));        // sum of parity count for each ray
   vector<pair<int  , int  >> C_vote_parity(num_cc, make_pair(0, 0));        // sum of parity count for each ray
-  
+
   if (is_verbose) cout << "shooting rays... ";
   if (is_verbose) cout << "shooting rays... ";
 #pragma omp parallel for
 #pragma omp parallel for
   for (int i = 0; i < (int)ray_face.size(); ++i)
   for (int i = 0; i < (int)ray_face.size(); ++i)
@@ -161,7 +161,7 @@ IGL_INLINE void igl::embree::reorient_facets_raycast(
     Vector3f o = ray_ori [i];
     Vector3f o = ray_ori [i];
     Vector3f d = ray_dir [i];
     Vector3f d = ray_dir [i];
     int c = C(f);
     int c = C(f);
-    
+
     // shoot ray toward front & back
     // shoot ray toward front & back
     vector<Hit> hits_front;
     vector<Hit> hits_front;
     vector<Hit> hits_back;
     vector<Hit> hits_back;
@@ -171,13 +171,13 @@ IGL_INLINE void igl::embree::reorient_facets_raycast(
     ei.intersectRay(o, -d, hits_back , num_rays_back );
     ei.intersectRay(o, -d, hits_back , num_rays_back );
     if (!hits_front.empty() && hits_front[0].id == f) hits_front.erase(hits_front.begin());
     if (!hits_front.empty() && hits_front[0].id == f) hits_front.erase(hits_front.begin());
     if (!hits_back .empty() && hits_back [0].id == f) hits_back .erase(hits_back .begin());
     if (!hits_back .empty() && hits_back [0].id == f) hits_back .erase(hits_back .begin());
-    
+
     if (use_parity) {
     if (use_parity) {
 #pragma omp atomic
 #pragma omp atomic
       C_vote_parity[c].first  += hits_front.size() % 2;
       C_vote_parity[c].first  += hits_front.size() % 2;
 #pragma omp atomic
 #pragma omp atomic
       C_vote_parity[c].second += hits_back .size() % 2;
       C_vote_parity[c].second += hits_back .size() % 2;
-    
+
     } else {
     } else {
       if (hits_front.empty())
       if (hits_front.empty())
       {
       {
@@ -187,7 +187,7 @@ IGL_INLINE void igl::embree::reorient_facets_raycast(
 #pragma omp atomic
 #pragma omp atomic
         C_vote_distance[c].first += hits_front[0].t;
         C_vote_distance[c].first += hits_front[0].t;
       }
       }
-    
+
       if (hits_back.empty())
       if (hits_back.empty())
       {
       {
 #pragma omp atomic
 #pragma omp atomic
@@ -198,14 +198,14 @@ IGL_INLINE void igl::embree::reorient_facets_raycast(
       }
       }
     }
     }
   }
   }
-  
+
   I.resize(m);
   I.resize(m);
   for(int f = 0; f < m; ++f)
   for(int f = 0; f < m; ++f)
   {
   {
     int c = C(f);
     int c = C(f);
     if (use_parity) {
     if (use_parity) {
       I(f) = C_vote_parity[c].first > C_vote_parity[c].second ? 1 : 0;      // Ideally, parity for the front/back side should be 1/0 (i.e., parity sum for all rays should be smaller on the front side)
       I(f) = C_vote_parity[c].first > C_vote_parity[c].second ? 1 : 0;      // Ideally, parity for the front/back side should be 1/0 (i.e., parity sum for all rays should be smaller on the front side)
-    
+
     } else {
     } else {
       I(f) = (C_vote_infinity[c].first == C_vote_infinity[c].second && C_vote_distance[c].first <  C_vote_distance[c].second) ||
       I(f) = (C_vote_infinity[c].first == C_vote_infinity[c].second && C_vote_distance[c].first <  C_vote_distance[c].second) ||
               C_vote_infinity[c].first <  C_vote_infinity[c].second
               C_vote_infinity[c].first <  C_vote_infinity[c].second
@@ -219,8 +219,8 @@ IGL_INLINE void igl::embree::reorient_facets_raycast(
 }
 }
 
 
 template <
 template <
-  typename DerivedV, 
-  typename DerivedF, 
+  typename DerivedV,
+  typename DerivedF,
   typename DerivedFF,
   typename DerivedFF,
   typename DerivedI>
   typename DerivedI>
 IGL_INLINE void igl::embree::reorient_facets_raycast(
 IGL_INLINE void igl::embree::reorient_facets_raycast(
@@ -255,4 +255,5 @@ IGL_INLINE void igl::embree::reorient_facets_raycast(
 // Explicit template specialization
 // Explicit template specialization
 template void igl::embree::reorient_facets_raycast<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::embree::reorient_facets_raycast<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::embree::reorient_facets_raycast<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, int, int, bool, bool, bool, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::embree::reorient_facets_raycast<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, int, int, bool, bool, bool, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+template void igl::embree::reorient_facets_raycast<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, int, int, bool, bool, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 #endif
 #endif

+ 24 - 8
include/igl/extract_manifold_patches.cpp

@@ -1,18 +1,20 @@
 #include "extract_manifold_patches.h"
 #include "extract_manifold_patches.h"
+#include "unique_edge_map.h"
 #include <cassert>
 #include <cassert>
 #include <limits>
 #include <limits>
 #include <queue>
 #include <queue>
 
 
 template<
 template<
-typename DerivedF,
-typename DerivedEMAP,
-typename uE2EType,
-typename DerivedP>
+  typename DerivedF,
+  typename DerivedEMAP,
+  typename uE2EType,
+  typename DerivedP>
 IGL_INLINE size_t igl::extract_manifold_patches(
 IGL_INLINE size_t igl::extract_manifold_patches(
-        const Eigen::PlainObjectBase<DerivedF>& F,
-        const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
-        const std::vector<std::vector<uE2EType> >& uE2E,
-        Eigen::PlainObjectBase<DerivedP>& P) {
+  const Eigen::PlainObjectBase<DerivedF>& F,
+  const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
+  const std::vector<std::vector<uE2EType> >& uE2E,
+  Eigen::PlainObjectBase<DerivedP>& P) 
+{
     assert(F.cols() == 3);
     assert(F.cols() == 3);
     const size_t num_faces = F.rows();
     const size_t num_faces = F.rows();
 
 
@@ -67,6 +69,20 @@ IGL_INLINE size_t igl::extract_manifold_patches(
     return num_patches;
     return num_patches;
 }
 }
 
 
+template<
+  typename DerivedF,
+  typename DerivedP>
+IGL_INLINE size_t igl::extract_manifold_patches(
+  const Eigen::PlainObjectBase<DerivedF>& F,
+  Eigen::PlainObjectBase<DerivedP>& P) 
+{
+  Eigen::MatrixXi E, uE;
+  Eigen::VectorXi EMAP;
+  std::vector<std::vector<size_t> > uE2E;
+  igl::unique_edge_map(F, E, uE, EMAP, uE2E);
+  return igl::extract_manifold_patches(F, EMAP, uE2E, P);
+}
+
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
 template unsigned long igl::extract_manifold_patches<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, unsigned long, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, std::vector<std::vector<unsigned long, std::allocator<unsigned long> >, std::allocator<std::vector<unsigned long, std::allocator<unsigned long> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template unsigned long igl::extract_manifold_patches<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, unsigned long, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, std::vector<std::vector<unsigned long, std::allocator<unsigned long> >, std::allocator<std::vector<unsigned long, std::allocator<unsigned long> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 #endif
 #endif

+ 6 - 0
include/igl/extract_manifold_patches.h

@@ -30,6 +30,12 @@ namespace igl {
       const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
       const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
       const std::vector<std::vector<uE2EType> >& uE2E,
       const std::vector<std::vector<uE2EType> >& uE2E,
       Eigen::PlainObjectBase<DerivedP>& P);
       Eigen::PlainObjectBase<DerivedP>& P);
+    template <
+      typename DerivedF,
+      typename DerivedP>
+    IGL_INLINE size_t extract_manifold_patches(
+      const Eigen::PlainObjectBase<DerivedF>& F,
+      Eigen::PlainObjectBase<DerivedP>& P);
 }
 }
 #ifndef IGL_STATIC_LIBRARY
 #ifndef IGL_STATIC_LIBRARY
 #  include "extract_manifold_patches.cpp"
 #  include "extract_manifold_patches.cpp"

+ 2 - 1
include/igl/fit_rotations.cpp

@@ -71,7 +71,7 @@ IGL_INLINE void igl::fit_rotations_planar(
   using namespace std;
   using namespace std;
   const int dim = S.cols();
   const int dim = S.cols();
   const int nr = S.rows()/dim;
   const int nr = S.rows()/dim;
-  assert(dim == 2 && "_planar input should be 2D");
+  //assert(dim == 2 && "_planar input should be 2D");
   assert(nr * dim == S.rows());
   assert(nr * dim == S.rows());
 
 
   // resize output
   // resize output
@@ -105,6 +105,7 @@ IGL_INLINE void igl::fit_rotations_planar(
 #endif  
 #endif  
 
 
     // Not sure why polar_dec computes transpose...
     // Not sure why polar_dec computes transpose...
+    R.block(0,r*dim,dim,dim).setIdentity();
     R.block(0,r*dim,2,2) = ri.transpose();
     R.block(0,r*dim,2,2) = ri.transpose();
   }
   }
 }
 }

+ 81 - 0
include/igl/flood_fill.cpp

@@ -0,0 +1,81 @@
+#include "flood_fill.h"
+#include <limits>
+
+IGL_INLINE void igl::flood_fill(
+  const Eigen::RowVector3i & res,
+  Eigen::VectorXd & S)
+{
+  using namespace Eigen;
+  using namespace std;
+  const auto flood = [&res,&S] (
+     const int xi, 
+     const int yi, 
+     const int zi,
+     const int signed_xi, 
+     const int signed_yi, 
+     const int signed_zi,
+     const double s)
+    {
+      // flood fill this value back on this row
+      for(int bxi = xi;signed_xi<--bxi;)
+      {
+        S(bxi+res(0)*(yi + res(1)*zi)) = s;
+      }
+      // flood fill this value back on any previous rows
+      for(int byi = yi;signed_yi<--byi;)
+      {
+        for(int xi = 0;xi<res(0);xi++)
+        {
+          S(xi+res(0)*(byi + res(1)*zi)) = s;
+        }
+      }
+      // flood fill this value back on any previous "sheets"
+      for(int bzi = zi;signed_zi<--bzi;)
+      {
+        for(int yi = 0;yi<res(1);yi++)
+        {
+          for(int xi = 0;xi<res(0);xi++)
+          {
+            S(xi+res(0)*(yi + res(1)*bzi)) = s;
+          }
+        }
+      }
+    };
+  int signed_zi = -1;
+  double s = numeric_limits<double>::quiet_NaN();
+  for(int zi = 0;zi<res(2);zi++)
+  {
+    int signed_yi = -1;
+    if(zi != 0)
+    {
+      s = S(0+res(0)*(0 + res(1)*(zi-1)));
+    }
+    for(int yi = 0;yi<res(1);yi++)
+    {
+      // index of last signed item on this row
+      int signed_xi = -1;
+      if(yi != 0)
+      {
+        s = S(0+res(0)*(yi-1 + res(1)*zi));
+      }
+      for(int xi = 0;xi<res(0);xi++)
+      {
+        int i = xi+res(0)*(yi + res(1)*zi);
+        if(S(i)!=S(i))
+        {
+          if(s == s)
+          {
+            S(i) = s;
+          }
+          continue;
+        }
+        s = S(i);
+        flood(xi,yi,zi,signed_xi,signed_yi,signed_zi,s);
+        // remember this position
+        signed_xi = xi;
+        signed_yi = yi;
+        signed_zi = zi;
+      }
+    }
+  }
+}

+ 23 - 0
include/igl/flood_fill.h

@@ -0,0 +1,23 @@
+#ifndef IGL_FLOOD_FILL_H
+#define IGL_FLOOD_FILL_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+namespace igl
+{
+  // Given a 3D array with sparse non-nan (number?) data fill in the NaNs via
+  // flood fill. This should ensure that, e.g., if data near 0 always has a band
+  // (surface) of numbered and signed data, then components of nans will be
+  // correctly signed.
+  //
+  // Inputs:
+  //   res  3-long list of dimensions of grid
+  //   S  res(0)*res(1)*res(2)  list of scalar values (with (many) nans), see
+  //     output
+  // Outputs:
+  //   S  flood fill data in place
+  IGL_INLINE void flood_fill(const Eigen::RowVector3i& res, Eigen::VectorXd& S);
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "flood_fill.cpp"
+#endif
+#endif

+ 23 - 0
include/igl/grid.cpp

@@ -0,0 +1,23 @@
+#include "grid.h"
+
+IGL_INLINE void igl::grid(const Eigen::RowVector3i & res, Eigen::MatrixXd & GV)
+{
+  using namespace Eigen;
+  GV.resize(res(0)*res(1)*res(2),3);
+  for(int zi = 0;zi<res(2);zi++)
+  {
+    const auto lerp = 
+      [&](const double di, const int d)->double{return di/(double)(res(d)-1);};
+    const double z = lerp(zi,2);
+    for(int yi = 0;yi<res(1);yi++)
+    {
+      const double y = lerp(yi,1);
+      for(int xi = 0;xi<res(0);xi++)
+      {
+        const double x = lerp(xi,0);
+        GV.row(xi+res(0)*(yi + res(1)*zi)) = RowVector3d(x,y,z);
+      }
+    }
+  }
+}
+

+ 20 - 0
include/igl/grid.h

@@ -0,0 +1,20 @@
+#ifndef IGL_GRID_H
+#define IGL_GRID_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+namespace igl
+{
+  // Construct vertices of a regular grid, suitable for input to
+  // `igl::marching_cubes`
+  //
+  // Inputs:
+  //   res  3-long list of number of vertices along the x y and z dimensions
+  // Outputs:
+  //   GV  res(0)*res(1)*res(2) by 3 list of mesh vertex positions.
+  //   
+  IGL_INLINE void grid(const Eigen::RowVector3i & res, Eigen::MatrixXd & GV);
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "grid.cpp"
+#endif
+#endif 

+ 1 - 1
include/igl/infinite_cost_stopping_condition.cpp

@@ -55,7 +55,7 @@ IGL_INLINE void igl::infinite_cost_stopping_condition(
       Eigen::RowVectorXd p;
       Eigen::RowVectorXd p;
       double cost;
       double cost;
       cost_and_placement(e,V,F,E,EMAP,EF,EI,cost,p);
       cost_and_placement(e,V,F,E,EMAP,EF,EI,cost,p);
-      return isinf(cost);
+      return std::isinf(cost);
     };
     };
 }
 }
 
 

+ 13 - 21
include/igl/internal_angles.cpp

@@ -8,6 +8,7 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "internal_angles.h"
 #include "internal_angles.h"
 #include "edge_lengths.h"
 #include "edge_lengths.h"
+#include "parallel_for.h"
 #include "get_seconds.h"
 #include "get_seconds.h"
 
 
 template <typename DerivedV, typename DerivedF, typename DerivedK>
 template <typename DerivedV, typename DerivedF, typename DerivedK>
@@ -70,28 +71,19 @@ IGL_INLINE void igl::internal_angles(
   assert(L.cols() == 3 && "Edge-lengths should come from triangles");
   assert(L.cols() == 3 && "Edge-lengths should come from triangles");
   const Index m = L.rows();
   const Index m = L.rows();
   K.resize(m,3);
   K.resize(m,3);
-  //for(int d = 0;d<3;d++)
-  //{
-  //  const auto & s1 = L.col(d).array();
-  //  const auto & s2 = L.col((d+1)%3).array();
-  //  const auto & s3 = L.col((d+2)%3).array();
-  //  K.col(d) = ((s3.square() + s2.square() - s1.square())/(2.*s3*s2)).acos();
-  //}
-  // Minimum number of iterms per openmp thread
-  #ifndef IGL_OMP_MIN_VALUE
-  #  define IGL_OMP_MIN_VALUE 1000
-  #endif
-  #pragma omp parallel for if (m>IGL_OMP_MIN_VALUE)
-  for(Index f = 0;f<m;f++)
-  {
-    for(size_t d = 0;d<3;d++)
+  parallel_for(
+    m,
+    [&L,&K](const Index f)
     {
     {
-      const auto & s1 = L(f,d);
-      const auto & s2 = L(f,(d+1)%3);
-      const auto & s3 = L(f,(d+2)%3);
-      K(f,d) = acos((s3*s3 + s2*s2 - s1*s1)/(2.*s3*s2));
-    }
-  }
+      for(size_t d = 0;d<3;d++)
+      {
+        const auto & s1 = L(f,d);
+        const auto & s2 = L(f,(d+1)%3);
+        const auto & s3 = L(f,(d+2)%3);
+        K(f,d) = acos((s3*s3 + s2*s2 - s1*s1)/(2.*s3*s2));
+      }
+    },
+    1000l);
 }
 }
 
 
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY

+ 11 - 0
include/igl/list_to_matrix.cpp

@@ -118,6 +118,16 @@ IGL_INLINE bool igl::list_to_matrix(const std::vector<T > & V,Eigen::PlainObject
 
 
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // Explicit template specialization
+// generated by autoexplicit.sh
+template bool igl::list_to_matrix<int, Eigen::Matrix<int, -1, 2, 0, -1, 2> >(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&);
+// generated by autoexplicit.sh
+template bool igl::list_to_matrix<double, Eigen::Matrix<double, -1, 2, 0, -1, 2> >(std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&);
+// generated by autoexplicit.sh
+template bool igl::list_to_matrix<double, Eigen::Matrix<double, 4, 1, 0, 4, 1> >(std::vector<double, std::allocator<double> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 4, 1, 0, 4, 1> >&);
+// generated by autoexplicit.sh
+template bool igl::list_to_matrix<double, Eigen::Matrix<double, 3, 1, 0, 3, 1> >(std::vector<double, std::allocator<double> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >&);
+// generated by autoexplicit.sh
+template bool igl::list_to_matrix<double, Eigen::Matrix<double, 2, 1, 0, 2, 1> >(std::vector<double, std::allocator<double> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 2, 1, 0, 2, 1> >&);
 template bool igl::list_to_matrix<double, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
 template bool igl::list_to_matrix<double, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
 template bool igl::list_to_matrix<double, Eigen::Matrix<double, -1, 3, 1, -1, 3> >(std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> >&);
 template bool igl::list_to_matrix<double, Eigen::Matrix<double, -1, 3, 1, -1, 3> >(std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> >&);
 template bool igl::list_to_matrix<double, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 template bool igl::list_to_matrix<double, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
@@ -146,5 +156,6 @@ template bool igl::list_to_matrix<double, Eigen::Matrix<double, -1, -1, 0, -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> >&);
 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> >&);
 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> >&);
 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> >&);
 template bool igl::list_to_matrix<unsigned long, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::vector<unsigned long, std::allocator<unsigned long> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template bool igl::list_to_matrix<unsigned long, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::vector<unsigned long, std::allocator<unsigned long> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template bool igl::list_to_matrix<unsigned __int64, class Eigen::Matrix<int, -1, -1, 0, -1, -1> >(class std::vector<unsigned __int64, class std::allocator<unsigned __int64> > const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1> > &);
 #endif
 #endif
 #endif
 #endif

+ 185 - 0
include/igl/parallel_for.h

@@ -0,0 +1,185 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_PARALLEL_FOR_H
+#define IGL_PARALLEL_FOR_H
+#include "igl_inline.h"
+#include <functional>
+
+namespace igl
+{
+  // PARALLEL_FOR Functional implementation of a basic, open-mp style, parallel
+  // for loop. If the inner block of a for-loop can be rewritten/encapsulated in
+  // a single (anonymous/lambda) function call `func` so that the serial code
+  // looks like:
+  // 
+  //     for(int i = 0;i<loop_size;i++)
+  //     {
+  //       func(i);
+  //     }
+  //
+  // then `parallel_for(loop_size,func,min_parallel)` will use as many threads as
+  // available on the current hardware to parallelize this for loop so long as
+  // loop_size<min_parallel, otherwise it will just use a serial for loop.
+  //
+  // Inputs:
+  //   loop_size  number of iterations. I.e. for(int i = 0;i<loop_size;i++) ...
+  //   func  function handle taking iteration index as only arguement to compute
+  //     inner block of for loop I.e. for(int i ...){ func(i); }
+  //   min_parallel  min size of loop_size such that parallel (non-serial)
+  //     thread pooling should be attempted {0}
+  // Returns true iff thread pool was invoked
+  template<typename Index, typename FunctionType >
+  inline bool parallel_for(
+    const Index loop_size, 
+    const FunctionType & func,
+    const size_t min_parallel=0);
+  // PARALLEL_FOR Functional implementation of an open-mp style, parallel for
+  // loop with accumulation. For example, serial code separated into n chunks
+  // (each to be parallelized with a thread) might look like:
+  //     
+  //     Eigen::VectorXd S;
+  //     const auto & prep_func = [&S](int n){ S = Eigen:VectorXd::Zero(n); };
+  //     const auto & func = [&X,&S](int i, int t){ S(t) += X(i); };
+  //     const auto & accum_func = [&S,&sum](int t){ sum += S(t); };
+  //     prep_func(n);
+  //     for(int i = 0;i<loop_size;i++)
+  //     {
+  //       func(i,i%n);
+  //     }
+  //     double sum = 0;
+  //     for(int t = 0;t<n;t++)
+  //     {
+  //       accum_func(t);
+  //     }
+  // 
+  // Inputs:
+  //   loop_size  number of iterations. I.e. for(int i = 0;i<loop_size;i++) ...
+  //   prep_func function handle taking n >= number of threads as only
+  //     argument 
+  //   func  function handle taking iteration index i and thread id t as only
+  //     arguements to compute inner block of for loop I.e. 
+  //     for(int i ...){ func(i,t); }
+  //   accum_func  function handle taking thread index as only argument, to be
+  //     called after all calls of func, e.g., for serial accumulation across
+  //     all n (potential) threads, see n in description of prep_func.
+  //   min_parallel  min size of loop_size such that parallel (non-serial)
+  //     thread pooling should be attempted {0}
+  // Returns true iff thread pool was invoked
+  template<
+    typename Index, 
+    typename PrepFunctionType, 
+    typename FunctionType, 
+    typename AccumFunctionType 
+    >
+  inline bool parallel_for(
+    const Index loop_size, 
+    const PrepFunctionType & prep_func,
+    const FunctionType & func,
+    const AccumFunctionType & accum_func,
+    const size_t min_parallel=0);
+}
+
+// Implementation
+
+#include <cmath>
+#include <cassert>
+#include <thread>
+#include <vector>
+#include <algorithm>
+
+template<typename Index, typename FunctionType >
+inline bool igl::parallel_for(
+  const Index loop_size, 
+  const FunctionType & func,
+  const size_t min_parallel)
+{
+  using namespace std;
+  // no op preparation/accumulation
+  const auto & no_op = [](const size_t /*n/t*/){};
+  // two-parameter wrapper ignoring thread id
+  const auto & wrapper = [&func](Index i,size_t /*t*/){ func(i); };
+  return parallel_for(loop_size,no_op,wrapper,no_op,min_parallel);
+}
+
+template<
+  typename Index, 
+  typename PreFunctionType,
+  typename FunctionType, 
+  typename AccumFunctionType>
+inline bool igl::parallel_for(
+  const Index loop_size, 
+  const PreFunctionType & prep_func,
+  const FunctionType & func,
+  const AccumFunctionType & accum_func,
+  const size_t min_parallel)
+{
+  assert(loop_size>=0);
+  if(loop_size==0) return false;
+  // Estimate number of threads in the pool
+  // http://ideone.com/Z7zldb
+  const static size_t sthc = std::thread::hardware_concurrency();
+  const size_t nthreads = 
+#ifdef IGL_PARALLEL_FOR_FORCE_SERIAL
+    0;
+#else
+    loop_size<min_parallel?0:(sthc==0?8:sthc);
+#endif
+  if(nthreads==0)
+  {
+    // serial
+    prep_func(1);
+    for(Index i = 0;i<loop_size;i++) func(i,0);
+    accum_func(0);
+    return false;
+  }else
+  {
+    // Size of a slice for the range functions
+    Index slice = 
+      std::max(
+        (Index)std::round((loop_size+1)/static_cast<double>(nthreads)),(Index)1);
+ 
+    // [Helper] Inner loop
+    const auto & range = [&func](const Index k1, const Index k2, const size_t t)
+    {
+      for(Index k = k1; k < k2; k++) func(k,t);
+    };
+    prep_func(nthreads);
+    // Create pool and launch jobs
+    std::vector<std::thread> pool;
+    pool.reserve(nthreads);
+    // Inner range extents
+    Index i1 = 0;
+    Index i2 = std::min(0 + slice, loop_size);
+    {
+      size_t t = 0;
+      for (; t+1 < nthreads && i1 < loop_size; ++t)
+      {
+        pool.emplace_back(range, i1, i2, t);
+        i1 = i2;
+        i2 = std::min(i2 + slice, loop_size);
+      }
+      if (i1 < loop_size)
+      {
+        pool.emplace_back(range, i1, loop_size, t);
+      }
+    }
+    // Wait for jobs to finish
+    for (std::thread &t : pool) if (t.joinable()) t.join();
+    // Accumulate across threads
+    for(size_t t = 0;t<nthreads;t++)
+    {
+      accum_func(t);
+    }
+    return true;
+  }
+}
+ 
+//#ifndef IGL_STATIC_LIBRARY
+//#include "parallel_for.cpp"
+//#endif
+#endif

+ 1 - 0
include/igl/parula.cpp

@@ -69,4 +69,5 @@ template void igl::parula<double>(double, double*);
 template void igl::parula<double>(double, double&, double&, double&);
 template void igl::parula<double>(double, double&, double&, double&);
 template void igl::parula<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&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 template void igl::parula<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&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 template void igl::parula<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&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 template void igl::parula<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&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+template void igl::parula<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&, double, double, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 #endif
 #endif

+ 23 - 11
include/igl/per_vertex_normals.cpp

@@ -10,6 +10,7 @@
 #include "get_seconds.h"
 #include "get_seconds.h"
 #include "per_face_normals.h"
 #include "per_face_normals.h"
 #include "doublearea.h"
 #include "doublearea.h"
+#include "parallel_for.h"
 #include "internal_angles.h"
 #include "internal_angles.h"
 
 
 template <typename DerivedV, typename DerivedF>
 template <typename DerivedV, typename DerivedF>
@@ -68,23 +69,34 @@ IGL_INLINE void igl::per_vertex_normals(
   }
   }
 
 
   // loop over faces
   // loop over faces
-  const int Frows = F.rows();
-//// Minimum number of iterms per openmp thread
-//#ifndef IGL_OMP_MIN_VALUE
-//#  define IGL_OMP_MIN_VALUE 1000
-//#endif
-//#pragma omp parallel for if (Frows>IGL_OMP_MIN_VALUE)
-  for(int i = 0; i < Frows;i++)
+  for(int i = 0;i<F.rows();i++)
   {
   {
     // throw normal at each corner
     // throw normal at each corner
     for(int j = 0; j < 3;j++)
     for(int j = 0; j < 3;j++)
     {
     {
-      // Q: Does this need to be critical?
-      // A: Yes. Different (i,j)'s could produce the same F(i,j)
-//#pragma omp critical
-      N.row(F(i,j)) += W(i,j)*FN.row(i);
+      N.row(F(i,j)) += W(i,j) * FN.row(i);
     }
     }
   }
   }
+
+  //// loop over faces
+  //std::mutex critical;
+  //std::vector<DerivedN> NN;
+  //parallel_for(
+  //  F.rows(),
+  //  [&NN,&N](const size_t n){ NN.resize(n,DerivedN::Zero(N.rows(),3));},
+  //  [&F,&W,&FN,&NN,&critical](const int i, const size_t t)
+  //  {
+  //    // throw normal at each corner
+  //    for(int j = 0; j < 3;j++)
+  //    {
+  //      // Q: Does this need to be critical?
+  //      // A: Yes. Different (i,j)'s could produce the same F(i,j)
+  //      NN[t].row(F(i,j)) += W(i,j) * FN.row(i);
+  //    }
+  //  },
+  //  [&N,&NN](const size_t t){ N += NN[t]; },
+  //  1000l);
+
   // take average via normalization
   // take average via normalization
   N.rowwise().normalize();
   N.rowwise().normalize();
 }
 }

+ 47 - 0
include/igl/png/readPNG.cpp

@@ -0,0 +1,47 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2016 Daniele Panozzo <daniele.panozzo@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 "readPNG.h"
+#include <stb_image.h>
+
+IGL_INLINE bool igl::png::readPNG(
+  const std::string png_file,
+  Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& R,
+  Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& G,
+  Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& B,
+  Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& A
+)
+{
+  int cols,rows,n;
+  unsigned char *data = stbi_load(png_file.c_str(), &cols, &rows, &n, 4);
+  if(data == NULL) {
+    return false;
+  }
+
+  R.resize(cols,rows);
+  G.resize(cols,rows);
+  B.resize(cols,rows);
+  A.resize(cols,rows);
+
+  for (unsigned i=0; i<rows; ++i) {
+    for (unsigned j=0; j<cols; ++j) {
+      R(j,rows-1-i) = data[4*(j + cols * i) + 0];
+      G(j,rows-1-i) = data[4*(j + cols * i) + 1];
+      B(j,rows-1-i) = data[4*(j + cols * i) + 2];
+      A(j,rows-1-i) = data[4*(j + cols * i) + 3];
+    }
+  }
+
+  stbi_image_free(data);
+
+  return true;
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template specialization
+// generated by autoexplicit.sh
+#endif

+ 39 - 0
include/igl/png/readPNG.h

@@ -0,0 +1,39 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2016 Daniele Panozzo <daniele.panozzo@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_PNG_READ_PNG_H
+#define IGL_PNG_READ_PNG_H
+#include "../igl_inline.h"
+#include <Eigen/Core>
+#include <string>
+
+namespace igl
+{
+  namespace png
+  {
+    // Read an image from a .png file into 4 memory buffers
+    //
+    // Input:
+    //  png_file  path to .png file
+    // Output:
+    //  R,G,B,A texture channels
+    // Returns true on success, false on failure
+    //
+    IGL_INLINE bool readPNG(const std::string png_file,
+    Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& R,
+    Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& G,
+    Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& B,
+    Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& A
+    );
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "readPNG.cpp"
+#endif
+
+#endif

+ 46 - 0
include/igl/png/writePNG.cpp

@@ -0,0 +1,46 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2016 Daniele Panozzo <daniele.panozzo@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 "writePNG.h"
+#include <stb_image_write.h>
+#include <vector>
+
+IGL_INLINE bool igl::png::writePNG(
+  const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& R,
+  const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& G,
+  const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& B,
+  const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& A,
+  const std::string png_file
+)
+{
+  assert((R.rows() == G.rows()) && (G.rows() == B.rows()) && (B.rows() == A.rows()));
+  assert((R.cols() == G.cols()) && (G.cols() == B.cols()) && (B.cols() == A.cols()));
+
+  const int comp = 4;                                  // 4 Channels Red, Green, Blue, Alpha
+  const int stride_in_bytes = R.rows()*comp;           // Lenght of one row in bytes
+  std::vector<unsigned char> data(R.size()*comp,0);     // The image itself;
+
+  for (unsigned i = 0; i<R.rows();++i)
+  {
+    for (unsigned j = 0; j < R.cols(); ++j)
+    {
+        data[(j * R.rows() * comp) + (i * comp) + 0] = R(i,R.cols()-1-j);
+        data[(j * R.rows() * comp) + (i * comp) + 1] = G(i,R.cols()-1-j);
+        data[(j * R.rows() * comp) + (i * comp) + 2] = B(i,R.cols()-1-j);
+        data[(j * R.rows() * comp) + (i * comp) + 3] = A(i,R.cols()-1-j);
+    }
+  }
+
+  stbi_write_png(png_file.c_str(), R.rows(), R.cols(), comp, data.data(), stride_in_bytes);
+
+  return true;
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template specialization
+// generated by autoexplicit.sh
+#endif

+ 41 - 0
include/igl/png/writePNG.h

@@ -0,0 +1,41 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2016 Daniele Panozzo <daniele.panozzo@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_PNG_WRITE_PNG_H
+#define IGL_PNG_WRITE_PNG_H
+#include "../igl_inline.h"
+#include <Eigen/Core>
+#include <string>
+
+namespace igl
+{
+  namespace png
+  {
+    // Writes an image to a png file
+    //
+    // Input:
+    //  R,G,B,A texture channels
+    // Output:
+    //  png_file  path to .png file
+    // Returns true on success, false on failure
+    //
+    IGL_INLINE bool writePNG
+    (
+      const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& R,
+      const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& G,
+      const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& B,
+      const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& A,
+      const std::string png_file
+    );
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "writePNG.cpp"
+#endif
+
+#endif

+ 2 - 0
include/igl/project_to_line.cpp

@@ -120,6 +120,8 @@ IGL_INLINE void igl::project_to_line(
 
 
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // Explicit template specialization
+// generated by autoexplicit.sh
+template void igl::project_to_line<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::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<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<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&);
 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<double>(double, double, double, double, double, double, double, double, double, double&, double&,double&,double&, double&);
 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> >&);
 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> >&);

+ 2 - 0
include/igl/project_to_line_segment.cpp

@@ -43,5 +43,7 @@ IGL_INLINE void igl::project_to_line_segment(
 
 
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // Explicit template specialization
+// generated by autoexplicit.sh
+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::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<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, 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> >&);
 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
 #endif

+ 6 - 6
include/igl/random_dir.cpp

@@ -1,9 +1,9 @@
 // This file is part of libigl, a simple c++ geometry processing library.
 // This file is part of libigl, a simple c++ geometry processing library.
-// 
+//
 // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
 // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
 // obtain one at http://mozilla.org/MPL/2.0/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "random_dir.h"
 #include "random_dir.h"
 #include <igl/PI.h>
 #include <igl/PI.h>
@@ -18,14 +18,14 @@ IGL_INLINE Eigen::Vector3d igl::random_dir()
   double r = sqrt(1.0-z*z);
   double r = sqrt(1.0-z*z);
   double x = r * cos(t);
   double x = r * cos(t);
   double y = r * sin(t);
   double y = r * sin(t);
-  return Vector3d(x,y,z); 
+  return Vector3d(x,y,z);
 }
 }
 
 
 IGL_INLINE Eigen::MatrixXd igl::random_dir_stratified(const int n)
 IGL_INLINE Eigen::MatrixXd igl::random_dir_stratified(const int n)
 {
 {
   using namespace Eigen;
   using namespace Eigen;
   using namespace std;
   using namespace std;
-  const double m = floor(sqrt(double(n)));
+  const double m = std::floor(sqrt(double(n)));
   MatrixXd N(n,3);
   MatrixXd N(n,3);
   int row = 0;
   int row = 0;
   for(int i = 0;i<m;i++)
   for(int i = 0;i<m;i++)

+ 27 - 26
include/igl/repdiag.cpp

@@ -18,7 +18,7 @@ IGL_INLINE void igl::repdiag(
   using namespace Eigen;
   using namespace Eigen;
   int m = A.rows();
   int m = A.rows();
   int n = A.cols();
   int n = A.cols();
-
+#if false
   vector<Triplet<T> > IJV;
   vector<Triplet<T> > IJV;
   IJV.reserve(A.nonZeros()*d);
   IJV.reserve(A.nonZeros()*d);
   // Loop outer level
   // Loop outer level
@@ -35,31 +35,32 @@ IGL_INLINE void igl::repdiag(
   }
   }
   B.resize(m*d,n*d);
   B.resize(m*d,n*d);
   B.setFromTriplets(IJV.begin(),IJV.end());
   B.setFromTriplets(IJV.begin(),IJV.end());
-  
-
-  // Q: Why is this **Very** slow?
-
-  //int m = A.rows();
-  //int n = A.cols();
-
-  //B.resize(m*d,n*d);
-  //// Reserve enough space for new non zeros
-  //B.reserve(d*A.nonZeros());
-
-  //// loop over reps
-  //for(int i=0;i<d;i++)
-  //{
-  //  // Loop outer level
-  //  for (int k=0; k<A.outerSize(); ++k)
-  //  {
-  //    // loop inner level
-  //    for (typename Eigen::SparseMatrix<T>::InnerIterator it(A,k); it; ++it)
-  //    {
-  //      B.insert(i*m+it.row(),i*n+it.col()) = it.value();
-  //    }
-  //  }
-  //}
-  //B.makeCompressed();
+#else
+  // This will not work for RowMajor
+  B.resize(m*d,n*d);
+  Eigen::VectorXi per_col = Eigen::VectorXi::Zero(n*d);
+  for (int k=0; k<A.outerSize(); ++k)
+  {
+    for (typename Eigen::SparseMatrix<T>::InnerIterator it(A,k); it; ++it)
+    {
+      for(int r = 0;r<d;r++) per_col(n*r + k)++;
+    }
+  }
+  B.reserve(per_col);
+  for(int r = 0;r<d;r++)
+  {
+    const int mr = m*r;
+    const int nr = n*r;
+    for (int k=0; k<A.outerSize(); ++k)
+    {
+      for (typename Eigen::SparseMatrix<T>::InnerIterator it(A,k); it; ++it)
+      {
+        B.insert(it.row()+mr,k+nr) = it.value();
+      }
+    }
+  }
+  B.makeCompressed();
+#endif
 }
 }
 
 
 template <typename T>
 template <typename T>

+ 1 - 0
include/igl/resolve_duplicated_faces.cpp

@@ -86,4 +86,5 @@ IGL_INLINE void igl::resolve_duplicated_faces(
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
 template void igl::resolve_duplicated_faces<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::resolve_duplicated_faces<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::resolve_duplicated_faces<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<long, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&);
 template void igl::resolve_duplicated_faces<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<long, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&);
+template void igl::resolve_duplicated_faces<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 #endif
 #endif

+ 5 - 5
include/igl/round.cpp

@@ -1,9 +1,9 @@
 // This file is part of libigl, a simple c++ geometry processing library.
 // This file is part of libigl, a simple c++ geometry processing library.
-// 
+//
 // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
 // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
 // obtain one at http://mozilla.org/MPL/2.0/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "round.h"
 #include "round.h"
 #include <cmath>
 #include <cmath>
@@ -13,7 +13,7 @@
 template <typename DerivedX >
 template <typename DerivedX >
 IGL_INLINE DerivedX igl::round(const DerivedX r)
 IGL_INLINE DerivedX igl::round(const DerivedX r)
 {
 {
-  return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);
+  return (r > 0.0) ? std::floor(r + 0.5) : std::ceil(r - 0.5);
 }
 }
 
 
 template < typename DerivedX, typename DerivedY>
 template < typename DerivedX, typename DerivedY>

+ 2 - 0
include/igl/slice.cpp

@@ -282,4 +282,6 @@ template void igl::slice<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<i
 template void igl::slice<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::Matrix<int, -1, -1, 0, -1, -1>&);
 template void igl::slice<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::Matrix<int, -1, -1, 0, -1, -1>&);
 template void igl::slice<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::Matrix<int, -1, 1, 0, -1, 1>&);
 template void igl::slice<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::Matrix<int, -1, 1, 0, -1, 1>&);
 template void igl::slice<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::slice<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template void igl::slice<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, int, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
+template void igl::slice<Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 #endif
 #endif

+ 5 - 1
include/igl/slice_mask.cpp

@@ -55,8 +55,8 @@ IGL_INLINE void igl::slice_mask(
     case 1:
     case 1:
     {
     {
       const int ym = R.count();
       const int ym = R.count();
-      Y.resize(ym,X.cols());
       assert(X.rows() == R.size() && "X.rows() should match R.size()");
       assert(X.rows() == R.size() && "X.rows() should match R.size()");
+      Y.resize(ym,X.cols());
       {
       {
         int yi = 0;
         int yi = 0;
         for(int i = 0;i<X.rows();i++)
         for(int i = 0;i<X.rows();i++)
@@ -117,4 +117,8 @@ IGL_INLINE DerivedX igl::slice_mask(
 
 
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
 template void igl::slice_mask<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Array<bool, -1, 1, 0, -1, 1> const&, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::slice_mask<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Array<bool, -1, 1, 0, -1, 1> const&, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template void igl::slice_mask<Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Array<bool, -1, 1, 0, -1, 1> const&, Eigen::Array<bool, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+template void igl::slice_mask<Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Array<bool, -1, 1, 0, -1, 1> const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+template void igl::slice_mask<Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Array<bool, -1, 1, 0, -1, 1> const&, Eigen::Array<bool, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+
 #endif
 #endif

+ 69 - 82
include/igl/sort.cpp

@@ -11,12 +11,11 @@
 #include "reorder.h"
 #include "reorder.h"
 #include "IndexComparison.h"
 #include "IndexComparison.h"
 #include "colon.h"
 #include "colon.h"
+#include "parallel_for.h"
 
 
 #include <cassert>
 #include <cassert>
 #include <algorithm>
 #include <algorithm>
 #include <iostream>
 #include <iostream>
-#include <thread>
-#include <functional>
 
 
 template <typename DerivedX, typename DerivedY, typename DerivedIX>
 template <typename DerivedX, typename DerivedY, typename DerivedIX>
 IGL_INLINE void igl::sort(
 IGL_INLINE void igl::sort(
@@ -223,98 +222,86 @@ IGL_INLINE void igl::sort3(
     IX.col(2).setConstant(2);// = Eigen::PlainObjectBase<DerivedIX>::Ones (IX.rows(),1);
     IX.col(2).setConstant(2);// = Eigen::PlainObjectBase<DerivedIX>::Ones (IX.rows(),1);
   }
   }
 
 
-  const int n = num_outer;
-  const size_t nthreads = n<8000?1:std::thread::hardware_concurrency();
+
+  const auto & inner = [&IX,&Y,&dim,&ascending](const Index & i)
   {
   {
-    std::vector<std::thread> threads(nthreads);
-    for(int t = 0;t<nthreads;t++)
+    YScalar & a = (dim==1 ? Y(0,i) : Y(i,0));
+    YScalar & b = (dim==1 ? Y(1,i) : Y(i,1));
+    YScalar & c = (dim==1 ? Y(2,i) : Y(i,2));
+    Index & ai = (dim==1 ? IX(0,i) : IX(i,0));
+    Index & bi = (dim==1 ? IX(1,i) : IX(i,1));
+    Index & ci = (dim==1 ? IX(2,i) : IX(i,2));
+    if(ascending)
+    {
+      // 123 132 213 231 312 321
+      if(a > b)
+      {
+        std::swap(a,b);
+        std::swap(ai,bi);
+      }
+      // 123 132 123 231 132 231
+      if(b > c)
+      {
+        std::swap(b,c);
+        std::swap(bi,ci);
+        // 123 123 123 213 123 213
+        if(a > b)
+        {
+          std::swap(a,b);
+          std::swap(ai,bi);
+        }
+        // 123 123 123 123 123 123
+      }
+    }else
     {
     {
-      threads[t] = std::thread(std::bind(
-        [&X,&Y,&IX,&dim,&ascending](const int bi, const int ei, const int t)
+      // 123 132 213 231 312 321
+      if(a < b)
       {
       {
-        // loop over columns (or rows)
-        for(int i = bi;i<ei;i++)
+        std::swap(a,b);
+        std::swap(ai,bi);
+      }
+      // 213 312 213 321 312 321
+      if(b < c)
+      {
+        std::swap(b,c);
+        std::swap(bi,ci);
+        // 231 321 231 321 321 321
+        if(a < b)
         {
         {
-          YScalar & a = (dim==1 ? Y(0,i) : Y(i,0));
-          YScalar & b = (dim==1 ? Y(1,i) : Y(i,1));
-          YScalar & c = (dim==1 ? Y(2,i) : Y(i,2));
-          Index & ai = (dim==1 ? IX(0,i) : IX(i,0));
-          Index & bi = (dim==1 ? IX(1,i) : IX(i,1));
-          Index & ci = (dim==1 ? IX(2,i) : IX(i,2));
-          if(ascending)
-          {
-            // 123 132 213 231 312 321
-            if(a > b)
-            {
-              std::swap(a,b);
-              std::swap(ai,bi);
-            }
-            // 123 132 123 231 132 231
-            if(b > c)
-            {
-              std::swap(b,c);
-              std::swap(bi,ci);
-              // 123 123 123 213 123 213
-              if(a > b)
-              {
-                std::swap(a,b);
-                std::swap(ai,bi);
-              }
-              // 123 123 123 123 123 123
-            }
-          }else
-          {
-            // 123 132 213 231 312 321
-            if(a < b)
-            {
-              std::swap(a,b);
-              std::swap(ai,bi);
-            }
-            // 213 312 213 321 312 321
-            if(b < c)
-            {
-              std::swap(b,c);
-              std::swap(bi,ci);
-              // 231 321 231 321 321 321
-              if(a < b)
-              {
-                std::swap(a,b);
-                std::swap(ai,bi);
-              }
-              // 321 321 321 321 321 321
-            }
-          }
+          std::swap(a,b);
+          std::swap(ai,bi);
         }
         }
-      }, t*n/nthreads, (t+1)==nthreads?n:(t+1)*n/nthreads,t));
+        // 321 321 321 321 321 321
+      }
     }
     }
-    std::for_each(threads.begin(),threads.end(),[](std::thread& x){x.join();});
-  }
+  };
+  parallel_for(num_outer,inner,16000);
 }
 }
 
 
 template <class T>
 template <class T>
 IGL_INLINE void igl::sort(
 IGL_INLINE void igl::sort(
-  const std::vector<T> & unsorted,
-  const bool ascending,
-  std::vector<T> & sorted,
-  std::vector<size_t> & index_map)
+const std::vector<T> & unsorted,
+const bool ascending,
+std::vector<T> & sorted,
+std::vector<size_t> & index_map)
 {
 {
-  // Original unsorted index map
-  index_map.resize(unsorted.size());
-  for(size_t i=0;i<unsorted.size();i++)
-  {
-    index_map[i] = i;
-  }
-  // Sort the index map, using unsorted for comparison
-  std::sort(
-    index_map.begin(),
-    index_map.end(),
-    igl::IndexLessThan<const std::vector<T>& >(unsorted));
+// Original unsorted index map
+index_map.resize(unsorted.size());
+for(size_t i=0;i<unsorted.size();i++)
+{
+  index_map[i] = i;
+}
+// Sort the index map, using unsorted for comparison
+std::sort(
+  index_map.begin(),
+  index_map.end(),
+  igl::IndexLessThan<const std::vector<T>& >(unsorted));
 
 
-  // if not ascending then reverse
-  if(!ascending)
-  {
-    std::reverse(index_map.begin(),index_map.end());
-  }
+// if not ascending then reverse
+if(!ascending)
+{
+  std::reverse(index_map.begin(),index_map.end());
+}
   // make space for output without clobbering
   // make space for output without clobbering
   sorted.resize(unsorted.size());
   sorted.resize(unsorted.size());
   // reorder unsorted into sorted using index map
   // reorder unsorted into sorted using index map

+ 20 - 0
include/igl/swept_volume_bounding_box.cpp

@@ -0,0 +1,20 @@
+#include "swept_volume_bounding_box.h"
+
+IGL_INLINE void igl::swept_volume_bounding_box(
+  const size_t & n,
+  const std::function<Eigen::RowVector3d(const size_t vi, const double t)> & V,
+  const size_t & steps,
+  Eigen::AlignedBox3d & box)
+{
+  using namespace Eigen;
+  box.setEmpty();
+  const VectorXd t = VectorXd::LinSpaced(steps,0,1);
+  // Find extent over all time steps
+  for(int ti = 0;ti<t.size();ti++)
+  {
+    for(size_t vi = 0;vi<n;vi++)
+    {
+      box.extend(V(vi,t(ti)).transpose());
+    }
+  }
+}

+ 31 - 0
include/igl/swept_volume_bounding_box.h

@@ -0,0 +1,31 @@
+#ifndef IGL_SWEPT_VOLUME_BOUNDING_BOX_H
+#define IGL_SWEPT_VOLUME_BOUNDING_BOX_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+#include <Eigen/Geometry>
+#include <functional>
+namespace igl
+{
+  // Construct an axis-aligned bounding box containing a shape undergoing a
+  // motion sampled at `steps` discrete momements.
+  //
+  // Inputs:
+  //   n  number of mesh vertices
+  //   V  function handle so that V(i,t) returns the 3d position of vertex
+  //     i at time t, for t∈[0,1]
+  //   steps  number of time steps: steps=3 --> t∈{0,0.5,1}
+  // Outputs:
+  //   box  box containing mesh under motion
+  IGL_INLINE void swept_volume_bounding_box(
+    const size_t & n,
+    const std::function<
+      Eigen::RowVector3d(const size_t vi, const double t)> & V,
+    const size_t & steps,
+    Eigen::AlignedBox3d & box);
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "swept_volume_bounding_box.cpp"
+#endif
+
+#endif 

+ 113 - 0
include/igl/swept_volume_signed_distance.cpp

@@ -0,0 +1,113 @@
+#include "swept_volume_signed_distance.h"
+#include "flood_fill.h"
+#include "signed_distance.h"
+#include "AABB.h"
+#include "pseudonormal_test.h"
+#include "per_face_normals.h"
+#include "per_vertex_normals.h"
+#include "per_edge_normals.h"
+#include <Eigen/Geometry>
+#include <cmath>
+
+IGL_INLINE void igl::swept_volume_signed_distance(
+  const Eigen::MatrixXd & V,
+  const Eigen::MatrixXi & F,
+  const std::function<Eigen::Affine3d(const double t)> & transform,
+  const size_t & steps,
+  const Eigen::MatrixXd & GV,
+  const Eigen::RowVector3i & res,
+  const double h,
+  const double isolevel,
+  const Eigen::VectorXd & S0,
+  Eigen::VectorXd & S)
+{
+  using namespace std;
+  using namespace igl;
+  using namespace Eigen;
+  S = S0;
+  const VectorXd t = VectorXd::LinSpaced(steps,0,1);
+  const bool finite_iso = isfinite(isolevel);
+  const double extension = (finite_iso ? isolevel : 0) + sqrt(3.0)*h;
+  Eigen::AlignedBox3d box(
+    V.colwise().minCoeff().array()-extension,
+    V.colwise().maxCoeff().array()+extension);
+  // Precomputation
+  Eigen::MatrixXd FN,VN,EN;
+  Eigen::MatrixXi E;
+  Eigen::VectorXi EMAP;
+  per_face_normals(V,F,FN);
+  per_vertex_normals(V,F,PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE,FN,VN);
+  per_edge_normals(
+    V,F,PER_EDGE_NORMALS_WEIGHTING_TYPE_UNIFORM,FN,EN,E,EMAP);
+  AABB<MatrixXd,3> tree;
+  tree.init(V,F);
+  for(int ti = 0;ti<t.size();ti++)
+  {
+    const Affine3d At = transform(t(ti));
+    for(int g = 0;g<GV.rows();g++)
+    {
+      // Don't bother finding out how deep inside points are.
+      if(finite_iso && S(g)==S(g) && S(g)<isolevel-sqrt(3.0)*h)
+      {
+        continue;
+      }
+      const RowVector3d gv = 
+        (GV.row(g) - At.translation().transpose())*At.linear();
+      // If outside of extended box, then consider it "far away enough"
+      if(finite_iso && !box.contains(gv.transpose()))
+      {
+        continue;
+      }
+      RowVector3d c,n;
+      int i;
+      double sqrd,s;
+      //signed_distance_pseudonormal(tree,V,F,FN,VN,EN,EMAP,gv,s,sqrd,i,c,n);
+      const double min_sqrd = 
+        finite_iso ? 
+        pow(sqrt(3.)*h+isolevel,2) : 
+        numeric_limits<double>::infinity();
+      sqrd = tree.squared_distance(V,F,gv,min_sqrd,i,c);
+      if(sqrd<min_sqrd)
+      {
+        pseudonormal_test(V,F,FN,VN,EN,EMAP,gv,i,c,s,n);
+        if(S(g) == S(g))
+        {
+          S(g) = min(S(g),s*sqrt(sqrd));
+        }else
+        {
+          S(g) = s*sqrt(sqrd);
+        }
+      }
+    }
+  }
+
+  if(finite_iso)
+  {
+    flood_fill(res,S);
+  }else
+  {
+#ifndef NDEBUG
+    // Check for nans
+    for_each(S.data(),S.data()+S.size(),[](const double s){assert(s==s);});
+#endif
+  }
+}
+
+IGL_INLINE void igl::swept_volume_signed_distance(
+  const Eigen::MatrixXd & V,
+  const Eigen::MatrixXi & F,
+  const std::function<Eigen::Affine3d(const double t)> & transform,
+  const size_t & steps,
+  const Eigen::MatrixXd & GV,
+  const Eigen::RowVector3i & res,
+  const double h,
+  const double isolevel,
+  Eigen::VectorXd & S)
+{
+  using namespace std;
+  using namespace igl;
+  using namespace Eigen;
+  S = VectorXd::Constant(GV.rows(),1,numeric_limits<double>::quiet_NaN());
+  return 
+    swept_volume_signed_distance(V,F,transform,steps,GV,res,h,isolevel,S,S);
+}

+ 57 - 0
include/igl/swept_volume_signed_distance.h

@@ -0,0 +1,57 @@
+#ifndef IGL_SWEPT_VOLUME_SIGNED_DISTANCE_H
+#define IGL_SWEPT_VOLUME_SIGNED_DISTANCE_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+#include <Eigen/Geometry>
+#include <functional>
+namespace igl
+{
+  // Compute the signed distance to a sweep surface of a mesh under-going
+  // an arbitrary motion V(t) discretely sampled at `steps`-many moments in
+  // time at a grid.
+  //
+  // Inputs:
+  //   V  #V by 3 list of mesh positions in reference pose
+  //   F  #F by 3 list of triangle indices [0,n)
+  //   transform  function handle so that transform(t) returns the rigid
+  //     transformation at time t∈[0,1]
+  //   steps  number of time steps: steps=3 --> t∈{0,0.5,1}
+  //   GV  #GV by 3 list of evaluation point grid positions
+  //   res  3-long resolution of GV grid
+  //   h  edge-length of grid
+  //   isolevel  isolevel to "focus" on; grid positions far enough away from
+  //     isolevel (based on h) will get approximate values). Set
+  //     isolevel=infinity to get good values everywhere (slow and
+  //     unnecessary if just trying to extract isolevel-level set).
+  //   S0  #GV initial values (will take minimum with these), can be same
+  //     as S)
+  // Outputs:
+  //   S  #GV list of signed distances
+  IGL_INLINE void swept_volume_signed_distance(
+    const Eigen::MatrixXd & V,
+    const Eigen::MatrixXi & F,
+    const std::function<Eigen::Affine3d(const double t)> & transform,
+    const size_t & steps,
+    const Eigen::MatrixXd & GV,
+    const Eigen::RowVector3i & res,
+    const double h,
+    const double isolevel,
+    const Eigen::VectorXd & S0,
+    Eigen::VectorXd & S);
+  IGL_INLINE void swept_volume_signed_distance(
+    const Eigen::MatrixXd & V,
+    const Eigen::MatrixXi & F,
+    const std::function<Eigen::Affine3d(const double t)> & transform,
+    const size_t & steps,
+    const Eigen::MatrixXd & GV,
+    const Eigen::RowVector3i & res,
+    const double h,
+    const double isolevel,
+    Eigen::VectorXd & S);
+  }
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "swept_volume_signed_distance.cpp"
+#endif 
+
+#endif

+ 1 - 1
include/igl/triangle/triangulate.h

@@ -7,7 +7,7 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #ifndef IGL_TRIANGLE_TRIANGULATE_H
 #ifndef IGL_TRIANGLE_TRIANGULATE_H
 #define IGL_TRIANGLE_TRIANGULATE_H
 #define IGL_TRIANGLE_TRIANGULATE_H
-#include <igl/igl_inline.h>
+#include "../igl_inline.h"
 #include <string>
 #include <string>
 #include <Eigen/Core>
 #include <Eigen/Core>
 
 

+ 27 - 21
include/igl/triangle_triangle_adjacency.cpp

@@ -9,6 +9,7 @@
 #include "is_edge_manifold.h"
 #include "is_edge_manifold.h"
 #include "all_edges.h"
 #include "all_edges.h"
 #include "unique_simplices.h"
 #include "unique_simplices.h"
+#include "parallel_for.h"
 #include "unique_edge_map.h"
 #include "unique_edge_map.h"
 #include <algorithm>
 #include <algorithm>
 #include <iostream>
 #include <iostream>
@@ -172,41 +173,46 @@ template <
   }
   }
 
 
   // No race conditions because TT*[f][c]'s are in bijection with e's
   // No race conditions because TT*[f][c]'s are in bijection with e's
-  // Minimum number of iterms per openmp thread
+  // Minimum number of items per thread
   //const size_t num_e = E.rows();
   //const size_t num_e = E.rows();
-# ifndef IGL_OMP_MIN_VALUE
-#   define IGL_OMP_MIN_VALUE 1000
-# endif
-# pragma omp parallel for if (m>IGL_OMP_MIN_VALUE)
   // Slightly better memory access than loop over E
   // Slightly better memory access than loop over E
-  for(Index f = 0;f<(Index)m;f++)
-  {
-    for(Index c = 0;c<3;c++)
+  igl::parallel_for(
+    m,
+    [&](const Index & f)
     {
     {
-      const Index e = f + m*c;
-      //const Index c = e/m;
-      const vector<uE2EType> & N = uE2E[EMAP(e)];
-      for(const auto & ne : N)
+      for(Index c = 0;c<3;c++)
       {
       {
-        const Index nf = ne%m;
-        // don't add self
-        if(nf != f)
+        const Index e = f + m*c;
+        //const Index c = e/m;
+        const vector<uE2EType> & N = uE2E[EMAP(e)];
+        for(const auto & ne : N)
         {
         {
-          TT[f][c].push_back(nf);
-          if(construct_TTi)
+          const Index nf = ne%m;
+          // don't add self
+          if(nf != f)
           {
           {
-            const Index nc = ne/m;
-            TTi[f][c].push_back(nc);
+            TT[f][c].push_back(nf);
+            if(construct_TTi)
+            {
+              const Index nc = ne/m;
+              TTi[f][c].push_back(nc);
+            }
           }
           }
         }
         }
       }
       }
-    }
-  }
+    },
+    1000ul);
+
+
 }
 }
 
 
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // Explicit template specialization
 // generated by autoexplicit.sh
 // generated by autoexplicit.sh
+template void igl::triangle_triangle_adjacency<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+// generated by autoexplicit.sh
+template void igl::triangle_triangle_adjacency<Eigen::Matrix<int, -1, 3, 0, -1, 3>, int>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >, std::allocator<std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > > >&);
+// generated by autoexplicit.sh
 template void igl::triangle_triangle_adjacency<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::triangle_triangle_adjacency<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 // generated by autoexplicit.sh
 // generated by autoexplicit.sh
 template void igl::triangle_triangle_adjacency<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
 template void igl::triangle_triangle_adjacency<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);

+ 5 - 3
include/igl/uniformly_sample_two_manifold.h

@@ -11,8 +11,10 @@
 #include <Eigen/Dense>
 #include <Eigen/Dense>
 namespace igl
 namespace igl
 {
 {
-  // UNIFORMLY_SAMPLE_TWO_MANIFOLD Attempt to sample a mesh uniformly by furthest
-  // point relaxation as described in "Fast Automatic Skinning Transformations"
+  // UNIFORMLY_SAMPLE_TWO_MANIFOLD Attempt to sample a mesh uniformly by
+  // furthest point relaxation as described in "Fast Automatic Skinning
+  // Transformations"
+  //
   // [Jacobson et al. 12] Section 3.3.
   // [Jacobson et al. 12] Section 3.3.
   //
   //
   // Inputs:
   // Inputs:
@@ -37,6 +39,6 @@ namespace igl
     Eigen::VectorXi & S);
     Eigen::VectorXi & S);
 }
 }
 #ifndef IGL_STATIC_LIBRARY
 #ifndef IGL_STATIC_LIBRARY
-#  include "uniformly_sample_two_manifold.h"
+#  include "uniformly_sample_two_manifold.cpp"
 #endif
 #endif
 #endif
 #endif

+ 5 - 0
include/igl/unique.cpp

@@ -268,4 +268,9 @@ template void igl::unique<double>(std::vector<double, std::allocator<double> > c
 template void igl::unique<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::unique<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::unique<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::unique<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::unique_rows<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::unique_rows<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+
+#ifdef WIN32
+template void __cdecl igl::unique_rows<class Eigen::Matrix<int, -1, -1, 0, -1, -1>, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1> >(class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1> > const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1> > &, class Eigen::PlainObjectBase<class Eigen::Matrix<__int64, -1, 1, 0, -1, 1> > &, class Eigen::PlainObjectBase<class Eigen::Matrix<__int64, -1, 1, 0, -1, 1> > &);
+#endif
+
 #endif
 #endif

+ 5 - 0
include/igl/unique_edge_map.cpp

@@ -52,4 +52,9 @@ template void igl::unique_edge_map<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::M
 template void igl::unique_edge_map<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, long>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > >&);
 template void igl::unique_edge_map<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, long>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > >&);
 template void igl::unique_edge_map<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, int>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&);
 template void igl::unique_edge_map<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, int>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&);
 template void igl::unique_edge_map<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, unsigned long>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, std::vector<std::vector<unsigned long, std::allocator<unsigned long> >, std::allocator<std::vector<unsigned long, std::allocator<unsigned long> > > >&);
 template void igl::unique_edge_map<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, unsigned long>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, std::vector<std::vector<unsigned long, std::allocator<unsigned long> >, std::allocator<std::vector<unsigned long, std::allocator<unsigned long> > > >&);
+
+#ifdef WIN32
+template void __cdecl igl::unique_edge_map<class Eigen::Matrix<int, -1, 3, 0, -1, 3>, class Eigen::Matrix<int, -1, 2, 0, -1, 2>, class Eigen::Matrix<int, -1, 2, 0, -1, 2>, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, __int64>(class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, 3, 0, -1, 3> > const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, 2, 0, -1, 2> > &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, 2, 0, -1, 2> > &, class Eigen::PlainObjectBase<class Eigen::Matrix<__int64, -1, 1, 0, -1, 1> > &, class std::vector<class std::vector<__int64, class std::allocator<__int64> >, class std::allocator<class std::vector<__int64, class std::allocator<__int64> > > > &);
+#endif
+
 #endif 
 #endif 

+ 6 - 12
include/igl/unique_simplices.cpp

@@ -1,6 +1,6 @@
 // This file is part of libigl, a simple c++ geometry processing library.
 // This file is part of libigl, a simple c++ geometry processing library.
 // 
 // 
-// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
 // 
 // 
 // This Source Code Form is subject to the terms of the Mozilla Public License 
 // This Source Code Form is subject to the terms of the Mozilla Public License 
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can 
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can 
@@ -8,7 +8,7 @@
 #include "unique_simplices.h"
 #include "unique_simplices.h"
 #include "sort.h"
 #include "sort.h"
 #include "unique.h"
 #include "unique.h"
-#include "get_seconds.h"
+#include "parallel_for.h"
 
 
 template <
 template <
   typename DerivedF,
   typename DerivedF,
@@ -31,16 +31,7 @@ IGL_INLINE void igl::unique_simplices(
   igl::unique_rows(sortF,C,IA,IC);
   igl::unique_rows(sortF,C,IA,IC);
   FF.resize(IA.size(),F.cols());
   FF.resize(IA.size(),F.cols());
   const size_t mff = FF.rows();
   const size_t mff = FF.rows();
-  // Minimum number of iterms per openmp thread
-  #ifndef IGL_OMP_MIN_VALUE
-  #  define IGL_OMP_MIN_VALUE 1000
-  #endif
-  #pragma omp parallel for if (mff>IGL_OMP_MIN_VALUE)
-  // Copy into output
-  for(size_t i = 0;i<mff;i++)
-  {
-    FF.row(i) = F.row(IA(i));
-  }
+  parallel_for(mff,[&F,&IA,&FF](size_t & i){FF.row(i) = F.row(IA(i));},1000ul);
 }
 }
 
 
 template <
 template <
@@ -64,4 +55,7 @@ template void igl::unique_simplices<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::
 template void igl::unique_simplices<Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<long, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&);
 template void igl::unique_simplices<Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<long, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&);
 template void igl::unique_simplices<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::unique_simplices<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::unique_simplices<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::unique_simplices<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+#ifdef WIN32
+template void __cdecl igl::unique_simplices<class Eigen::Matrix<int, -1, 2, 0, -1, 2>, class Eigen::Matrix<int, -1, 2, 0, -1, 2>, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1> >(class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, 2, 0, -1, 2> > const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, 2, 0, -1, 2> > &, class Eigen::PlainObjectBase<class Eigen::Matrix<__int64, -1, 1, 0, -1, 1> > &, class Eigen::PlainObjectBase<class Eigen::Matrix<__int64, -1, 1, 0, -1, 1> > &);
+#endif
 #endif
 #endif

+ 1 - 0
include/igl/unproject_onto_mesh.cpp

@@ -73,5 +73,6 @@ IGL_INLINE bool igl::unproject_onto_mesh(
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // Explicit template specialization
 template bool igl::unproject_onto_mesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<float, 3, 1, 0, 3, 1> >(Eigen::Matrix<float, 2, 1, 0, 2, 1> const&, Eigen::Matrix<float, 4, 4, 0, 4, 4> const&, Eigen::Matrix<float, 4, 4, 0, 4, 4> const&, Eigen::Matrix<float, 4, 1, 0, 4, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, int&, Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> >&);
 template bool igl::unproject_onto_mesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<float, 3, 1, 0, 3, 1> >(Eigen::Matrix<float, 2, 1, 0, 2, 1> const&, Eigen::Matrix<float, 4, 4, 0, 4, 4> const&, Eigen::Matrix<float, 4, 4, 0, 4, 4> const&, Eigen::Matrix<float, 4, 1, 0, 4, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, int&, Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> >&);
+template bool igl::unproject_onto_mesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::Matrix<float, 2, 1, 0, 2, 1> const&, Eigen::Matrix<float, 4, 4, 0, 4, 4> const&, Eigen::Matrix<float, 4, 4, 0, 4, 4> const&, Eigen::Matrix<float, 4, 1, 0, 4, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, int&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 #endif
 #endif
 
 

+ 2 - 0
include/igl/upsample.cpp

@@ -105,5 +105,7 @@ IGL_INLINE void igl::upsample(
 
 
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // Explicit template specialization
+// generated by autoexplicit.sh
+template void igl::upsample<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
 template void igl::upsample<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::Matrix<double, -1, -1, 0, -1, -1>&, Eigen::Matrix<int, -1, -1, 0, -1, -1>&);
 template void igl::upsample<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::Matrix<double, -1, -1, 0, -1, -1>&, Eigen::Matrix<int, -1, -1, 0, -1, -1>&);
 #endif
 #endif

+ 5 - 5
include/igl/viewer/Viewer.cpp

@@ -346,14 +346,14 @@ namespace viewer
   T,t     Toggle filled faces
   T,t     Toggle filled faces
   Z       Snap to canonical view
   Z       Snap to canonical view
   [,]     Toggle between rotation control types (e.g. trackball, two-axis
   [,]     Toggle between rotation control types (e.g. trackball, two-axis
-          valuator with fixed up)
+          valuator with fixed up))"
 #ifdef IGL_VIEWER_WITH_NANOGUI
 #ifdef IGL_VIEWER_WITH_NANOGUI
+		R"(
   ;       Toggle vertex labels
   ;       Toggle vertex labels
-  :       Toggle face labels
+  :       Toggle face labels)"
 #endif
 #endif
-
-)");
-    std::cout<<usage;
+);
+    std::cout<<usage<<std::endl;
 #endif
 #endif
   }
   }
 
 

+ 5 - 3
include/igl/viewer/ViewerData.cpp

@@ -11,6 +11,7 @@
 #include <iostream>
 #include <iostream>
 
 
 #include <igl/per_face_normals.h>
 #include <igl/per_face_normals.h>
+#include <igl/material_colors.h>
 #include <igl/per_vertex_normals.h>
 #include <igl/per_vertex_normals.h>
 
 
 #ifdef ENABLE_SERIALIZATION
 #ifdef ENABLE_SERIALIZATION
@@ -104,9 +105,10 @@ IGL_INLINE void igl::viewer::ViewerData::set_mesh(const Eigen::MatrixXd& _V, con
     F = _F;
     F = _F;
 
 
     compute_normals();
     compute_normals();
-    uniform_colors(Eigen::Vector3d(51.0/255.0,43.0/255.0,33.3/255.0),
-                   Eigen::Vector3d(255.0/255.0,228.0/255.0,58.0/255.0),
-                   Eigen::Vector3d(255.0/255.0,235.0/255.0,80.0/255.0));
+    uniform_colors(
+      Eigen::Vector3d(GOLD_AMBIENT[0], GOLD_AMBIENT[1], GOLD_AMBIENT[2]),
+      Eigen::Vector3d(GOLD_DIFFUSE[0], GOLD_DIFFUSE[1], GOLD_DIFFUSE[2]),
+      Eigen::Vector3d(GOLD_SPECULAR[0], GOLD_SPECULAR[1], GOLD_SPECULAR[2]));
 
 
     grid_texture();
     grid_texture();
   }
   }

+ 4 - 1
include/igl/viewer/ViewerData.h

@@ -108,7 +108,10 @@ public:
   IGL_INLINE void compute_normals();
   IGL_INLINE void compute_normals();
 
 
   // Assigns uniform colors to all faces/vertices
   // Assigns uniform colors to all faces/vertices
-  IGL_INLINE void uniform_colors(Eigen::Vector3d ambient, Eigen::Vector3d diffuse, Eigen::Vector3d specular);
+  IGL_INLINE void uniform_colors(
+    Eigen::Vector3d ambient, 
+    Eigen::Vector3d diffuse, 
+    Eigen::Vector3d specular);
 
 
   // Generates a default grid texture
   // Generates a default grid texture
   IGL_INLINE void grid_texture();
   IGL_INLINE void grid_texture();

+ 51 - 0
include/igl/voxel_grid.cpp

@@ -0,0 +1,51 @@
+#include "voxel_grid.h"
+#include "grid.h"
+
+IGL_INLINE void igl::voxel_grid(
+  const Eigen::AlignedBox3d & box, 
+  const int in_s,
+  const int pad_count,
+  Eigen::MatrixXd & GV,
+  Eigen::RowVector3i & side)
+{
+  using namespace Eigen;
+  using namespace std;
+  MatrixXd::Index si = -1;
+  box.diagonal().maxCoeff(&si);
+  //MatrixXd::Index si = 0;
+  //assert(si>=0);
+  const double s_len = box.diagonal()(si);
+  assert(in_s>(pad_count*2+1) && "s should be > 2*pad_count+1");
+  const double s = in_s - 2*pad_count;
+  side(si) = s;
+  for(int i = 0;i<3;i++)
+  {
+    if(i!=si)
+    {
+      side(i) = ceil(s * (box.max()(i)-box.min()(i))/s_len);
+    }
+  }
+  side.array() += 2*pad_count;
+  grid(side,GV);
+  // A *    p/s  + B = min
+  // A * (1-p/s) + B = max
+  // B = min - A * p/s
+  // A * (1-p/s) + min - A * p/s = max
+  // A * (1-p/s) - A * p/s = max-min
+  // A * (1-2p/s) = max-min
+  // A  = (max-min)/(1-2p/s)
+  const Array<double,3,1> ps= 
+    (double)(pad_count)/(side.transpose().cast<double>().array()-1.);
+  const Array<double,3,1> A = box.diagonal().array()/(1.0-2.*ps);
+  //// This would result in an "anamorphic", but perfectly fit grid:
+  //const Array<double,3,1> B = box.min().array() - A.array()*ps;
+  //GV.array().rowwise() *= A.transpose();
+  //GV.array().rowwise() += B.transpose();
+  // Instead scale by largest factor and move to match center
+  Array<double,3,1>::Index ai = -1;
+  double a = A.maxCoeff(&ai);
+  const Array<double,1,3> ratio = 
+    a*(side.cast<double>().array()-1.0)/(double)(side(ai)-1.0);
+  GV.array().rowwise() *= ratio;
+  GV.rowwise() += (box.center().transpose()-GV.colwise().mean()).eval();
+}

+ 28 - 0
include/igl/voxel_grid.h

@@ -0,0 +1,28 @@
+#ifndef IGL_VOXEL_GRID_H
+#define IGL_VOXEL_GRID_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+#include <Eigen/Geometry>
+namespace igl
+{
+  // Construct the cell center positions of a regular voxel grid (lattice) made
+  // of perfectly square voxels.
+  // 
+  // Inputs:
+  //   box  bounding box to enclose by grid
+  //   s  number of cell centers on largest side (including 2*pad_count)
+  //   pad_count  number of cells beyond box
+  // Outputs:
+  //   GV  res(0)*res(1)*res(2) by 3 list of cell center positions
+  //   res  3-long list of dimension of voxel grid
+  IGL_INLINE void voxel_grid(
+    const Eigen::AlignedBox3d & box, 
+    const int s,
+    const int pad_count,
+    Eigen::MatrixXd & GV,
+    Eigen::RowVector3i & side);
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "voxel_grid.cpp"
+#endif
+#endif

+ 2 - 0
include/igl/writeMESH.cpp

@@ -137,6 +137,8 @@ IGL_INLINE bool igl::writeMESH(
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // Explicit template specialization
 // generated by autoexplicit.sh
 // generated by autoexplicit.sh
+template bool igl::writeMESH<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&);
+// generated by autoexplicit.sh
 template bool igl::writeMESH<Eigen::Matrix<double, 8, 3, 0, 8, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, 12, 3, 0, 12, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, 8, 3, 0, 8, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, 12, 3, 0, 12, 3> > const&);
 template bool igl::writeMESH<Eigen::Matrix<double, 8, 3, 0, 8, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, 12, 3, 0, 12, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, 8, 3, 0, 8, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, 12, 3, 0, 12, 3> > const&);
 //template bool igl::writeMESH<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
 //template bool igl::writeMESH<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
 template bool igl::writeMESH<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
 template bool igl::writeMESH<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);

+ 2 - 0
include/igl/writeSTL.cpp

@@ -110,6 +110,8 @@ IGL_INLINE bool igl::writeSTL(
 
 
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // Explicit template specialization
+// generated by autoexplicit.sh
+template bool igl::writeSTL<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, bool);
 template bool igl::writeSTL<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, bool);
 template bool igl::writeSTL<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, bool);
 template bool igl::writeSTL<Eigen::Matrix<double, 8, 3, 0, 8, 3>, Eigen::Matrix<int, 12, 3, 0, 12, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 8, 3, 0, 8, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, 12, 3, 0, 12, 3> > const&, bool);
 template bool igl::writeSTL<Eigen::Matrix<double, 8, 3, 0, 8, 3>, Eigen::Matrix<int, 12, 3, 0, 12, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 8, 3, 0, 8, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, 12, 3, 0, 12, 3> > const&, bool);
 #endif
 #endif

+ 2 - 0
include/igl/writeWRL.cpp

@@ -56,6 +56,8 @@ ccw TRUE
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // Explicit template specialization
 // generated by autoexplicit.sh
 // generated by autoexplicit.sh
+template bool igl::writeWRL<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&);
+// generated by autoexplicit.sh
 template bool igl::writeWRL<Eigen::Matrix<double, 8, 3, 0, 8, 3>, Eigen::Matrix<int, 12, 3, 0, 12, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 8, 3, 0, 8, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, 12, 3, 0, 12, 3> > const&);
 template bool igl::writeWRL<Eigen::Matrix<double, 8, 3, 0, 8, 3>, Eigen::Matrix<int, 12, 3, 0, 12, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 8, 3, 0, 8, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, 12, 3, 0, 12, 3> > const&);
 template bool igl::writeWRL<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
 template bool igl::writeWRL<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
 #endif
 #endif

+ 2 - 0
include/igl/write_triangle_mesh.cpp

@@ -63,6 +63,8 @@ IGL_INLINE bool igl::write_triangle_mesh(
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // Explicit template specialization
 // generated by autoexplicit.sh
 // generated by autoexplicit.sh
+template bool igl::write_triangle_mesh<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, bool);
+// generated by autoexplicit.sh
 template bool igl::write_triangle_mesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, const bool);
 template bool igl::write_triangle_mesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, const bool);
 template bool igl::write_triangle_mesh<Eigen::Matrix<double, 8, 3, 0, 8, 3>, Eigen::Matrix<int, 12, 3, 0, 12, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, 8, 3, 0, 8, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, 12, 3, 0, 12, 3> > const&, bool);
 template bool igl::write_triangle_mesh<Eigen::Matrix<double, 8, 3, 0, 8, 3>, Eigen::Matrix<int, 12, 3, 0, 12, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, 8, 3, 0, 8, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, 12, 3, 0, 12, 3> > const&, bool);
 #endif
 #endif

+ 25 - 10
index.html

@@ -14,9 +14,9 @@
 
 
 <h1 id="libigl-asimplecgeometryprocessinglibrary">libigl - A simple C++ geometry processing library</h1>
 <h1 id="libigl-asimplecgeometryprocessinglibrary">libigl - A simple C++ geometry processing library</h1>
 
 
-<figure>
-<img src="libigl-teaser.png" alt="" />
-</figure>
+<p><a href="https://travis-ci.org/libigl/libigl"><img src="https://travis-ci.org/libigl/libigl.svg?branch=master" alt="Build Status" /></a>
+<a href="https://ci.appveyor.com/project/danielepanozzo/libigl-6hjk1"><img src="https://ci.appveyor.com/api/projects/status/mf3t9rnhco0vhly8?svg=true" alt="Build status" /></a>
+<img src="libigl-teaser.png" alt="" /></p>
 
 
 <p><a href="https://github.com/libigl/libigl/">https://github.com/libigl/libigl/</a></p>
 <p><a href="https://github.com/libigl/libigl/">https://github.com/libigl/libigl/</a></p>
 
 
@@ -51,6 +51,9 @@ the header-only default mode: (i.e. just include the headers you want to use).</
 group prototypes a lot in MATLAB, and we have a useful <a href="matlab-to-eigen.html">MATLAB to libigl+Eigen
 group prototypes a lot in MATLAB, and we have a useful <a href="matlab-to-eigen.html">MATLAB to libigl+Eigen
 conversion table</a>.</p>
 conversion table</a>.</p>
 
 
+<p>We regularly test compiling our library on Mac OS X with clang, Linux with gcc
+and Windows with Visual Studio 2015 Community Edition.</p>
+
 <h2 id="tutorial">Tutorial</h2>
 <h2 id="tutorial">Tutorial</h2>
 
 
 <p>As of version 1.0, libigl includes an introductory
 <p>As of version 1.0, libigl includes an introductory
@@ -168,7 +171,7 @@ and updating (i.e. committing) that change to the hash.</p>
 subrepos:</p>
 subrepos:</p>
 
 
 <pre><code class="bash">git pull
 <pre><code class="bash">git pull
-git submodule update -- recursive
+git submodule update --recursive
 </code></pre>
 </code></pre>
 
 
 <h2 id="unittesting">Unit testing</h2>
 <h2 id="unittesting">Unit testing</h2>
@@ -199,7 +202,7 @@ BibTeX entry:</p>
   title = {{libigl}: A simple {C++} geometry processing library},
   title = {{libigl}: A simple {C++} geometry processing library},
   author = {Alec Jacobson and Daniele Panozzo and others},
   author = {Alec Jacobson and Daniele Panozzo and others},
   note = {http://libigl.github.io/libigl/},
   note = {http://libigl.github.io/libigl/},
-  year = {2015},
+  year = {2016},
 }
 }
 </code></pre>
 </code></pre>
 
 
@@ -210,23 +213,35 @@ Eurographics/ACM Symposium on Geometry Processing software award. Here are a
 few labs/companies/institutions using libigl:</p>
 few labs/companies/institutions using libigl:</p>
 
 
 <ul>
 <ul>
+<li><a href="http://www.adobe.com/technology/">Adobe Research</a></li>
+<li><a href="http://www.ea.com">Electronic Arts, Inc</a></li>
+<li><a href="http://meshconsultants.ca/">Mesh</a>, consultants, Canada</li>
+<li><a href="http://graphics.pixar.com/research/">Pixar Research</a></li>
 <li><a href="http://esotericsoftware.com/">Spine by Esoteric Software</a> is an animation tool dedicated to 2D characters.</li>
 <li><a href="http://esotericsoftware.com/">Spine by Esoteric Software</a> is an animation tool dedicated to 2D characters.</li>
 <li>Columbia University, <a href="http://www.cs.columbia.edu/cg/">Columbia Computer Graphics Group</a>, USA</li>
 <li>Columbia University, <a href="http://www.cs.columbia.edu/cg/">Columbia Computer Graphics Group</a>, USA</li>
 <li><a href="http://www.graphics.cornell.edu/">Cornell University</a>, USA</li>
 <li><a href="http://www.graphics.cornell.edu/">Cornell University</a>, USA</li>
+<li><a href="http://dcgi.felk.cvut.cz/">Czech Technical University in Prague</a>, Czech</li>
 <li>EPF Lausanne, <a href="http://lgg.epfl.ch/people.php">Computer Graphics and Geometry Laboratory</a>, Switzerland</li>
 <li>EPF Lausanne, <a href="http://lgg.epfl.ch/people.php">Computer Graphics and Geometry Laboratory</a>, Switzerland</li>
 <li>ETH Zurich, <a href="http://igl.ethz.ch/">Interactive Geometry Lab</a> and <a href="http://ait.inf.ethz.ch/">Advanced Technologies Lab</a>, Swizterland</li>
 <li>ETH Zurich, <a href="http://igl.ethz.ch/">Interactive Geometry Lab</a> and <a href="http://ait.inf.ethz.ch/">Advanced Technologies Lab</a>, Swizterland</li>
 <li>George Mason University, <a href="http://cs.gmu.edu/~ygingold/">CraGL</a>, USA</li>
 <li>George Mason University, <a href="http://cs.gmu.edu/~ygingold/">CraGL</a>, USA</li>
-<li><a href="http://www.ust.hk/">Hong Kong University of Science and Technology</a>, USA</li>
+<li><a href="http://www.ust.hk/">Hong Kong University of Science and Technology</a>, Hong Kong</li>
 <li><a href="http://www.nii.ac.jp/en/">National Institute of Informatics</a>, Japan</li>
 <li><a href="http://www.nii.ac.jp/en/">National Institute of Informatics</a>, Japan</li>
 <li>New York University, <a href="http://mrl.nyu.edu/">Media Research Lab</a>, USA</li>
 <li>New York University, <a href="http://mrl.nyu.edu/">Media Research Lab</a>, USA</li>
 <li>NYUPoly, <a href="http://game.engineering.nyu.edu/">Game Innovation Lab</a>, USA</li>
 <li>NYUPoly, <a href="http://game.engineering.nyu.edu/">Game Innovation Lab</a>, USA</li>
-<li><a href="http://www.telecom-paristech.fr/en/formation-et-innovation-dans-le-numerique.html">Telecom ParisTech</a>, Paris, France</li>
+<li><a href="https://www.cg.tu-berlin.de">TU Berlin</a>, Germany</li>
 <li><a href="http://www.tudelft.nl/en/">TU Delft</a>, Netherlands</li>
 <li><a href="http://www.tudelft.nl/en/">TU Delft</a>, Netherlands</li>
+<li><a href="https://www.tuwien.ac.at/en/tuwien_home/">TU Wien</a>, Austria</li>
+<li><a href="http://www.telecom-paristech.fr/en/formation-et-innovation-dans-le-numerique.html">Telecom ParisTech</a>, Paris, France</li>
 <li><a href="http://mtm.ufsc.br/~leo/">Universidade Federal de Santa Catarina</a>, Brazil</li>
 <li><a href="http://mtm.ufsc.br/~leo/">Universidade Federal de Santa Catarina</a>, Brazil</li>
-<li><a href="http://www.usi.ch/en">Università della Svizzera Italiana</a>, Switzerland</li>
 <li><a href="http://vecg.cs.ucl.ac.uk/">University College London</a>, England</li>
 <li><a href="http://vecg.cs.ucl.ac.uk/">University College London</a>, England</li>
+<li><a href="http://vis.berkeley.edu/">University of California Berkeley</a>, USA</li>
 <li><a href="http://www.cam.ac.uk/">University of Cambridge</a>, England</li>
 <li><a href="http://www.cam.ac.uk/">University of Cambridge</a>, England</li>
 <li><a href="http://cg.cis.upenn.edu/">University of Pennsylvania</a>, USA</li>
 <li><a href="http://cg.cis.upenn.edu/">University of Pennsylvania</a>, USA</li>
+<li><a href="http://www.cs.utexas.edu/users/evouga/">University of Texas at Austin</a>, USA</li>
+<li><a href="https://www.csc.uvic.ca/Research/graphics/">University of Victoria</a>, Canada</li>
+<li><a href="http://www.usi.ch/en">Università della Svizzera Italiana</a>, Switzerland</li>
+<li><a href="http://www.univ-tlse3.fr/">Université Toulouse III Paul Sabatier</a>, France</li>
+<li><a href="http://www.math.zju.edu.cn/cagd/">Zhejiang University</a>, China</li>
 </ul>
 </ul>
 
 
 <h2 id="contact">Contact</h2>
 <h2 id="contact">Contact</h2>
@@ -248,8 +263,8 @@ page</a>.</p>
 
 
 <h2 id="copyright">Copyright</h2>
 <h2 id="copyright">Copyright</h2>
 
 
-<p>2015 Alec Jacobson, Daniele Panozzo, Christian Schüller, Olga Diamanti, Qingnan
-Zhou, Nico Pietroni, Stefan Brugger, Kenshi Takayama, Wenzel Jakob, Nikolas De
+<p>2016 Alec Jacobson, Daniele Panozzo, Christian Schüller, Olga Diamanti, Qingnan
+Zhou, Sebastian Koch, Nico Pietroni, Stefan Brugger, Kenshi Takayama, Wenzel Jakob, Nikolas De
 Giorgis, Luigi Rocca, Leonardo Sacht, Kevin Walliman, Olga Sorkine-Hornung, and others.</p>
 Giorgis, Luigi Rocca, Leonardo Sacht, Kevin Walliman, Olga Sorkine-Hornung, and others.</p>
 
 
 <p>Please see individual files for appropriate copyright notices.</p>
 <p>Please see individual files for appropriate copyright notices.</p>

+ 1 - 9
optional/index.html

@@ -50,14 +50,6 @@ make
 <p>These are (admittedly unpopular) functions that have never been used by us
 <p>These are (admittedly unpopular) functions that have never been used by us
 statically so we haven&#8217;t explicit instantiations (yet).</p>
 statically so we haven&#8217;t explicit instantiations (yet).</p>
 
 
-<h4 id="examples">Examples</h4>
-
-<p>You can make a slew of examples by issuing:</p>
-
-<pre><code>cd ../examples
-make
-</code></pre>
-
 <h4 id="external">External</h4>
 <h4 id="external">External</h4>
 
 
 <p>Finally there are a number of external libraries that we include in
 <p>Finally there are a number of external libraries that we include in
@@ -316,7 +308,7 @@ int main(int argc, char * argv[])
 {
 {
 Eigen::MatrixXd V;
 Eigen::MatrixXd V;
 Eigen::MatrixXi F;
 Eigen::MatrixXi F;
-return (argc&gt;=2 &amp;amp;&amp;amp; igl::read_triangle_mesh(argv[1],V,F)?0:1);
+return (argc&gt;=2 &amp;&amp; igl::read_triangle_mesh(argv[1],V,F)?0:1);
 }
 }
 </code></pre>
 </code></pre>
 
 

+ 33 - 8
python/CMakeLists.txt

@@ -47,7 +47,7 @@ endif()
 
 
 include_directories(${PYTHON_INCLUDE_DIR} include)
 include_directories(${PYTHON_INCLUDE_DIR} include)
 
 
-## include pybing
+## include pybind
 include_directories(${PROJECT_SOURCE_DIR}/../external/pybind11/include)
 include_directories(${PROJECT_SOURCE_DIR}/../external/pybind11/include)
 
 
 ## include libigl
 ## include libigl
@@ -57,12 +57,12 @@ option(LIBIGL_WITH_NANOGUI          "Use Nanogui menu"   OFF)
 option(LIBIGL_WITH_CGAL             "Use CGAL"           OFF)
 option(LIBIGL_WITH_CGAL             "Use CGAL"           OFF)
 option(LIBIGL_WITH_BOOLEAN          "Use Cork boolean"   OFF)
 option(LIBIGL_WITH_BOOLEAN          "Use Cork boolean"   OFF)
 option(LIBIGL_WITH_COMISO           "Use CoMiso"         ON)
 option(LIBIGL_WITH_COMISO           "Use CoMiso"         ON)
-option(LIBIGL_WITH_EMBREE           "Use Embree"         OFF)
+option(LIBIGL_WITH_EMBREE           "Use Embree"         ON)
 option(LIBIGL_WITH_LIM              "Use LIM"            ON)
 option(LIBIGL_WITH_LIM              "Use LIM"            ON)
 option(LIBIGL_WITH_MATLAB           "Use Matlab"         OFF)
 option(LIBIGL_WITH_MATLAB           "Use Matlab"         OFF)
 option(LIBIGL_WITH_MOSEK            "Use MOSEK"          OFF)
 option(LIBIGL_WITH_MOSEK            "Use MOSEK"          OFF)
 option(LIBIGL_WITH_BBW              "Use BBW"            ON)
 option(LIBIGL_WITH_BBW              "Use BBW"            ON)
-option(LIBIGL_WITH_OPENGL_AND_PNG   "Use OpenGL"         ON)
+option(LIBIGL_WITH_PNG              "Use PNG"            ON)
 option(LIBIGL_WITH_TETGEN           "Use Tetgen"         ON)
 option(LIBIGL_WITH_TETGEN           "Use Tetgen"         ON)
 option(LIBIGL_WITH_TRIANGLE         "Use Triangle"       ON)
 option(LIBIGL_WITH_TRIANGLE         "Use Triangle"       ON)
 option(LIBIGL_WITH_XML              "Use XML"            ON)
 option(LIBIGL_WITH_XML              "Use XML"            ON)
@@ -84,19 +84,44 @@ add_definitions(${LIBIGL_DEFINITIONS})
 ## Optional modules
 ## Optional modules
 if (LIBIGL_WITH_VIEWER)
 if (LIBIGL_WITH_VIEWER)
   add_definitions(-DPY_VIEWER)
   add_definitions(-DPY_VIEWER)
-  list(APPEND SHARED_SOURCES "py_igl_viewer.cpp")
+  list(APPEND SHARED_SOURCES "modules/py_igl_viewer.cpp")
 endif ()
 endif ()
 
 
 if (LIBIGL_WITH_COMISO)
 if (LIBIGL_WITH_COMISO)
   add_definitions(-DPY_COMISO)
   add_definitions(-DPY_COMISO)
-  list(APPEND SHARED_SOURCES "copyleft/py_igl_comiso.cpp")
+  list(APPEND SHARED_SOURCES "modules/copyleft/py_igl_comiso.cpp")
+endif ()
+
+if (LIBIGL_WITH_TETGEN)
+  add_definitions(-DPY_TETGEN)
+  list(APPEND SHARED_SOURCES "modules/copyleft/py_igl_tetgen.cpp")
+endif ()
+
+if (LIBIGL_WITH_EMBREE)
+  add_definitions(-DPY_EMBREE)
+  list(APPEND SHARED_SOURCES "modules/py_igl_embree.cpp")
+endif ()
+
+if (LIBIGL_WITH_TRIANGLE)
+  add_definitions(-DPY_TRIANGLE)
+  list(APPEND SHARED_SOURCES "modules/py_igl_triangle.cpp")
+endif ()
+
+if (LIBIGL_WITH_CGAL)
+  add_definitions(-DPY_CGAL)
+  list(APPEND SHARED_SOURCES "modules/copyleft/py_igl_cgal.cpp")
+endif ()
+
+if (LIBIGL_WITH_PNG)
+  add_definitions(-DPY_PNG)
+  list(APPEND SHARED_SOURCES "modules/py_igl_png.cpp")
 endif ()
 endif ()
 
 
 
 
 ## Prepare the python library
 ## Prepare the python library
 add_library(pyigl SHARED
 add_library(pyigl SHARED
   python_shared.cpp
   python_shared.cpp
-  py_vector.cpp
+  modules/py_vector.cpp
   py_igl.cpp
   py_igl.cpp
   py_doc.cpp
   py_doc.cpp
   ${SHARED_SOURCES}
   ${SHARED_SOURCES}
@@ -142,10 +167,10 @@ elseif (UNIX)
   #Enable flag if undefined symbols appear on pyigl module import to get notified about the missing symbols at link time
   #Enable flag if undefined symbols appear on pyigl module import to get notified about the missing symbols at link time
   option(CHECK_UNDEFINED        "Check for undefined symbols"    OFF)
   option(CHECK_UNDEFINED        "Check for undefined symbols"    OFF)
 
 
-  # Strip unnecessary sections of the binary on Linux/Mac OS 
+  # Strip unnecessary sections of the binary on Linux/Mac OS
   if(APPLE)
   if(APPLE)
     set_target_properties(pyigl PROPERTIES MACOSX_RPATH ".")
     set_target_properties(pyigl PROPERTIES MACOSX_RPATH ".")
-    
+
     if (NOT CHECK_UNDEFINED)
     if (NOT CHECK_UNDEFINED)
       set_target_properties(pyigl PROPERTIES LINK_FLAGS "-undefined dynamic_lookup -dead_strip")
       set_target_properties(pyigl PROPERTIES LINK_FLAGS "-undefined dynamic_lookup -dead_strip")
     endif()
     endif()

+ 2 - 2
python/README.md

@@ -5,7 +5,7 @@
 <span style="color:#F62217">
 <span style="color:#F62217">
 Everything in this folder is currently being developed and it is likely to be
 Everything in this folder is currently being developed and it is likely to be
 changed radically in the next couple of months, breaking compatibility between
 changed radically in the next couple of months, breaking compatibility between
-different version. We plan to stabilize the python API by the end of 2015.
+different version. We plan to stabilize the python API by the end of 2016.
 </span>
 </span>
 
 
 ## Introduction
 ## Introduction
@@ -153,7 +153,7 @@ page](https://github.com/libigl/libigl/issues).
 
 
 ## Copyright
 ## Copyright
 2015 Alec Jacobson, Daniele Panozzo, Christian Schüller, Olga Diamanti, Qingnan
 2015 Alec Jacobson, Daniele Panozzo, Christian Schüller, Olga Diamanti, Qingnan
-Zhou, Nico Pietroni, Stefan Brugger, Kenshi Takayama, Wenzel Jakob, Nikolas De
+Zhou, Sebastian Koch, Nico Pietroni, Stefan Brugger, Kenshi Takayama, Wenzel Jakob, Nikolas De
 Giorgis, Luigi Rocca, Leonardo Sacht, Olga Sorkine-Hornung, and others.
 Giorgis, Luigi Rocca, Leonardo Sacht, Olga Sorkine-Hornung, and others.
 
 
 Please see individual files for appropriate copyright notices.
 Please see individual files for appropriate copyright notices.

+ 5 - 1
python/iglhelpers.py

@@ -8,7 +8,9 @@ def p2e(m):
             return igl.eigen.MatrixXi(m)
             return igl.eigen.MatrixXi(m)
         elif m.dtype.type == np.float64:
         elif m.dtype.type == np.float64:
             return igl.eigen.MatrixXd(m)
             return igl.eigen.MatrixXd(m)
-        raise TypeError("p2e only support dtype float64 or int32")
+        elif m.dtype.type == np.bool:
+            return igl.eigen.MatrixXb(m)
+        raise TypeError("p2e only support dtype float64, int32 and bool")
     if sparse.issparse(m):
     if sparse.issparse(m):
         # convert in a dense matrix with triples
         # convert in a dense matrix with triples
         coo = m.tocoo()
         coo = m.tocoo()
@@ -34,6 +36,8 @@ def e2p(m):
         return np.array(m, dtype='float64')
         return np.array(m, dtype='float64')
     elif isinstance(m, igl.eigen.MatrixXi):
     elif isinstance(m, igl.eigen.MatrixXi):
         return np.array(m, dtype='int32')
         return np.array(m, dtype='int32')
+    elif isinstance(m, igl.eigen.MatrixXb):
+        return np.array(m, dtype='bool')
     elif isinstance(m, igl.eigen.SparseMatrixd):
     elif isinstance(m, igl.eigen.SparseMatrixd):
         coo = np.array(m.toCOO())
         coo = np.array(m.toCOO())
         I = coo[:, 0]
         I = coo[:, 0]

+ 18 - 0
python/modules/copyleft/py_igl_cgal.cpp

@@ -0,0 +1,18 @@
+//#include <Eigen/Geometry>
+//#include <Eigen/Dense>
+//#include <Eigen/Sparse>
+
+
+#include "../../python_shared.h"
+
+#include <igl/copyleft/cgal/mesh_boolean.h>
+
+
+void python_export_igl_cgal(py::module &me) {
+
+  py::module m = me.def_submodule(
+    "cgal", "Wrappers for libigl functions that use cgal");
+
+  #include "../../py_igl/copyleft/cgal/py_mesh_boolean.cpp"
+
+}

+ 3 - 3
python/copyleft/py_igl_comiso.cpp → python/modules/copyleft/py_igl_comiso.cpp

@@ -3,7 +3,7 @@
 #include <Eigen/Sparse>
 #include <Eigen/Sparse>
 
 
 
 
-#include "../python_shared.h"
+#include "../../python_shared.h"
 
 
 #include <igl/copyleft/comiso/nrosy.h>
 #include <igl/copyleft/comiso/nrosy.h>
 #include <igl/copyleft/comiso/miq.h>
 #include <igl/copyleft/comiso/miq.h>
@@ -13,7 +13,7 @@ void python_export_igl_comiso(py::module &me) {
   py::module m = me.def_submodule(
   py::module m = me.def_submodule(
     "comiso", "Wrappers for libigl functions that use comiso");
     "comiso", "Wrappers for libigl functions that use comiso");
 
 
-  #include "../py_igl/copyleft/comiso/py_nrosy.cpp"
-  #include "../py_igl/copyleft/comiso/py_miq.cpp"
+  #include "../../py_igl/copyleft/comiso/py_nrosy.cpp"
+  #include "../../py_igl/copyleft/comiso/py_miq.cpp"
 
 
 }
 }

+ 18 - 0
python/modules/copyleft/py_igl_tetgen.cpp

@@ -0,0 +1,18 @@
+//#include <Eigen/Geometry>
+//#include <Eigen/Dense>
+//#include <Eigen/Sparse>
+
+
+#include "../../python_shared.h"
+
+#include <igl/copyleft/tetgen/tetrahedralize.h>
+
+
+void python_export_igl_tetgen(py::module &me) {
+
+  py::module m = me.def_submodule(
+    "tetgen", "Wrappers for libigl functions that use tetgen");
+
+  #include "../../py_igl/copyleft/tetgen/py_tetrahedralize.cpp"
+
+}

+ 18 - 0
python/modules/py_igl_embree.cpp

@@ -0,0 +1,18 @@
+//#include <Eigen/Geometry>
+//#include <Eigen/Dense>
+//#include <Eigen/Sparse>
+
+
+#include "../python_shared.h"
+
+#include <igl/embree/ambient_occlusion.h>
+
+
+void python_export_igl_embree(py::module &me) {
+
+  py::module m = me.def_submodule(
+    "embree", "Wrappers for libigl functions that use embree");
+
+  #include "../py_igl/embree/py_ambient_occlusion.cpp"
+
+}

+ 16 - 0
python/modules/py_igl_png.cpp

@@ -0,0 +1,16 @@
+
+#include "../python_shared.h"
+
+#include <igl/png/readPNG.h>
+#include <igl/png/writePNG.h>
+
+
+void python_export_igl_png(py::module &me) {
+
+  py::module m = me.def_submodule(
+    "png", "Wrappers for libigl functions that use png");
+
+  #include "../py_igl/png/py_readPNG.cpp"
+  #include "../py_igl/png/py_writePNG.cpp"
+
+}

+ 18 - 0
python/modules/py_igl_triangle.cpp

@@ -0,0 +1,18 @@
+//#include <Eigen/Geometry>
+//#include <Eigen/Dense>
+//#include <Eigen/Sparse>
+
+
+#include "../python_shared.h"
+
+#include <igl/triangle/triangulate.h>
+
+
+void python_export_igl_triangle(py::module &me) {
+
+  py::module m = me.def_submodule(
+    "triangle", "Wrappers for libigl functions that use triangle");
+
+  #include "../py_igl/triangle/py_triangulate.cpp"
+
+}

+ 17 - 1
python/py_igl_viewer.cpp → python/modules/py_igl_viewer.cpp

@@ -1,11 +1,12 @@
 #include <Eigen/Dense>
 #include <Eigen/Dense>
 #include <Eigen/Sparse>
 #include <Eigen/Sparse>
 
 
-#include "python_shared.h"
+#include "../python_shared.h"
 #define ENABLE_SERIALIZATION
 #define ENABLE_SERIALIZATION
 #include <igl/viewer/Viewer.h>
 #include <igl/viewer/Viewer.h>
 #include <igl/viewer/ViewerCore.h>
 #include <igl/viewer/ViewerCore.h>
 #include <igl/viewer/ViewerData.h>
 #include <igl/viewer/ViewerData.h>
+#include <igl/viewer/OpenGL_state.h>
 #include <igl/serialize.h>
 #include <igl/serialize.h>
 
 
 void python_export_igl_viewer(py::module &m)
 void python_export_igl_viewer(py::module &m)
@@ -118,6 +119,16 @@ py::enum_<igl::viewer::ViewerData::DirtyFlags>(viewerdata_class, "DirtyFlags")
 
 
     ;
     ;
 
 
+//////////////////////// OPENGL_State
+
+py::class_<igl::viewer::OpenGL_state> opengl_state_class(me, "OpenGL_state");
+
+    opengl_state_class
+    .def(py::init<>())
+    .def("init", &igl::viewer::OpenGL_state::init)
+
+    ;
+
 //////////////////////// CORE
 //////////////////////// CORE
 
 
 py::class_<igl::viewer::ViewerCore> viewercore_class(me, "ViewerCore");
 py::class_<igl::viewer::ViewerCore> viewercore_class(me, "ViewerCore");
@@ -311,6 +322,7 @@ py::class_<igl::viewer::ViewerCore> viewercore_class(me, "ViewerCore");
     .def(py::init<>())
     .def(py::init<>())
     .def_readwrite("data", &igl::viewer::Viewer::data)
     .def_readwrite("data", &igl::viewer::Viewer::data)
     .def_readwrite("core", &igl::viewer::Viewer::core)
     .def_readwrite("core", &igl::viewer::Viewer::core)
+    .def_readwrite("opengl", &igl::viewer::Viewer::opengl)
     .def("launch", &igl::viewer::Viewer::launch, py::arg("resizable") = true, py::arg("fullscreen") = false)
     .def("launch", &igl::viewer::Viewer::launch, py::arg("resizable") = true, py::arg("fullscreen") = false)
     .def("launch_init", &igl::viewer::Viewer::launch_init, py::arg("resizable") = true, py::arg("fullscreen") = false)
     .def("launch_init", &igl::viewer::Viewer::launch_init, py::arg("resizable") = true, py::arg("fullscreen") = false)
     .def("launch_rendering", &igl::viewer::Viewer::launch_rendering, py::arg("loop") = true)
     .def("launch_rendering", &igl::viewer::Viewer::launch_rendering, py::arg("loop") = true)
@@ -356,6 +368,10 @@ py::class_<igl::viewer::ViewerCore> viewercore_class(me, "ViewerCore");
     .def("open_dialog_load_mesh", &igl::viewer::Viewer::open_dialog_load_mesh)
     .def("open_dialog_load_mesh", &igl::viewer::Viewer::open_dialog_load_mesh)
     .def("open_dialog_save_mesh", &igl::viewer::Viewer::open_dialog_save_mesh)
     .def("open_dialog_save_mesh", &igl::viewer::Viewer::open_dialog_save_mesh)
 
 
+    // Input handling
+    .def_readwrite("current_mouse_x", &igl::viewer::Viewer::current_mouse_x)
+    .def_readwrite("current_mouse_y", &igl::viewer::Viewer::current_mouse_y)
+
     // Callbacks
     // Callbacks
     .def_readwrite("callback_init", &igl::viewer::Viewer::callback_init)
     .def_readwrite("callback_init", &igl::viewer::Viewer::callback_init)
     .def_readwrite("callback_pre_draw", &igl::viewer::Viewer::callback_pre_draw)
     .def_readwrite("callback_pre_draw", &igl::viewer::Viewer::callback_pre_draw)

+ 33 - 1
python/py_vector.cpp → python/modules/py_vector.cpp

@@ -3,7 +3,7 @@
 #include <Eigen/Sparse>
 #include <Eigen/Sparse>
 
 
 
 
-#include "python_shared.h"
+#include "../python_shared.h"
 
 
 /// Creates Python bindings for a dynamic Eigen matrix
 /// Creates Python bindings for a dynamic Eigen matrix
 template <typename Type>
 template <typename Type>
@@ -126,9 +126,15 @@ py::class_<Type> bind_eigen_2(py::module &m, const char *name,
         .def("rightCols", [](Type &m, const int& k) { return Type(m.rightCols(k)); })
         .def("rightCols", [](Type &m, const int& k) { return Type(m.rightCols(k)); })
         .def("leftCols", [](Type &m, const int& k) { return Type(m.leftCols(k)); })
         .def("leftCols", [](Type &m, const int& k) { return Type(m.leftCols(k)); })
 
 
+        .def("setLeftCols", [](Type &m, const int& k, const Type& v) { return Type(m.leftCols(k) = v); })
+        .def("setRightCols", [](Type &m, const int& k, const Type& v) { return Type(m.rightCols(k) = v); })
+
         .def("topRows", [](Type &m, const int& k) { return Type(m.topRows(k)); })
         .def("topRows", [](Type &m, const int& k) { return Type(m.topRows(k)); })
         .def("bottomRows", [](Type &m, const int& k) { return Type(m.bottomRows(k)); })
         .def("bottomRows", [](Type &m, const int& k) { return Type(m.bottomRows(k)); })
 
 
+        .def("setTopRows", [](Type &m, const int& k, const Type& v) { return Type(m.topRows(k) = v); })
+        .def("setBottomRows", [](Type &m, const int& k, const Type& v) { return Type(m.bottomRows(k) = v); })
+
         .def("topLeftCorner", [](Type &m, const int& p, const int&q) { return Type(m.topLeftCorner(p,q)); })
         .def("topLeftCorner", [](Type &m, const int& p, const int&q) { return Type(m.topLeftCorner(p,q)); })
         .def("bottomLeftCorner", [](Type &m, const int& p, const int&q) { return Type(m.bottomLeftCorner(p,q)); })
         .def("bottomLeftCorner", [](Type &m, const int& p, const int&q) { return Type(m.bottomLeftCorner(p,q)); })
         .def("topRightCorner", [](Type &m, const int& p, const int&q) { return Type(m.topRightCorner(p,q)); })
         .def("topRightCorner", [](Type &m, const int& p, const int&q) { return Type(m.topRightCorner(p,q)); })
@@ -147,6 +153,7 @@ py::class_<Type> bind_eigen_2(py::module &m, const char *name,
         .def("trace", [](const Type &m) {return m.trace();})
         .def("trace", [](const Type &m) {return m.trace();})
         .def("norm", [](const Type &m) {return m.norm();})
         .def("norm", [](const Type &m) {return m.norm();})
         .def("squaredNorm", [](const Type &m) {return m.squaredNorm();})
         .def("squaredNorm", [](const Type &m) {return m.squaredNorm();})
+        .def("squaredMean", [](const Type &m) {return m.array().square().mean();})
 
 
         .def("minCoeff", [](const Type &m) {return m.minCoeff();} )
         .def("minCoeff", [](const Type &m) {return m.minCoeff();} )
         .def("maxCoeff", [](const Type &m) {return m.maxCoeff();} )
         .def("maxCoeff", [](const Type &m) {return m.maxCoeff();} )
@@ -167,6 +174,7 @@ py::class_<Type> bind_eigen_2(py::module &m, const char *name,
         .def("cwiseQuotient", [](const Type &m1, const Type &m2) -> Type { return m1.cwiseQuotient(m2); })
         .def("cwiseQuotient", [](const Type &m1, const Type &m2) -> Type { return m1.cwiseQuotient(m2); })
 
 
         /* Row and column-wise operations */
         /* Row and column-wise operations */
+        .def("rowwiseSet", [](Type &m, const Type &m2) {return Type(m.rowwise() = Eigen::Matrix<Scalar, 1, Eigen::Dynamic>(m2));} )
         .def("rowwiseSum", [](const Type &m) {return Type(m.rowwise().sum());} )
         .def("rowwiseSum", [](const Type &m) {return Type(m.rowwise().sum());} )
         .def("rowwiseProd", [](const Type &m) {return Type(m.rowwise().prod());} )
         .def("rowwiseProd", [](const Type &m) {return Type(m.rowwise().prod());} )
         .def("rowwiseMean", [](const Type &m) {return Type(m.rowwise().mean());} )
         .def("rowwiseMean", [](const Type &m) {return Type(m.rowwise().mean());} )
@@ -175,6 +183,7 @@ py::class_<Type> bind_eigen_2(py::module &m, const char *name,
         .def("rowwiseMinCoeff", [](const Type &m) {return Type(m.rowwise().minCoeff());} )
         .def("rowwiseMinCoeff", [](const Type &m) {return Type(m.rowwise().minCoeff());} )
         .def("rowwiseMaxCoeff", [](const Type &m) {return Type(m.rowwise().maxCoeff());} )
         .def("rowwiseMaxCoeff", [](const Type &m) {return Type(m.rowwise().maxCoeff());} )
 
 
+        .def("colwiseSet", [](Type &m, const Type &m2) {return Type(m.colwise() = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>(m2));} )
         .def("colwiseSum", [](const Type &m) {return Type(m.colwise().sum());} )
         .def("colwiseSum", [](const Type &m) {return Type(m.colwise().sum());} )
         .def("colwiseProd", [](const Type &m) {return Type(m.colwise().prod());} )
         .def("colwiseProd", [](const Type &m) {return Type(m.colwise().prod());} )
         .def("colwiseMean", [](const Type &m) {return Type(m.colwise().mean());} )
         .def("colwiseMean", [](const Type &m) {return Type(m.colwise().mean());} )
@@ -249,6 +258,26 @@ py::class_<Type> bind_eigen_2(py::module &m, const char *name,
         /* Comparison operators */
         /* Comparison operators */
         .def(py::self == py::self)
         .def(py::self == py::self)
         .def(py::self != py::self)
         .def(py::self != py::self)
+        .def("__lt__", []
+        (const Type &a, const Scalar& b) -> Eigen::Matrix<bool,Eigen::Dynamic,Eigen::Dynamic>
+        {
+          return Eigen::Matrix<bool, Eigen::Dynamic, Eigen::Dynamic>(a.array() < b);
+        })
+        .def("__gt__", []
+        (const Type &a, const Scalar& b) -> Eigen::Matrix<bool,Eigen::Dynamic,Eigen::Dynamic>
+        {
+          return Eigen::Matrix<bool, Eigen::Dynamic, Eigen::Dynamic>(a.array() > b);
+        })
+        .def("__le__", []
+        (const Type &a, const Scalar& b) -> Eigen::Matrix<bool,Eigen::Dynamic,Eigen::Dynamic>
+        {
+          return Eigen::Matrix<bool, Eigen::Dynamic, Eigen::Dynamic>(a.array() <= b);
+        })
+        .def("__ge__", []
+        (const Type &a, const Scalar& b) -> Eigen::Matrix<bool,Eigen::Dynamic,Eigen::Dynamic>
+        {
+          return Eigen::Matrix<bool, Eigen::Dynamic, Eigen::Dynamic>(a.array() >= b);
+        })
 
 
         .def("transposeInPlace", [](Type &m) { m.transposeInPlace(); })
         .def("transposeInPlace", [](Type &m) { m.transposeInPlace(); })
         /* Other transformations */
         /* Other transformations */
@@ -603,6 +632,9 @@ void python_export_vector(py::module &m) {
 //    py::implicitly_convertible<py::buffer, Eigen::MatrixXi>();
 //    py::implicitly_convertible<py::buffer, Eigen::MatrixXi>();
     //py::implicitly_convertible<double, Eigen::MatrixXi>();
     //py::implicitly_convertible<double, Eigen::MatrixXi>();
 
 
+    /* Bindings for MatrixXb */
+    bind_eigen_2<Eigen::Matrix<bool,Eigen::Dynamic,Eigen::Dynamic> > (me, "MatrixXb");
+
     /* Bindings for MatrixXuc */
     /* Bindings for MatrixXuc */
     bind_eigen_2<Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> > (me, "MatrixXuc");
     bind_eigen_2<Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> > (me, "MatrixXuc");
     // py::implicitly_convertible<py::buffer, Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> >();
     // py::implicitly_convertible<py::buffer, Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> >();

文件差異過大導致無法顯示
+ 644 - 481
python/py_doc.cpp


+ 67 - 52
python/py_doc.h

@@ -1,67 +1,82 @@
-extern const char *__doc_igl_principal_curvature;
-extern const char *__doc_igl_local_basis;
-extern const char *__doc_igl_cotmatrix;
-extern const char *__doc_igl_floor;
-extern const char *__doc_igl_slice;
-extern const char *__doc_igl_per_face_normals;
-extern const char *__doc_igl_per_face_normals_stable;
-extern const char *__doc_igl_readOFF;
-extern const char *__doc_igl_per_vertex_normals;
-extern const char *__doc_igl_sortrows;
+extern const char *__doc_igl_active_set;
+extern const char *__doc_igl_arap_precomputation;
+extern const char *__doc_igl_arap_solve;
+extern const char *__doc_igl_avg_edge_length;
 extern const char *__doc_igl_barycenter;
 extern const char *__doc_igl_barycenter;
-extern const char *__doc_igl_jet;
+extern const char *__doc_igl_barycentric_coordinates;
+extern const char *__doc_igl_boundary_facets;
+extern const char *__doc_igl_boundary_loop;
 extern const char *__doc_igl_cat;
 extern const char *__doc_igl_cat;
-extern const char *__doc_igl_eigs;
-extern const char *__doc_igl_per_corner_normals;
-extern const char *__doc_igl_massmatrix;
 extern const char *__doc_igl_colon;
 extern const char *__doc_igl_colon;
-extern const char *__doc_igl_fit_rotations;
-extern const char *__doc_igl_fit_rotations_planar;
-extern const char *__doc_igl_fit_rotations_SSE;
-extern const char *__doc_igl_rotate_vectors;
-extern const char *__doc_igl_read_triangle_mesh;
-extern const char *__doc_igl_gaussian_curvature;
-extern const char *__doc_igl_avg_edge_length;
-extern const char *__doc_igl_barycentric_coordinates;
-extern const char *__doc_igl_lscm;
-extern const char *__doc_igl_find_cross_field_singularities;
-extern const char *__doc_igl_upsample;
-extern const char *__doc_igl_point_mesh_squared_distance;
-extern const char *__doc_igl_parula;
-extern const char *__doc_igl_setdiff;
+extern const char *__doc_igl_comb_cross_field;
 extern const char *__doc_igl_comb_frame_field;
 extern const char *__doc_igl_comb_frame_field;
-extern const char *__doc_igl_map_vertices_to_circle;
-extern const char *__doc_igl_writeOBJ;
-extern const char *__doc_igl_active_set;
-extern const char *__doc_igl_per_edge_normals;
-extern const char *__doc_igl_covariance_scatter_matrix;
-extern const char *__doc_igl_boundary_facets;
 extern const char *__doc_igl_compute_frame_field_bisectors;
 extern const char *__doc_igl_compute_frame_field_bisectors;
-extern const char *__doc_igl_edge_lengths;
-extern const char *__doc_igl_readOBJ;
+extern const char *__doc_igl_copyleft_cgal_mesh_boolean;
+extern const char *__doc_igl_copyleft_comiso_miq;
+extern const char *__doc_igl_copyleft_comiso_nrosy;
+extern const char *__doc_igl_copyleft_tetgen_tetrahedralize;
+extern const char *__doc_igl_cotmatrix;
+extern const char *__doc_igl_covariance_scatter_matrix;
+extern const char *__doc_igl_cross_field_missmatch;
 extern const char *__doc_igl_cut_mesh_from_singularities;
 extern const char *__doc_igl_cut_mesh_from_singularities;
-extern const char *__doc_igl_readDMAT;
 extern const char *__doc_igl_doublearea;
 extern const char *__doc_igl_doublearea;
 extern const char *__doc_igl_doublearea_single;
 extern const char *__doc_igl_doublearea_single;
 extern const char *__doc_igl_doublearea_quad;
 extern const char *__doc_igl_doublearea_quad;
+extern const char *__doc_igl_edge_lengths;
+extern const char *__doc_igl_eigs;
+extern const char *__doc_igl_embree_ambient_occlusion;
+extern const char *__doc_igl_find_cross_field_singularities;
+extern const char *__doc_igl_fit_rotations;
+extern const char *__doc_igl_fit_rotations_planar;
+extern const char *__doc_igl_fit_rotations_SSE;
+extern const char *__doc_igl_floor;
+extern const char *__doc_igl_gaussian_curvature;
+extern const char *__doc_igl_grad;
+extern const char *__doc_igl_harmonic;
+extern const char *__doc_igl_internal_angles;
+extern const char *__doc_igl_invert_diag;
+extern const char *__doc_igl_is_irregular_vertex;
+extern const char *__doc_igl_jet;
+extern const char *__doc_igl_local_basis;
+extern const char *__doc_igl_lscm;
+extern const char *__doc_igl_map_vertices_to_circle;
+extern const char *__doc_igl_massmatrix;
 extern const char *__doc_igl_min_quad_with_fixed_precompute;
 extern const char *__doc_igl_min_quad_with_fixed_precompute;
 extern const char *__doc_igl_min_quad_with_fixed_solve;
 extern const char *__doc_igl_min_quad_with_fixed_solve;
 extern const char *__doc_igl_min_quad_with_fixed;
 extern const char *__doc_igl_min_quad_with_fixed;
-extern const char *__doc_igl_writeMESH;
-extern const char *__doc_igl_unique;
-extern const char *__doc_igl_unique_rows;
-extern const char *__doc_igl_arap_precomputation;
-extern const char *__doc_igl_arap_solve;
-extern const char *__doc_igl_cross_field_missmatch;
-extern const char *__doc_igl_grad;
-extern const char *__doc_igl_slice_into;
-extern const char *__doc_igl_slice_tets;
 extern const char *__doc_igl_n_polyvector;
 extern const char *__doc_igl_n_polyvector;
-extern const char *__doc_igl_harmonic;
-extern const char *__doc_igl_boundary_loop;
+extern const char *__doc_igl_parula;
+extern const char *__doc_igl_per_corner_normals;
+extern const char *__doc_igl_per_edge_normals;
+extern const char *__doc_igl_per_face_normals;
+extern const char *__doc_igl_per_face_normals_stable;
+extern const char *__doc_igl_per_vertex_normals;
+extern const char *__doc_igl_planarize_quad_mesh;
+extern const char *__doc_igl_png_readPNG;
+extern const char *__doc_igl_png_writePNG;
+extern const char *__doc_igl_point_mesh_squared_distance;
 extern const char *__doc_igl_polar_svd;
 extern const char *__doc_igl_polar_svd;
-extern const char *__doc_igl_comb_cross_field;
-extern const char *__doc_igl_invert_diag;
+extern const char *__doc_igl_principal_curvature;
+extern const char *__doc_igl_quad_planarity;
+extern const char *__doc_igl_readDMAT;
 extern const char *__doc_igl_readMESH;
 extern const char *__doc_igl_readMESH;
-extern const char *__doc_igl_copyleft_comiso_miq;
-extern const char *__doc_igl_copyleft_comiso_nrosy;
+extern const char *__doc_igl_readOBJ;
+extern const char *__doc_igl_readOFF;
+extern const char *__doc_igl_read_triangle_mesh;
+extern const char *__doc_igl_rotate_vectors;
+extern const char *__doc_igl_setdiff;
+extern const char *__doc_igl_signed_distance;
+extern const char *__doc_igl_signed_distance_pseudonormal;
+extern const char *__doc_igl_signed_distance_winding_number;
+extern const char *__doc_igl_slice;
+extern const char *__doc_igl_slice_into;
+extern const char *__doc_igl_slice_mask;
+extern const char *__doc_igl_slice_tets;
+extern const char *__doc_igl_sortrows;
+extern const char *__doc_igl_triangle_triangulate;
+extern const char *__doc_igl_unique;
+extern const char *__doc_igl_unique_rows;
+extern const char *__doc_igl_unproject_onto_mesh;
+extern const char *__doc_igl_upsample;
+extern const char *__doc_igl_writeMESH;
+extern const char *__doc_igl_writeOBJ;

+ 110 - 96
python/py_igl.cpp

@@ -2,129 +2,143 @@
 
 
 #include "python_shared.h"
 #include "python_shared.h"
 
 
-#include <igl/readOFF.h>
-#include <igl/writeOBJ.h>
-#include <igl/per_face_normals.h>
-#include <igl/per_corner_normals.h>
-#include <igl/per_vertex_normals.h>
-#include <igl/gaussian_curvature.h>
-#include <igl/jet.h>
-#include <igl/read_triangle_mesh.h>
-#include <igl/cotmatrix.h>
-#include <igl/massmatrix.h>
-#include <igl/invert_diag.h>
-#include <igl/principal_curvature.h>
-#include <igl/parula.h>
-#include <igl/readDMAT.h>
-#include <igl/grad.h>
-#include <igl/avg_edge_length.h>
-#include <igl/barycenter.h>
-#include <igl/doublearea.h>
-#include <igl/floor.h>
-#include <igl/slice.h>
-#include <igl/slice_into.h>
-#include <igl/sortrows.h>
-#include <igl/colon.h>
-#include <igl/boundary_facets.h>
-#include <igl/unique.h>
-#include <igl/setdiff.h>
-#include <igl/min_quad_with_fixed.h>
+#include <igl/AABB.h>
+#include <igl/ARAPEnergyType.h>
+#include <igl/MeshBooleanType.h>
 #include <igl/SolverStatus.h>
 #include <igl/SolverStatus.h>
 #include <igl/active_set.h>
 #include <igl/active_set.h>
-#include <igl/eigs.h>
-#include <igl/readOBJ.h>
-#include <igl/harmonic.h>
 #include <igl/arap.h>
 #include <igl/arap.h>
-#include <igl/ARAPEnergyType.h>
+#include <igl/avg_edge_length.h>
+#include <igl/barycenter.h>
+#include <igl/barycentric_coordinates.h>
+#include <igl/boundary_facets.h>
 #include <igl/boundary_loop.h>
 #include <igl/boundary_loop.h>
-#include <igl/map_vertices_to_circle.h>
-#include <igl/lscm.h>
-#include <igl/local_basis.h>
-#include <igl/rotate_vectors.h>
-#include <igl/compute_frame_field_bisectors.h>
+#include <igl/cat.h>
+#include <igl/colon.h>
 #include <igl/comb_cross_field.h>
 #include <igl/comb_cross_field.h>
+#include <igl/comb_frame_field.h>
+#include <igl/compute_frame_field_bisectors.h>
+#include <igl/cotmatrix.h>
+#include <igl/covariance_scatter_matrix.h>
 #include <igl/cross_field_missmatch.h>
 #include <igl/cross_field_missmatch.h>
-#include <igl/find_cross_field_singularities.h>
 #include <igl/cut_mesh_from_singularities.h>
 #include <igl/cut_mesh_from_singularities.h>
-#include <igl/comb_frame_field.h>
+#include <igl/doublearea.h>
+#include <igl/edge_lengths.h>
+#include <igl/eigs.h>
+#include <igl/find_cross_field_singularities.h>
+#include <igl/fit_rotations.h>
+#include <igl/floor.h>
+#include <igl/gaussian_curvature.h>
+#include <igl/grad.h>
+#include <igl/harmonic.h>
+#include <igl/internal_angles.h>
+#include <igl/invert_diag.h>
+#include <igl/is_irregular_vertex.h>
+#include <igl/jet.h>
+#include <igl/local_basis.h>
+#include <igl/lscm.h>
+#include <igl/map_vertices_to_circle.h>
+#include <igl/massmatrix.h>
+#include <igl/min_quad_with_fixed.h>
 #include <igl/n_polyvector.h>
 #include <igl/n_polyvector.h>
-
+#include <igl/parula.h>
+#include <igl/per_corner_normals.h>
+#include <igl/per_edge_normals.h>
+#include <igl/per_face_normals.h>
+#include <igl/per_vertex_normals.h>
+#include <igl/planarize_quad_mesh.h>
 #include <igl/point_mesh_squared_distance.h>
 #include <igl/point_mesh_squared_distance.h>
-#include <igl/AABB.h>
+#include <igl/polar_svd.h>
+#include <igl/principal_curvature.h>
+#include <igl/quad_planarity.h>
+#include <igl/readDMAT.h>
 #include <igl/readMESH.h>
 #include <igl/readMESH.h>
-#include <igl/writeMESH.h>
+#include <igl/readOBJ.h>
+#include <igl/readOFF.h>
+#include <igl/read_triangle_mesh.h>
+#include <igl/rotate_vectors.h>
+#include <igl/setdiff.h>
+#include <igl/signed_distance.h>
+#include <igl/slice.h>
+#include <igl/slice_into.h>
+#include <igl/slice_mask.h>
 #include <igl/slice_tets.h>
 #include <igl/slice_tets.h>
-#include <igl/edge_lengths.h>
+#include <igl/sortrows.h>
+#include <igl/unique.h>
+#include <igl/unproject_onto_mesh.h>
 #include <igl/upsample.h>
 #include <igl/upsample.h>
-#include <igl/cat.h>
-#include <igl/per_edge_normals.h>
-#include <igl/barycentric_coordinates.h>
-#include <igl/fit_rotations.h>
-#include <igl/polar_svd.h>
-#include <igl/covariance_scatter_matrix.h>
+#include <igl/writeMESH.h>
+#include <igl/writeOBJ.h>
 
 
 
 
 void python_export_igl(py::module &m)
 void python_export_igl(py::module &m)
 {
 {
-#include "py_igl/py_readOFF.cpp"
-#include "py_igl/py_writeOBJ.cpp"
-#include "py_igl/py_per_face_normals.cpp"
-#include "py_igl/py_per_corner_normals.cpp"
-#include "py_igl/py_per_vertex_normals.cpp"
-#include "py_igl/py_gaussian_curvature.cpp"
-#include "py_igl/py_jet.cpp"
-#include "py_igl/py_read_triangle_mesh.cpp"
-#include "py_igl/py_cotmatrix.cpp"
-#include "py_igl/py_massmatrix.cpp"
-#include "py_igl/py_invert_diag.cpp"
-#include "py_igl/py_principal_curvature.cpp"
-#include "py_igl/py_parula.cpp"
-#include "py_igl/py_readDMAT.cpp"
-#include "py_igl/py_grad.cpp"
-#include "py_igl/py_avg_edge_length.cpp"
-#include "py_igl/py_barycenter.cpp"
-#include "py_igl/py_doublearea.cpp"
-#include "py_igl/py_floor.cpp"
-#include "py_igl/py_slice.cpp"
-#include "py_igl/py_slice_into.cpp"
-#include "py_igl/py_sortrows.cpp"
-#include "py_igl/py_colon.cpp"
-#include "py_igl/py_boundary_facets.cpp"
-#include "py_igl/py_unique.cpp"
-#include "py_igl/py_setdiff.cpp"
-#include "py_igl/py_min_quad_with_fixed.cpp"
+#include "py_igl/py_AABB.cpp"
+#include "py_igl/py_ARAPEnergyType.cpp"
+#include "py_igl/py_MeshBooleanType.cpp"
 #include "py_igl/py_SolverStatus.cpp"
 #include "py_igl/py_SolverStatus.cpp"
 #include "py_igl/py_active_set.cpp"
 #include "py_igl/py_active_set.cpp"
-#include "py_igl/py_eigs.cpp"
-#include "py_igl/py_readOBJ.cpp"
-#include "py_igl/py_harmonic.cpp"
-#include "py_igl/py_ARAPEnergyType.cpp"
 #include "py_igl/py_arap.cpp"
 #include "py_igl/py_arap.cpp"
+#include "py_igl/py_avg_edge_length.cpp"
+#include "py_igl/py_barycenter.cpp"
+#include "py_igl/py_barycentric_coordinates.cpp"
+#include "py_igl/py_boundary_facets.cpp"
 #include "py_igl/py_boundary_loop.cpp"
 #include "py_igl/py_boundary_loop.cpp"
-#include "py_igl/py_map_vertices_to_circle.cpp"
-#include "py_igl/py_lscm.cpp"
-#include "py_igl/py_local_basis.cpp"
-#include "py_igl/py_rotate_vectors.cpp"
-#include "py_igl/py_compute_frame_field_bisectors.cpp"
+#include "py_igl/py_cat.cpp"
+#include "py_igl/py_colon.cpp"
 #include "py_igl/py_comb_cross_field.cpp"
 #include "py_igl/py_comb_cross_field.cpp"
+#include "py_igl/py_comb_frame_field.cpp"
+#include "py_igl/py_compute_frame_field_bisectors.cpp"
+#include "py_igl/py_cotmatrix.cpp"
+#include "py_igl/py_covariance_scatter_matrix.cpp"
 #include "py_igl/py_cross_field_missmatch.cpp"
 #include "py_igl/py_cross_field_missmatch.cpp"
-#include "py_igl/py_find_cross_field_singularities.cpp"
 #include "py_igl/py_cut_mesh_from_singularities.cpp"
 #include "py_igl/py_cut_mesh_from_singularities.cpp"
-#include "py_igl/py_comb_frame_field.cpp"
+#include "py_igl/py_doublearea.cpp"
+#include "py_igl/py_edge_lengths.cpp"
+#include "py_igl/py_eigs.cpp"
+#include "py_igl/py_find_cross_field_singularities.cpp"
+#include "py_igl/py_fit_rotations.cpp"
+#include "py_igl/py_floor.cpp"
+#include "py_igl/py_gaussian_curvature.cpp"
+#include "py_igl/py_grad.cpp"
+#include "py_igl/py_harmonic.cpp"
+#include "py_igl/py_internal_angles.cpp"
+#include "py_igl/py_invert_diag.cpp"
+#include "py_igl/py_is_irregular_vertex.cpp"
+#include "py_igl/py_jet.cpp"
+#include "py_igl/py_local_basis.cpp"
+#include "py_igl/py_lscm.cpp"
+#include "py_igl/py_map_vertices_to_circle.cpp"
+#include "py_igl/py_massmatrix.cpp"
+#include "py_igl/py_min_quad_with_fixed.cpp"
 #include "py_igl/py_n_polyvector.cpp"
 #include "py_igl/py_n_polyvector.cpp"
-
+#include "py_igl/py_parula.cpp"
+#include "py_igl/py_per_corner_normals.cpp"
+#include "py_igl/py_per_edge_normals.cpp"
+#include "py_igl/py_per_face_normals.cpp"
+#include "py_igl/py_per_vertex_normals.cpp"
+#include "py_igl/py_planarize_quad_mesh.cpp"
 #include "py_igl/py_point_mesh_squared_distance.cpp"
 #include "py_igl/py_point_mesh_squared_distance.cpp"
-#include "py_igl/py_AABB.cpp"
+#include "py_igl/py_polar_svd.cpp"
+#include "py_igl/py_principal_curvature.cpp"
+#include "py_igl/py_quad_planarity.cpp"
+#include "py_igl/py_readDMAT.cpp"
 #include "py_igl/py_readMESH.cpp"
 #include "py_igl/py_readMESH.cpp"
-#include "py_igl/py_writeMESH.cpp"
+#include "py_igl/py_readOBJ.cpp"
+#include "py_igl/py_readOFF.cpp"
+#include "py_igl/py_read_triangle_mesh.cpp"
+#include "py_igl/py_rotate_vectors.cpp"
+#include "py_igl/py_setdiff.cpp"
+#include "py_igl/py_signed_distance.cpp"
+#include "py_igl/py_slice.cpp"
+#include "py_igl/py_slice_into.cpp"
+#include "py_igl/py_slice_mask.cpp"
 #include "py_igl/py_slice_tets.cpp"
 #include "py_igl/py_slice_tets.cpp"
-#include "py_igl/py_edge_lengths.cpp"
+#include "py_igl/py_sortrows.cpp"
+#include "py_igl/py_unique.cpp"
+#include "py_igl/py_unproject_onto_mesh.cpp"
 #include "py_igl/py_upsample.cpp"
 #include "py_igl/py_upsample.cpp"
-#include "py_igl/py_cat.cpp"
-#include "py_igl/py_per_edge_normals.cpp"
-#include "py_igl/py_barycentric_coordinates.cpp"
-#include "py_igl/py_fit_rotations.cpp"
-#include "py_igl/py_polar_svd.cpp"
-#include "py_igl/py_covariance_scatter_matrix.cpp"
+#include "py_igl/py_writeMESH.cpp"
+#include "py_igl/py_writeOBJ.cpp"
 
 
 }
 }

+ 107 - 0
python/py_igl/copyleft/cgal/py_mesh_boolean.cpp

@@ -0,0 +1,107 @@
+// COMPLETE BINDINGS ========================
+
+m.def("mesh_boolean", []
+(
+  const Eigen::MatrixXd& VA,
+  const Eigen::MatrixXi& FA,
+  const Eigen::MatrixXd& VB,
+  const Eigen::MatrixXi& FB,
+  igl::MeshBooleanType & type,
+  Eigen::MatrixXd& VC,
+  Eigen::MatrixXi& FC,
+  Eigen::MatrixXi& J
+)
+{
+  return igl::copyleft::cgal::mesh_boolean(VA, FA, VB, FB, type, VC, FC, J);
+}, __doc_igl_copyleft_cgal_mesh_boolean,
+py::arg("VA"), py::arg("FA"), py::arg("VB"), py::arg("FB"), py::arg("type"), py::arg("VC"), py::arg("FC"), py::arg("J"));
+
+
+m.def("mesh_boolean", []
+(
+  const Eigen::MatrixXd& VA,
+  const Eigen::MatrixXi& FA,
+  const Eigen::MatrixXd& VB,
+  const Eigen::MatrixXi& FB,
+  const std::string & type_str,
+  Eigen::MatrixXd& VC,
+  Eigen::MatrixXi& FC,
+  Eigen::MatrixXi& J
+)
+{
+  return igl::copyleft::cgal::mesh_boolean(VA, FA, VB, FB, type_str, VC, FC, J);
+}, __doc_igl_copyleft_cgal_mesh_boolean,
+py::arg("VA"), py::arg("FA"), py::arg("VB"), py::arg("FB"), py::arg("type_str"), py::arg("VC"), py::arg("FC"), py::arg("J"));
+
+m.def("mesh_boolean", []
+(
+  const Eigen::MatrixXd& VA,
+  const Eigen::MatrixXi& FA,
+  const Eigen::MatrixXd& VB,
+  const Eigen::MatrixXi& FB,
+  const igl::MeshBooleanType & type,
+  Eigen::MatrixXd& VC,
+  Eigen::MatrixXi& FC
+)
+{
+  return igl::copyleft::cgal::mesh_boolean(VA, FA, VB, FB, type, VC, FC);
+}, __doc_igl_copyleft_cgal_mesh_boolean,
+py::arg("VA"), py::arg("FA"), py::arg("VB"), py::arg("FB"), py::arg("type"), py::arg("VC"), py::arg("FC"));
+
+
+
+// INCOMPLETE BINDINGS ========================
+
+
+
+
+//m.def("mesh_boolean", []
+//(
+//  const Eigen::MatrixXd& VA,
+//  const Eigen::MatrixXd& FA,
+//  const Eigen::MatrixXd& VB,
+//  const Eigen::MatrixXd& FB,
+//  std::function<int (const Eigen::Matrix<int, 1, Eigen::Dynamic>)> & wind_num_op,
+//  std::function<int (const int, const int)> & keep,
+//  Eigen::MatrixXd& VC,
+//  Eigen::MatrixXd& FC,
+//  Eigen::MatrixXd& J
+//)
+//{
+//  return igl::copyleft::cgal::mesh_boolean(VA, FA, VB, FB, wind_num_op, keep, VC, FC, J);
+//}, __doc_igl_copyleft_cgal_mesh_boolean,
+//py::arg("VA"), py::arg("FA"), py::arg("VB"), py::arg("FB"), py::arg("wind_num_op"), py::arg("keep"), py::arg("VC"), py::arg("FC"), py::arg("J"));
+
+//m.def("mesh_boolean", []
+//(
+//  std::vector<DerivedV> & Vlist,
+//  std::vector<DerivedF> & Flist,
+//  std::function<int (const Eigen::Matrix<int, 1, Eigen::Dynamic>)> & wind_num_op,
+//  std::function<int (const int, const int)> & keep,
+//  Eigen::MatrixXd& VC,
+//  Eigen::MatrixXd& FC,
+//  Eigen::MatrixXd& J
+//)
+//{
+//  return igl::copyleft::cgal::mesh_boolean(Vlist, Flist, wind_num_op, keep, VC, FC, J);
+//}, __doc_igl_copyleft_cgal_mesh_boolean,
+//py::arg("Vlist"), py::arg("Flist"), py::arg("wind_num_op"), py::arg("keep"), py::arg("VC"), py::arg("FC"), py::arg("J"));
+
+//m.def("mesh_boolean", []
+//(
+//  const Eigen::MatrixXd& VV,
+//  const Eigen::MatrixXd& FF,
+//  const Eigen::MatrixXd& sizes,
+//  std::function<int (const Eigen::Matrix<int, 1, Eigen::Dynamic>)> & wind_num_op,
+//  std::function<int (const int, const int)> & keep,
+//  Eigen::MatrixXd& VC,
+//  Eigen::MatrixXd& FC,
+//  Eigen::MatrixXd& J
+//)
+//{
+//  return igl::copyleft::cgal::mesh_boolean(VV, FF, sizes, wind_num_op, keep, VC, FC, J);
+//}, __doc_igl_copyleft_cgal_mesh_boolean,
+//py::arg("VV"), py::arg("FF"), py::arg("sizes"), py::arg("wind_num_op"), py::arg("keep"), py::arg("VC"), py::arg("FC"), py::arg("J"));
+
+
+

+ 16 - 0
python/py_igl/copyleft/tetgen/py_tetrahedralize.cpp

@@ -0,0 +1,16 @@
+
+m.def("tetrahedralize", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F,
+  const std::string switches,
+  Eigen::MatrixXd& TV,
+  Eigen::MatrixXi& TT,
+  Eigen::MatrixXi& TF
+)
+{
+  return igl::copyleft::tetgen::tetrahedralize(V, F, switches, TV, TT, TF);
+}, __doc_igl_copyleft_tetgen_tetrahedralize,
+py::arg("V"), py::arg("F"), py::arg("switches"), py::arg("TV"), py::arg("TT"), py::arg("TF"));
+
+

+ 16 - 0
python/py_igl/embree/py_ambient_occlusion.cpp

@@ -0,0 +1,16 @@
+
+
+m.def("ambient_occlusion", []
+(
+  const Eigen::MatrixXd& V,
+  const Eigen::MatrixXi& F,
+  const Eigen::MatrixXd& P,
+  const Eigen::MatrixXd& N,
+  const int num_samples,
+  Eigen::MatrixXd& S
+)
+{
+  return igl::embree::ambient_occlusion(V, F, P, N, num_samples, S);
+}, __doc_igl_embree_ambient_occlusion,
+py::arg("V"), py::arg("F"), py::arg("P"), py::arg("N"), py::arg("num_samples"), py::arg("S"));
+

+ 14 - 0
python/py_igl/png/py_readPNG.cpp

@@ -0,0 +1,14 @@
+
+m.def("readPNG", []
+(
+  const std::string png_file,
+  Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic> & R,
+  Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic> & G,
+  Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic> & B,
+  Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic> & A
+)
+{
+  return igl::png::readPNG(png_file, R, G, B, A);
+}, __doc_igl_png_readPNG,
+py::arg("png_file"), py::arg("R"), py::arg("G"), py::arg("B"), py::arg("A"));
+

+ 15 - 0
python/py_igl/png/py_writePNG.cpp

@@ -0,0 +1,15 @@
+
+
+m.def("writePNG", []
+(
+  const Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic> & R,
+  const Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic> & G,
+  const Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic> & B,
+  const Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic> & A,
+  const std::string png_file
+)
+{
+  return igl::png::writePNG(R, G, B, A, png_file);
+}, __doc_igl_png_writePNG,
+py::arg("R"), py::arg("G"), py::arg("B"), py::arg("A"), py::arg("png_file"));
+

+ 1 - 1
python/py_igl/py_AABB.cpp

@@ -5,7 +5,7 @@ AABB
 .def(py::init<const igl::AABB<Eigen::MatrixXd,3>& >())
 .def(py::init<const igl::AABB<Eigen::MatrixXd,3>& >())
 .def("init",[](igl::AABB<Eigen::MatrixXd,3>& tree, const Eigen::MatrixXd& V, const Eigen::MatrixXi& Ele)
 .def("init",[](igl::AABB<Eigen::MatrixXd,3>& tree, const Eigen::MatrixXd& V, const Eigen::MatrixXi& Ele)
 {
 {
-    return tree.init(V, Ele, Eigen::Matrix<double, Eigen::Dynamic, 3>(), Eigen::Matrix<double, Eigen::Dynamic, 3>(), Eigen::MatrixXi(), 0); 
+    return tree.init(V, Ele, Eigen::Matrix<double, Eigen::Dynamic, 3>(), Eigen::Matrix<double, Eigen::Dynamic, 3>(), Eigen::VectorXi(), 0); 
 })
 })
 .def("squared_distance", [](const igl::AABB<Eigen::MatrixXd,3>& tree, const Eigen::MatrixXd& V, const Eigen::MatrixXi& Ele, const Eigen::MatrixXd& P, Eigen::MatrixXd& sqrD, Eigen::MatrixXi& I, Eigen::MatrixXd& C)
 .def("squared_distance", [](const igl::AABB<Eigen::MatrixXd,3>& tree, const Eigen::MatrixXd& V, const Eigen::MatrixXi& Ele, const Eigen::MatrixXd& P, Eigen::MatrixXd& sqrD, Eigen::MatrixXi& I, Eigen::MatrixXd& C)
 {
 {

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