Эх сурвалжийг харах

aweful partial rebase to avoid breaking current project

Former-commit-id: c735b591c2bec3990ac3342736b6bc7d585b7b9d
Romain Prévost 9 жил өмнө
parent
commit
2303ad07bd
100 өөрчлөгдсөн 4962 нэмэгдсэн , 3496 устгасан
  1. 1 0
      .gitignore
  2. 0 12
      .gitmodules
  3. 9 2
      README.md
  4. 62 0
      before-submitting-pull-request.md
  5. 198 14
      include/igl/AABB.h
  6. 7 5
      include/igl/Camera.h
  7. 25 0
      include/igl/Hit.h
  8. 11 0
      include/igl/Singular_Value_Decomposition_Preamble.hpp
  9. 2 2
      include/igl/active_set.cpp
  10. 6 7
      include/igl/adjacency_matrix.cpp
  11. 2 2
      include/igl/adjacency_matrix.h
  12. 134 0
      include/igl/ambient_occlusion.cpp
  13. 80 0
      include/igl/ambient_occlusion.h
  14. 1 0
      include/igl/angle_bound_frame_fields.cpp
  15. 0 1
      include/igl/arap.cpp
  16. 3 5
      include/igl/arap_dof.cpp
  17. 8 10
      include/igl/average_onto_vertices.cpp
  18. 5 6
      include/igl/average_onto_vertices.h
  19. 5 8
      include/igl/barycenter.h
  20. 0 1
      include/igl/bbw/bbw.cpp
  21. 0 1
      include/igl/bfs_orient.cpp
  22. 0 185
      include/igl/boolean/CSGTree.h
  23. 0 26
      include/igl/boolean/MeshBooleanType.h
  24. 0 38
      include/igl/boolean/from_cork_mesh.h
  25. 0 404
      include/igl/boolean/mesh_boolean.cpp
  26. 0 110
      include/igl/boolean/mesh_boolean.h
  27. 0 54
      include/igl/boolean/mesh_boolean_cork.h
  28. 0 41
      include/igl/boolean/string_to_mesh_boolean_type.h
  29. 0 38
      include/igl/boolean/to_cork_mesh.h
  30. 4 1
      include/igl/boundary_conditions.cpp
  31. 3 3
      include/igl/boundary_loop.cpp
  32. 0 28
      include/igl/cgal/RemeshSelfIntersectionsParam.h
  33. 0 34
      include/igl/cgal/assign_scalar.h
  34. 0 44
      include/igl/cgal/complex_to_mesh.h
  35. 0 270
      include/igl/cgal/intersect_other.cpp
  36. 0 106
      include/igl/cgal/intersect_other.h
  37. 0 63
      include/igl/cgal/mesh_to_cgal_triangle_list.cpp
  38. 0 41
      include/igl/cgal/mesh_to_cgal_triangle_list.h
  39. 0 39
      include/igl/cgal/mesh_to_polyhedron.h
  40. 0 393
      include/igl/cgal/order_facets_around_edge.cpp
  41. 0 70
      include/igl/cgal/order_facets_around_edge.h
  42. 0 104
      include/igl/cgal/order_facets_around_edges.h
  43. 0 51
      include/igl/cgal/outer_hull.h
  44. 0 44
      include/igl/cgal/peel_outer_hull_layers.h
  45. 0 85
      include/igl/cgal/point_mesh_squared_distance.h
  46. 0 59
      include/igl/cgal/points_inside_component.h
  47. 0 37
      include/igl/cgal/polyhedron_to_mesh.h
  48. 0 43
      include/igl/cgal/projected_delaunay.h
  49. 0 328
      include/igl/cgal/remesh_intersections.cpp
  50. 0 77
      include/igl/cgal/remesh_intersections.h
  51. 0 92
      include/igl/cgal/remesh_self_intersections.cpp
  52. 0 85
      include/igl/cgal/remesh_self_intersections.h
  53. 0 51
      include/igl/cgal/signed_distance_isosurface.h
  54. 1 0
      include/igl/colon.cpp
  55. 2 1
      include/igl/comb_cross_field.cpp
  56. 1 1
      include/igl/comb_frame_field.cpp
  57. 3 1
      include/igl/comb_line_field.cpp
  58. 1 1
      include/igl/comiso/frame_field.cpp
  59. 1 1
      include/igl/comiso/miq.cpp
  60. 1 1
      include/igl/comiso/nrosy.cpp
  61. 1 1
      include/igl/compute_frame_field_bisectors.cpp
  62. 14 0
      include/igl/copyleft/README.md
  63. 131 0
      include/igl/copyleft/boolean/BinaryWindingNumberOperations.h
  64. 189 0
      include/igl/copyleft/boolean/CSGTree.h
  65. 29 0
      include/igl/copyleft/boolean/MeshBooleanType.h
  66. 3 3
      include/igl/copyleft/boolean/from_cork_mesh.cpp
  67. 41 0
      include/igl/copyleft/boolean/from_cork_mesh.h
  68. 349 0
      include/igl/copyleft/boolean/mesh_boolean.cpp
  69. 166 0
      include/igl/copyleft/boolean/mesh_boolean.h
  70. 3 3
      include/igl/copyleft/boolean/mesh_boolean_cork.cpp
  71. 57 0
      include/igl/copyleft/boolean/mesh_boolean_cork.h
  72. 367 0
      include/igl/copyleft/boolean/minkowski_sum.cpp
  73. 110 0
      include/igl/copyleft/boolean/minkowski_sum.h
  74. 2 2
      include/igl/copyleft/boolean/string_to_mesh_boolean_type.cpp
  75. 44 0
      include/igl/copyleft/boolean/string_to_mesh_boolean_type.h
  76. 3 3
      include/igl/copyleft/boolean/to_cork_mesh.cpp
  77. 41 0
      include/igl/copyleft/boolean/to_cork_mesh.h
  78. 0 0
      include/igl/copyleft/cgal/CGAL_includes.hpp
  79. 31 0
      include/igl/copyleft/cgal/RemeshSelfIntersectionsParam.h
  80. 362 329
      include/igl/copyleft/cgal/SelfIntersectMesh.h
  81. 10 4
      include/igl/copyleft/cgal/assign_scalar.cpp
  82. 37 0
      include/igl/copyleft/cgal/assign_scalar.h
  83. 453 0
      include/igl/copyleft/cgal/closest_facet.cpp
  84. 76 0
      include/igl/copyleft/cgal/closest_facet.h
  85. 8 7
      include/igl/copyleft/cgal/complex_to_mesh.cpp
  86. 47 0
      include/igl/copyleft/cgal/complex_to_mesh.h
  87. 6 6
      include/igl/copyleft/cgal/component_inside_component.cpp
  88. 6 3
      include/igl/copyleft/cgal/component_inside_component.h
  89. 556 0
      include/igl/copyleft/cgal/extract_cells.cpp
  90. 115 0
      include/igl/copyleft/cgal/extract_cells.h
  91. 273 0
      include/igl/copyleft/cgal/intersect_other.cpp
  92. 109 0
      include/igl/copyleft/cgal/intersect_other.h
  93. 65 0
      include/igl/copyleft/cgal/mesh_to_cgal_triangle_list.cpp
  94. 44 0
      include/igl/copyleft/cgal/mesh_to_cgal_triangle_list.h
  95. 2 2
      include/igl/copyleft/cgal/mesh_to_polyhedron.cpp
  96. 42 0
      include/igl/copyleft/cgal/mesh_to_polyhedron.h
  97. 406 0
      include/igl/copyleft/cgal/order_facets_around_edge.cpp
  98. 74 0
      include/igl/copyleft/cgal/order_facets_around_edge.h
  99. 7 7
      include/igl/copyleft/cgal/order_facets_around_edges.cpp
  100. 107 0
      include/igl/copyleft/cgal/order_facets_around_edges.h

+ 1 - 0
.gitignore

@@ -92,3 +92,4 @@ tests/build
 tests/bin
 python/build3
 *.pyc
+python/build4

+ 0 - 12
.gitmodules

@@ -9,15 +9,3 @@ url=https://github.com/libigl/nanogui.git
 [submodule "external/pybind11"]
 	path = external/pybind11
 	url = https://github.com/wjakob/pybind11.git
-[submodule "external/tetgen"]
-	path = external/tetgen
-	url = https://github.com/libigl/tetgen.git
-[submodule "external/triangle"]
-	path = external/triangle
-	url = https://github.com/libigl/triangle.git
-[submodule "external/tinyxml2"]
-	path = external/tinyxml2
-	url = https://github.com/leethomason/tinyxml2.git
-[submodule "external/cgal"]
-	path = external/cgal
-	url = https://github.com/CGAL/cgal.git

+ 9 - 2
README.md

@@ -190,6 +190,8 @@ Libigl is used by many research groups around the world. In 2015, it won the
 Eurographics/ACM Symposium on Geometry Processing software award. Here are a
 few labs/companies/institutions using libigl:
 
+ - [Adobe Research](http://www.adobe.com/technology/)  
+ - [Pixar Research](http://graphics.pixar.com/research/)
  - [Spine by Esoteric Software](http://esotericsoftware.com/) is an animation tool dedicated to 2D characters.
  - Columbia University, [Columbia Computer Graphics Group](http://www.cs.columbia.edu/cg/), USA
  - [Cornell University](http://www.graphics.cornell.edu/), USA
@@ -200,13 +202,18 @@ few labs/companies/institutions using libigl:
  - [National Institute of Informatics](http://www.nii.ac.jp/en/), Japan
  - New York University, [Media Research Lab](http://mrl.nyu.edu/), USA
  - NYUPoly, [Game Innovation Lab](http://game.engineering.nyu.edu/), USA
- - [Telecom ParisTech](http://www.telecom-paristech.fr/en/formation-et-innovation-dans-le-numerique.html), Paris, France
+ - [TU Berlin](https://www.cg.tu-berlin.de), Germany
  - [TU Delft](http://www.tudelft.nl/en/), Netherlands
+ - [Telecom ParisTech](http://www.telecom-paristech.fr/en/formation-et-innovation-dans-le-numerique.html), Paris, France
  - [Universidade Federal de Santa Catarina](http://mtm.ufsc.br/~leo/), Brazil
- - [Università della Svizzera Italiana](http://www.usi.ch/en), Switzerland
  - [University College London](http://vecg.cs.ucl.ac.uk/), England
+ - [University of California Berkeley](http://vis.berkeley.edu/), USA
  - [University of Cambridge](http://www.cam.ac.uk/), England
  - [University of Pennsylvania](http://cg.cis.upenn.edu/), USA
+ - [University of Texas at Austin](http://www.cs.utexas.edu/users/evouga/), USA
+ - [University of Victoria](https://www.csc.uvic.ca/Research/graphics/), Canada
+ - [Università della Svizzera Italiana](http://www.usi.ch/en), Switzerland
+ - [Université Toulouse III Paul Sabatier](http://www.univ-tlse3.fr/), France
 
 
 ## Contact

+ 62 - 0
before-submitting-pull-request.md

@@ -0,0 +1,62 @@
+# Before submitting a pull request
+
+There are a variety of things you can do before submitting a pull request that
+will reduce the effort on the libigl team to merge your code and increase the
+likelihood that the merge ever happens.
+
+  1. Test your code and submit a unit test as part of the pull request
+  2. Verify that your code matches the [libigl style
+  guidelines](style-guidelines.md)
+  3. Run the [exhaustive build test](#exhaustivebuildtest) below
+
+## Exhaustive build test
+
+This script will `git clone` libigl to a temporary directory and build 
+
+  1. the static libigl library, 
+  2. the tutorial using the default header only libigl, and 
+  3. the tutorial using the static library libigl.
+  
+Eventually this script should also run the unit tests.
+
+```bash
+# In scripts/clone_and_build.sh add your email address to the line:
+# `recipients="alecjacobson@gmail.com,youremail@domain.com"`
+# In your email client (e.g. gmail) create a filter to prevent emails 
+# from your local machine from going to spam
+scripts/clone_and_build.sh
+```
+
+### Direct test of tutorial using static library
+
+This part of the `clone_and_build.sh` script catches 99% of the compilation
+issues that _don't_ show up when testing:
+
+```bash
+cd tutorial/
+mkdir build-use-static
+cd build-use-static
+cmake -DCMAKE_BUILD_TYPE=Release -DLIBIGL_USE_STATIC_LIBRARY=ON ..
+make
+```
+
+A typical issue is a missing template instantiation (symbol not found):
+
+    "void igl::cgal::points_inside_component<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&)", referenced from:
+        void igl::cgal::outer_hull<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&) in libiglboolean.a(mesh_boolean.cpp.o)
+        void igl::cgal::outer_hull<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&) in libiglboolean.a(mesh_boolean.cpp.o)
+
+This looks like a mess, but the solution is very simple. Copy the chunk inside of the quotes, in this case:
+
+    "void igl::cgal::points_inside_component<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&)"
+
+and paste it at the bottom of the relevant .cpp file with the word template in front of it and a semicolon at then. In this case, in include/igl/cgal/points_inside_component.cpp:
+
+```cpp
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template specialization
+template void igl::cgal::points_inside_component<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+#endif
+```
+
+Then "rinse and repeat".

+ 198 - 14
include/igl/AABB.h

@@ -8,6 +8,7 @@
 #ifndef IGL_AABB_H
 #define IGL_AABB_H
 
+#include "Hit.h"
 #include <Eigen/Core>
 #include <Eigen/Geometry>
 #include <vector>
@@ -134,7 +135,8 @@ public:
           const Eigen::VectorXi & I);
       // Return whether at leaf node
       inline bool is_leaf() const;
-      // Find the indices of elements containing given point.
+      // 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).
       //
       // Inputs:
       //   V  #V by dim list of mesh vertex positions. **Should be same as used to
@@ -185,19 +187,43 @@ public:
       // Known bugs: currently assumes Elements are triangles regardless of
       // dimension.
       inline Scalar squared_distance(
-          const Eigen::PlainObjectBase<DerivedV> & V,
-          const Eigen::MatrixXi & Ele, 
-          const RowVectorDIMS & p,
-          int & i,
-          RowVectorDIMS & c) const;
+        const Eigen::PlainObjectBase<DerivedV> & V,
+        const Eigen::MatrixXi & Ele, 
+        const RowVectorDIMS & p,
+        int & i,
+        RowVectorDIMS & c) const;
 //private:
       inline Scalar squared_distance(
-          const Eigen::PlainObjectBase<DerivedV> & V,
-          const Eigen::MatrixXi & Ele, 
-          const RowVectorDIMS & p,
-          const Scalar min_sqr_d,
-          int & i,
-          RowVectorDIMS & c) const;
+        const Eigen::PlainObjectBase<DerivedV> & V,
+        const Eigen::MatrixXi & Ele, 
+        const RowVectorDIMS & p,
+        const Scalar min_sqr_d,
+        int & i,
+        RowVectorDIMS & c) const;
+      // All hits
+      inline bool intersect_ray(
+        const Eigen::PlainObjectBase<DerivedV> & V,
+        const Eigen::MatrixXi & Ele, 
+        const RowVectorDIMS & origin,
+        const RowVectorDIMS & dir,
+        std::vector<igl::Hit> & hits) const;
+      // First hit
+      inline bool intersect_ray(
+        const Eigen::PlainObjectBase<DerivedV> & V,
+        const Eigen::MatrixXi & Ele, 
+        const RowVectorDIMS & origin,
+        const RowVectorDIMS & dir,
+        igl::Hit & hit) const;
+//private:
+      inline bool 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;
+
+
 public:
       template <
         typename DerivedP, 
@@ -281,10 +307,14 @@ public:
 #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>
@@ -627,7 +657,6 @@ igl::AABB<DerivedV,DIM>::squared_distance(
 {
   using namespace Eigen;
   using namespace std;
-  using namespace igl;
   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)
@@ -996,7 +1025,6 @@ inline void igl::AABB<DerivedV,DIM>::leaf_squared_distance(
   RowVectorDIMS & c) const
 {
   using namespace Eigen;
-  using namespace igl;
   using namespace std;
 
   // Simplex size
@@ -1149,4 +1177,160 @@ igl::AABB<DerivedV,DIM>::barycentric_coordinates(
   bary(0) = 1.0f - bary(1) - bary(2);
 }
 
+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).eval(),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).eval(),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).eval(),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

+ 7 - 5
include/igl/Camera.h

@@ -66,11 +66,13 @@ namespace igl
       //     glMultMatrixd(projection().data());
       //
       inline Eigen::Matrix4d projection() const;
-      // Return an Affine transformation (rigid actually) that takes a world 3d coordinate and
-      // transforms it into the relative camera coordinates.
+      // Return an Affine transformation (rigid actually) that 
+      // takes relative coordinates and tramsforms them into world 3d
+      // coordinates: moves the camera into the scene.
       inline Eigen::Affine3d affine() const;
-      // Return an Affine transformation (rigid actually) that takes relative
-      // coordinates and tramsforms them into world 3d coordinates.
+      // Return an Affine transformation (rigid actually) that puts the takes a
+      // world 3d coordinate and transforms it into the relative camera
+      // coordinates: moves the scene in front of the camera.
       //
       // Note:
       //
@@ -81,7 +83,7 @@ namespace igl
       //
       // Is equivalent to
       //
-      //     glMultMatrixd(camera.affine().matrix().data());
+      //     glMultMatrixd(camera.inverse().matrix().data());
       //
       // See also: affine, eye, at, up
       inline Eigen::Affine3d inverse() const;

+ 25 - 0
include/igl/Hit.h

@@ -0,0 +1,25 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
+//               2014 Christian Schüller <schuellchr@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_HIT_H
+#define IGL_HIT_H
+
+namespace igl
+{
+  // Reimplementation of the embree::Hit struct from embree1.0
+  // 
+  // TODO: template on floating point type
+  struct Hit
+  {
+    int id; // primitive id
+    int gid; // geometry id
+    float u,v; // barycentric coordinates
+    float t; // distance = direction*t to intersection
+  };
+}
+#endif 

+ 11 - 0
include/igl/Singular_Value_Decomposition_Preamble.hpp

@@ -19,6 +19,17 @@
 #include <iostream>
 #endif
 
+// Prevent warnings
+#ifdef ENABLE_SCALAR_IMPLEMENTATION
+#  undef ENABLE_SCALAR_IMPLEMENTATION
+#endif
+#ifdef ENABLE_SSE_IMPLEMENTATION
+#  undef ENABLE_SSE_IMPLEMENTATION
+#endif
+#ifdef ENABLE_AVX_IMPLEMENTATION
+#  undef ENABLE_AVX_IMPLEMENTATION
+#endif
+
 #ifdef USE_SCALAR_IMPLEMENTATION
 #define ENABLE_SCALAR_IMPLEMENTATION(X) X
 #else

+ 2 - 2
include/igl/active_set.cpp

@@ -67,8 +67,8 @@ IGL_INLINE igl::SolverStatus igl::active_set(
   assert((Aieq.size() == 0 && Bieq.size() == 0) || Aieq.cols() == n);
   assert((Aieq.size() == 0 && Bieq.size() == 0) || Aieq.rows() == Bieq.rows());
   assert((Aieq.size() == 0 && Bieq.size() == 0) || Bieq.cols() == 1);
-  Eigen::PlainObjectBase<Derivedlx> lx;
-  Eigen::PlainObjectBase<Derivedux> ux;
+  Eigen::Matrix<typename Derivedlx::Scalar,Eigen::Dynamic,1> lx;
+  Eigen::Matrix<typename Derivedux::Scalar,Eigen::Dynamic,1> ux;
   if(p_lx.size() == 0)
   {
     lx = Eigen::PlainObjectBase<Derivedlx>::Constant(

+ 6 - 7
include/igl/adjacency_matrix.cpp

@@ -11,13 +11,14 @@
 
 #include <vector>
 
-template <typename T>
+template <typename DerivedF, typename T>
 IGL_INLINE void igl::adjacency_matrix(
-  const Eigen::MatrixXi & F, 
+  const Eigen::PlainObjectBase<DerivedF> & F, 
   Eigen::SparseMatrix<T>& A)
 {
   using namespace std;
   using namespace Eigen;
+  typedef typename DerivedF::Scalar Index;
 
   typedef Triplet<T> IJV;
   vector<IJV > ijv;
@@ -29,14 +30,14 @@ IGL_INLINE void igl::adjacency_matrix(
     for(int j = 0;j<F.cols();j++)
     {
       // Get indices of edge: s --> d
-      int s = F(i,j);
-      int d = F(i,(j+1)%F.cols());
+      Index s = F(i,j);
+      Index d = F(i,(j+1)%F.cols());
       ijv.push_back(IJV(s,d,1));
       ijv.push_back(IJV(d,s,1));
     }
   }
 
-  const int n = F.maxCoeff()+1;
+  const Index n = F.maxCoeff()+1;
   A.resize(n,n);
   switch(F.cols())
   {
@@ -65,6 +66,4 @@ IGL_INLINE void igl::adjacency_matrix(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
-template void igl::adjacency_matrix<int>(Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::SparseMatrix<int, 0, int>&);
-template void igl::adjacency_matrix<double>(Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::SparseMatrix<double, 0, int>&);
 #endif

+ 2 - 2
include/igl/adjacency_matrix.h

@@ -38,9 +38,9 @@ namespace igl
   //   U = A-Adiag;
   //
   // See also: edges, cotmatrix, diag
-  template <typename T>
+  template <typename DerivedF, typename T>
   IGL_INLINE void adjacency_matrix(
-    const Eigen::MatrixXi & F, 
+    const Eigen::PlainObjectBase<DerivedF> & F, 
     Eigen::SparseMatrix<T>& A);
 }
 

+ 134 - 0
include/igl/ambient_occlusion.cpp

@@ -0,0 +1,134 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "ambient_occlusion.h"
+#include "random_dir.h"
+#include "ray_mesh_intersect.h"
+#include "EPS.h"
+#include "Hit.h"
+
+template <
+  typename DerivedP,
+  typename DerivedN,
+  typename DerivedS >
+IGL_INLINE void igl::ambient_occlusion(
+  const std::function<
+    bool(
+      const Eigen::Vector3f&,
+      const Eigen::Vector3f&)
+      > & shoot_ray,
+  const Eigen::PlainObjectBase<DerivedP> & P,
+  const Eigen::PlainObjectBase<DerivedN> & N,
+  const int num_samples,
+  Eigen::PlainObjectBase<DerivedS> & S)
+{
+  using namespace Eigen;
+  const int n = P.rows();
+  // Resize output
+  S.resize(n,1);
+  VectorXi hits = VectorXi::Zero(n,1);
+  const MatrixXf D = random_dir_stratified(num_samples).cast<float>();
+  // Embree seems to be parallel when constructing but not when tracing rays
+#pragma omp parallel for
+  // loop over mesh vertices
+  for(int p = 0;p<n;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++)
+    {
+//      //Vector3d d = random_dir();
+      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;
+  }
+}
+
+template <
+  typename DerivedV,
+  int DIM,
+  typename DerivedF,
+  typename DerivedP,
+  typename DerivedN,
+  typename DerivedS >
+IGL_INLINE void igl::ambient_occlusion(
+  const igl::AABB<DerivedV,DIM> & aabb,
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::PlainObjectBase<DerivedF> & F,
+  const Eigen::PlainObjectBase<DerivedP> & P,
+  const Eigen::PlainObjectBase<DerivedN> & N,
+  const int num_samples,
+  Eigen::PlainObjectBase<DerivedS> & S)
+{
+  const auto & shoot_ray = [&aabb,&V,&F](
+    const Eigen::Vector3f& _s,
+    const Eigen::Vector3f& dir)->bool
+  {
+    Eigen::Vector3f s = _s+1e-4*dir;
+    igl::Hit hit;
+    return aabb.intersect_ray(
+      V,
+      F,
+      s  .cast<typename DerivedV::Scalar>().eval(),
+      dir.cast<typename DerivedV::Scalar>().eval(),
+      hit);
+  };
+  return ambient_occlusion(shoot_ray,P,N,num_samples,S);
+
+}
+
+template <
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedP,
+  typename DerivedN,
+  typename DerivedS >
+IGL_INLINE void igl::ambient_occlusion(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::PlainObjectBase<DerivedF> & F,
+  const Eigen::PlainObjectBase<DerivedP> & P,
+  const Eigen::PlainObjectBase<DerivedN> & N,
+  const int num_samples,
+  Eigen::PlainObjectBase<DerivedS> & S)
+{
+  if(F.rows() < 100)
+  {
+    // Super naive
+    const auto & shoot_ray = [&V,&F](
+      const Eigen::Vector3f& _s,
+      const Eigen::Vector3f& dir)->bool
+    {
+      Eigen::Vector3f s = _s+1e-4*dir;
+      igl::Hit hit;
+      return ray_mesh_intersect(s,dir,V,F,hit);
+    };
+    return ambient_occlusion(shoot_ray,P,N,num_samples,S);
+  }
+  AABB<DerivedV,3> aabb;
+  aabb.init(V,F);
+  return ambient_occlusion(aabb,V,F,P,N,num_samples,S);
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template specialization
+// generated by autoexplicit.sh
+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> >&);
+// generated by autoexplicit.sh
+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
+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> >&);
+#endif

+ 80 - 0
include/igl/ambient_occlusion.h

@@ -0,0 +1,80 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_AMBIENT_OCCLUSION_H
+#define IGL_AMBIENT_OCCLUSION_H
+#include "igl_inline.h"
+#include "AABB.h"
+#include <Eigen/Core>
+#include <functional>
+namespace igl
+{
+  // Compute ambient occlusion per given point
+  //
+  // Inputs:
+  //    shoot_ray  function handle that outputs hits of a given ray against a
+  //      mesh (embedded in function handles as captured variable/data)
+  //    P  #P by 3 list of origin points
+  //    N  #P by 3 list of origin normals
+  // Outputs:
+  //    S  #P list of ambient occlusion values between 1 (fully occluded) and
+  //      0 (not occluded)
+  //
+  template <
+    typename DerivedP,
+    typename DerivedN,
+    typename DerivedS >
+  IGL_INLINE void ambient_occlusion(
+    const std::function<
+      bool(
+        const Eigen::Vector3f&,
+        const Eigen::Vector3f&)
+        > & shoot_ray,
+    const Eigen::PlainObjectBase<DerivedP> & P,
+    const Eigen::PlainObjectBase<DerivedN> & N,
+    const int num_samples,
+    Eigen::PlainObjectBase<DerivedS> & S);
+  // Inputs:
+  //   AABB  axis-aligned bounding box hierarchy around (V,F)
+  template <
+    typename DerivedV,
+    int DIM,
+    typename DerivedF,
+    typename DerivedP,
+    typename DerivedN,
+    typename DerivedS >
+  IGL_INLINE void ambient_occlusion(
+    const igl::AABB<DerivedV,DIM> & aabb,
+    const Eigen::PlainObjectBase<DerivedV> & V,
+    const Eigen::PlainObjectBase<DerivedF> & F,
+    const Eigen::PlainObjectBase<DerivedP> & P,
+    const Eigen::PlainObjectBase<DerivedN> & N,
+    const int num_samples,
+    Eigen::PlainObjectBase<DerivedS> & S);
+  // Inputs:
+  //    V  #V by 3 list of mesh vertex positions
+  //    F  #F by 3 list of mesh face indices into V
+  template <
+    typename DerivedV,
+    typename DerivedF,
+    typename DerivedP,
+    typename DerivedN,
+    typename DerivedS >
+  IGL_INLINE void ambient_occlusion(
+    const Eigen::PlainObjectBase<DerivedV> & V,
+    const Eigen::PlainObjectBase<DerivedF> & F,
+    const Eigen::PlainObjectBase<DerivedP> & P,
+    const Eigen::PlainObjectBase<DerivedN> & N,
+    const int num_samples,
+    Eigen::PlainObjectBase<DerivedS> & S);
+
+};
+#ifndef IGL_STATIC_LIBRARY
+#  include "ambient_occlusion.cpp"
+#endif
+
+#endif

+ 1 - 0
include/igl/angle_bound_frame_fields.cpp

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

+ 0 - 1
include/igl/arap.cpp

@@ -173,7 +173,6 @@ IGL_INLINE bool igl::arap_solve(
   ARAPData & data,
   Eigen::PlainObjectBase<DerivedU> & U)
 {
-  using namespace igl;
   using namespace Eigen;
   using namespace std;
   assert(data.b.size() == bc.rows());

+ 3 - 5
include/igl/arap_dof.cpp

@@ -14,7 +14,6 @@
 #include "repmat.h"
 #include "slice.h"
 #include "colon.h"
-#include "full.h"
 #include "is_sparse.h"
 #include "mode.h"
 #include "is_symmetric.h"
@@ -203,9 +202,8 @@ IGL_INLINE bool igl::arap_dof_precomputation(
       if(is_sparse(CSMjM_i))
       {
         // Convert to full
-        MatrixXd CSMjM_ifull;
         //printf("CSM_M(): full\n");
-        full(CSMjM_i,CSMjM_ifull);
+        MatrixXd CSMjM_ifull(CSMjM_i);
 //        printf("CSM_M[%d]: %d %d\n",i,data.CSM_M[i].rows(),data.CSM_M[i].cols());
 //        printf("CSM_M[%d].block(%d*%d=%d,0,%d,%d): %d %d\n",i,j,k,CSMjM_i.rows(),CSMjM_i.cols(),
 //            data.CSM_M[i].block(j*k,0,CSMjM_i.rows(),CSMjM_i.cols()).rows(),
@@ -546,8 +544,8 @@ IGL_INLINE bool igl::arap_dof_recomputation(
 
   // Compute dense solve matrix (alternative of matrix factorization)
   //printf("min_quad_dense_precompute()\n");
-  MatrixXd Qfull; full(*Q, Qfull);  
-  MatrixXd A_eqfull; full(A_eq, A_eqfull);
+  MatrixXd Qfull(*Q);
+  MatrixXd A_eqfull(A_eq);
   MatrixXd M_Solve;
 
   double timer0_start = get_seconds_hires();

+ 8 - 10
include/igl/average_onto_vertices.cpp

@@ -7,15 +7,15 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "average_onto_vertices.h"
 
-template <typename T, typename I>
-IGL_INLINE void igl::average_onto_vertices(const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &V,
-            const Eigen::Matrix<I, Eigen::Dynamic, Eigen::Dynamic> &F,
-            const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &S,
-            Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &SV)
+template<typename DerivedV,typename DerivedF,typename DerivedS>
+IGL_INLINE void igl::average_onto_vertices(const Eigen::MatrixBase<DerivedV> &V,
+  const Eigen::MatrixBase<DerivedF> &F,
+  const Eigen::MatrixBase<DerivedS> &S,
+  Eigen::MatrixBase<DerivedS> &SV)
 {
-
-  SV = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>::Zero(V.rows(),S.cols());
-  Eigen::Matrix<T, Eigen::Dynamic, 1> COUNT = Eigen::Matrix<T, Eigen::Dynamic, 1>::Zero(V.rows());
+  SV = DerivedS::Zero(V.rows(),S.cols());
+  Eigen::Matrix<typename DerivedF::Scalar,Eigen::Dynamic,1> COUNT(V.rows());
+  COUNT.setZero();
   for (int i = 0; i <F.rows(); ++i)
   {
     for (int j = 0; j<F.cols(); ++j)
@@ -26,10 +26,8 @@ IGL_INLINE void igl::average_onto_vertices(const Eigen::Matrix<T, Eigen::Dynamic
   }
   for (int i = 0; i <V.rows(); ++i)
     SV.row(i) /= COUNT[i];
-
 };
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
-template void igl::average_onto_vertices<double, int>(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> const&, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
 #endif

+ 5 - 6
include/igl/average_onto_vertices.h

@@ -21,12 +21,11 @@ namespace igl
   // 
   // Output:
   // SV: scalar field defined on vertices
-  template <typename T, typename I>
-  IGL_INLINE void average_onto_vertices(
-    const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &V,
-    const Eigen::Matrix<I, Eigen::Dynamic, Eigen::Dynamic> &F,
-    const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &S,
-    Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &SV);
+  template<typename DerivedV,typename DerivedF,typename DerivedS>
+  IGL_INLINE void average_onto_vertices(const Eigen::MatrixBase<DerivedV> &V,
+    const Eigen::MatrixBase<DerivedF> &F,
+    const Eigen::MatrixBase<DerivedS> &S,
+    Eigen::MatrixBase<DerivedS> &SV);
 }
 
 #ifndef IGL_STATIC_LIBRARY

+ 5 - 8
include/igl/barycenter.h

@@ -11,17 +11,14 @@
 #include <Eigen/Dense>
 namespace igl
 {
-  // BARYCENTER
-  //
-  // B = barycenter(V,F)
-  //
-  // Compute the barycenter of every simplex
+  // Computes the barycenter of every simplex
   //
   // Inputs:
-  //   V #V x dim matrix of vertex coordinates
-  //   F #F x simplex_size  matrix of indices of simplex corners
+  //   V  #V x dim matrix of vertex coordinates
+  //   F  #F x simplex_size  matrix of indices of simplex corners into V
   // Output:
-  //   BC a #F x dim matrix of 3d vertices
+  //   BC  #F x dim matrix of 3d vertices
+  //
   template <
     typename DerivedV,
     typename DerivedF,

+ 0 - 1
include/igl/bbw/bbw.cpp

@@ -59,7 +59,6 @@ IGL_INLINE bool igl::bbw::bbw(
   Eigen::PlainObjectBase<DerivedW> & W
   )
 {
-  using namespace igl;
   using namespace std;
   using namespace Eigen;
 

+ 0 - 1
include/igl/bfs_orient.cpp

@@ -17,7 +17,6 @@ IGL_INLINE void igl::bfs_orient(
   Eigen::PlainObjectBase<DerivedC> & C)
 {
   using namespace Eigen;
-  using namespace igl;
   using namespace std;
   SparseMatrix<int> A;
   orientable_patches(F,C,A);

+ 0 - 185
include/igl/boolean/CSGTree.h

@@ -1,185 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_BOOLEAN_CSG_TREE_H
-#define IGL_BOOLEAN_CSG_TREE_H
-
-#include <igl/boolean/string_to_mesh_boolean_type.h>
-#include <igl/boolean/MeshBooleanType.h>
-#include <igl/boolean/mesh_boolean.h>
-#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
-#include <CGAL/number_utils.h>
-
-namespace igl
-{
-  namespace boolean
-  {
-    // Class for defining and computing a constructive solid geometry result
-    // out of a tree of boolean operations on "solid" triangle meshes.
-    //
-    //template <typename DerivedF>
-    class CSGTree
-    {
-      private:
-        typedef CGAL::Epeck::FT ExactScalar;
-        typedef Eigen::Matrix<ExactScalar,Eigen::Dynamic,3> MatrixX3E;
-        //typedef Eigen::PlainObjectBase<DerivedF> POBF;
-        typedef Eigen::MatrixXi POBF;
-        typedef POBF::Index FIndex;
-        typedef Eigen::Matrix<FIndex,Eigen::Dynamic,1> VectorJ;
-        // Resulting mesh
-        MatrixX3E m_V;
-        POBF m_F;
-        VectorJ m_J;
-        // Number of birth faces in A + those in B. I.e. sum of original "leaf"
-        // faces involved in result.
-        size_t m_number_of_birth_faces;
-      public:
-        CSGTree()
-        {
-        }
-        //typedef Eigen::MatrixXd MatrixX3E;
-        //typedef Eigen::MatrixXi POBF;
-        // http://stackoverflow.com/a/3279550/148668
-        CSGTree(const CSGTree & other)
-          :
-          // copy things
-          m_V(other.m_V),
-          // This is an issue if m_F is templated
-          // https://forum.kde.org/viewtopic.php?f=74&t=128414
-          m_F(other.m_F),
-          m_J(other.m_J),
-          m_number_of_birth_faces(other.m_number_of_birth_faces)
-        {
-        }
-        // copy-swap idiom
-        friend void swap(CSGTree& first, CSGTree& second)
-        {
-          using std::swap;
-          // swap things
-          swap(first.m_V,second.m_V);
-          // This is an issue if m_F is templated, similar to
-          // https://forum.kde.org/viewtopic.php?f=74&t=128414
-          swap(first.m_F,second.m_F);
-          swap(first.m_J,second.m_J);
-          swap(first.m_number_of_birth_faces,second.m_number_of_birth_faces);
-        }
-        // Pass-by-value (aka copy)
-        CSGTree& operator=(CSGTree other)
-        {
-          swap(*this,other);
-          return *this;
-        }
-        CSGTree(CSGTree&& other):
-          // initialize via default constructor
-          CSGTree() 
-        {
-          swap(*this,other);
-        }
-        // Construct and compute a boolean operation on existing CSGTree nodes.
-        //
-        // Inputs:
-        //   A  Solid result of previous CSG operation (or identity, see below)
-        //   B  Solid result of previous CSG operation (or identity, see below)
-        //   type  type of mesh boolean to compute 
-        CSGTree(
-          const CSGTree & A,
-          const CSGTree & B,
-          const MeshBooleanType & type)
-        {
-          // conduct boolean operation
-          {
-            Eigen::VectorXi I;
-            mesh_boolean(A.V(),A.F(),B.V(),B.F(),type,m_V,m_F,m_J,I);
-          }
-          // reindex m_J
-          std::for_each(m_J.data(),m_J.data()+m_J.size(),
-            [&](typename VectorJ::Scalar & j)
-            {
-              if(j < A.F().rows())
-              {
-                j = A.J()(j);
-              }else
-              {
-                assert(j<(A.F().rows()+B.F().rows()));
-                j = A.number_of_birth_faces()+(B.J()(j-A.F().rows()));
-              }
-            });
-          m_number_of_birth_faces = 
-            A.number_of_birth_faces() + B.number_of_birth_faces();
-        }
-        // Overload using string for type
-        CSGTree(
-          const CSGTree & A,
-          const CSGTree & B,
-          const std::string & s):
-          CSGTree(A,B,string_to_mesh_boolean_type(s))
-        {
-          // do nothing (all done in constructor).
-        }
-        // "Leaf" node with identity operation on assumed "solid" mesh (V,F)
-        //
-        // Inputs:
-        //   V  #V by 3 list of mesh vertices (in any precision, will be
-        //     converted to exact)
-        //   F  #F by 3 list of mesh face indices into V
-        template <typename DerivedV>
-        CSGTree(const Eigen::PlainObjectBase<DerivedV> & V, const POBF & F)//:
-        // Possible Eigen bug:
-        // https://forum.kde.org/viewtopic.php?f=74&t=128414
-          //m_V(V.template cast<ExactScalar>()),m_F(F)
-        {
-          m_V = V.template cast<ExactScalar>();
-          m_F = F;
-          // number of faces
-          m_number_of_birth_faces = m_F.rows();
-          // identity birth index
-          m_J = VectorJ::LinSpaced(
-            m_number_of_birth_faces,0,m_number_of_birth_faces-1);
-        }
-        // Returns reference to resulting mesh vertices m_V in exact scalar
-        // representation
-        const MatrixX3E & V() const
-        {
-          return m_V;
-        }
-        // Returns mesh vertices in the desired output type, casting when
-        // appropriate to floating precision.
-        template <typename DerivedV>
-        Eigen::PlainObjectBase<DerivedV> cast_V() const
-        {
-          Eigen::PlainObjectBase<DerivedV> dV;
-          dV.resize(m_V.rows(),m_V.cols());
-          for(int i = 0;i<m_V.size();i++)
-          {
-            *(dV.data()+i) = CGAL::to_double((*(m_V.data()+i)));
-          }
-          return dV;
-        }
-        // Returns reference to resulting mesh faces m_F
-        const POBF & F() const
-        {
-          return m_F;
-        }
-        // Returns reference to "birth parents" indices into [F1;F2;...;Fn]
-        // where F1, ... , Fn are the face lists of the leaf ("original") input
-        // meshes.
-        const VectorJ & J() const
-        {
-          return m_J;
-        }
-        // The number of leaf faces = #F1 + #F2 + ... + #Fn
-        const size_t & number_of_birth_faces() const
-        {
-          return m_number_of_birth_faces;
-        }
-    };
-  }
-}
-
-
-#endif

+ 0 - 26
include/igl/boolean/MeshBooleanType.h

@@ -1,26 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_BOOLEAN_MESH_BOOLEAN_TYPE_H
-#define IGL_BOOLEAN_MESH_BOOLEAN_TYPE_H
-namespace igl
-{
-  namespace boolean
-  {
-    enum MeshBooleanType
-    {
-      MESH_BOOLEAN_TYPE_UNION = 0,
-      MESH_BOOLEAN_TYPE_INTERSECT = 1,
-      MESH_BOOLEAN_TYPE_MINUS = 2,
-      MESH_BOOLEAN_TYPE_XOR = 3,
-      MESH_BOOLEAN_TYPE_RESOLVE = 4,
-      NUM_MESH_BOOLEAN_TYPES = 5
-    };
-  }
-};
-
-#endif

+ 0 - 38
include/igl/boolean/from_cork_mesh.h

@@ -1,38 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_BOOLEAN_FROM_CORK_MESH_H
-#define IGL_BOOLEAN_FROM_CORK_MESH_H
-#ifndef IGL_NO_CORK
-#include <igl/igl_inline.h>
-#include <cork.h>
-#include <Eigen/Core>
-namespace igl
-{
-  namespace boolean
-  {
-    // Convert cork's triangle mesh representation to a (V,F) mesh.
-    //
-    // Inputs:
-    //   mesh  cork representation of mesh
-    // Outputs:
-    //   V  #V by 3 list of vertex positions
-    //   F  #F by 3 list of triangle indices into V
-    template <
-      typename DerivedV,
-      typename DerivedF>
-    IGL_INLINE void from_cork_mesh(
-      const CorkTriMesh & mesh,
-      Eigen::PlainObjectBase<DerivedV > & V,
-      Eigen::PlainObjectBase<DerivedF > & F);
-  }
-}
-#ifndef IGL_STATIC_LIBRARY
-#  include "from_cork_mesh.cpp"
-#endif
-#endif
-#endif

+ 0 - 404
include/igl/boolean/mesh_boolean.cpp

@@ -1,404 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#include "mesh_boolean.h"
-#include <igl/cgal/assign_scalar.h>
-#include <igl/per_face_normals.h>
-#include <igl/boundary_facets.h>
-#include <igl/exterior_edges.h>
-#include <igl/cgal/peel_outer_hull_layers.h>
-#include <igl/cgal/remesh_self_intersections.h>
-#include <igl/remove_unreferenced.h>
-#include <igl/mod.h>
-#include <igl/unique_simplices.h>
-#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
-#include <iostream>
-
-//#define IGL_MESH_BOOLEAN_DEBUG
-template <
-  typename DerivedVA,
-  typename DerivedFA,
-  typename DerivedVB,
-  typename DerivedFB,
-  typename DerivedVC,
-  typename DerivedFC,
-  typename DerivedJ,
-  typename DerivedI>
-IGL_INLINE void igl::boolean::mesh_boolean(
-  const Eigen::PlainObjectBase<DerivedVA > & VA,
-  const Eigen::PlainObjectBase<DerivedFA > & FA,
-  const Eigen::PlainObjectBase<DerivedVB > & VB,
-  const Eigen::PlainObjectBase<DerivedFB > & FB,
-  const MeshBooleanType & type,
-  const std::function<void(
-    const Eigen::Matrix<typename DerivedVC::Scalar,Eigen::Dynamic,3>&,
-    const Eigen::Matrix<typename DerivedFC::Scalar, Eigen::Dynamic,3>&,
-    Eigen::Matrix<typename DerivedVC::Scalar,Eigen::Dynamic,3>&,
-    Eigen::Matrix<typename DerivedFC::Scalar, Eigen::Dynamic,3>&,
-    Eigen::Matrix<typename DerivedJ::Scalar, Eigen::Dynamic,1>&,
-    Eigen::Matrix<typename DerivedI::Scalar, Eigen::Dynamic,1>&)> &
-    resolve_fun,
-  Eigen::PlainObjectBase<DerivedVC > & VC,
-  Eigen::PlainObjectBase<DerivedFC > & FC,
-  Eigen::PlainObjectBase<DerivedJ > & J,
-  Eigen::PlainObjectBase<DerivedI > & I)
-{
-  using namespace Eigen;
-  using namespace std;
-  using namespace igl;
-  using namespace igl::cgal;
-  MeshBooleanType eff_type = type;
-  // Concatenate A and B into a single mesh
-  typedef CGAL::Epeck Kernel;
-  typedef Kernel::FT ExactScalar;
-  typedef typename DerivedVC::Scalar Scalar;
-  typedef typename DerivedFC::Scalar Index;
-  typedef Matrix<Scalar,Dynamic,3> MatrixX3S;
-  typedef Matrix<ExactScalar,Dynamic,3> MatrixX3ES;
-  typedef Matrix<Index,Dynamic,3> MatrixX3I;
-  typedef Matrix<Index,Dynamic,2> MatrixX2I;
-  typedef Matrix<typename DerivedI::Scalar,Dynamic,1> VectorXI;
-  typedef Matrix<typename DerivedJ::Scalar,Dynamic,1> VectorXJ;
-#ifdef IGL_MESH_BOOLEAN_DEBUG
-  cout<<"mesh boolean..."<<endl;
-#endif
-  MatrixX3S V(VA.rows()+VB.rows(),3);
-  MatrixX3I F(FA.rows()+FB.rows(),3);
-  V.block(0,0,VA.rows(),VA.cols()) = VA;
-  V.block(VA.rows(),0,VB.rows(),VB.cols()) = VB;
-#ifdef IGL_MESH_BOOLEAN_DEBUG
-  cout<<"prepare selfintersect input..."<<endl;
-#endif
-  switch(type)
-  {
-    // Minus is implemented by flipping B and computing union
-    case MESH_BOOLEAN_TYPE_MINUS:
-      F.block(0,0,FA.rows(),FA.cols()) = FA.rowwise().reverse();
-      F.block(FA.rows(),0,FB.rows(),FB.cols()) = FB.array()+VA.rows();
-      //F.block(0,0,FA.rows(),3) = FA;
-      //F.block(FA.rows(),0,FB.rows(),3) =
-      //  FB.rowwise().reverse().array()+VA.rows();
-      eff_type = MESH_BOOLEAN_TYPE_INTERSECT;
-      break;
-    default:
-      F.block(0,0,FA.rows(),FA.cols()) = FA;
-      F.block(FA.rows(),0,FB.rows(),FB.cols()) = FB.array()+VA.rows();
-      break;
-  }
-
-  // Resolve intersections (assumes A and B are solid)
-  const auto & libigl_resolve = [](
-    const MatrixX3S & V,
-    const MatrixX3I & F,
-    MatrixX3ES & CV,
-    MatrixX3I & CF,
-    VectorXJ & J,
-    VectorXI & I)
-  {
-    MatrixX3ES SV;
-    MatrixX3I SF;
-    MatrixX2I SIF;
-    igl::cgal::RemeshSelfIntersectionsParam params;
-    remesh_self_intersections(V,F,params,SV,SF,SIF,J,I);
-    for_each(SF.data(),SF.data()+SF.size(),
-      [&I](typename MatrixX3I::Scalar & a){a=I(a);});
-    {
-      Eigen::Matrix<typename MatrixX3S::Index,Dynamic,1> UIM;
-      remove_unreferenced(SV,SF,CV,CF,UIM);
-      for_each(I.data(),I.data()+I.size(),
-        [&UIM](typename VectorXI::Scalar & a){a=UIM(a);});
-    }
-#ifdef IGL_MESH_BOOLEAN_DEBUG
-    cout<<"#F:  "<<F.rows()<<endl;
-    cout<<"#CF: "<<CF.rows()<<endl;
-#endif
-  };
-
-#ifdef IGL_MESH_BOOLEAN_DEBUG
-  cout<<"resolve..."<<endl;
-#endif
-  MatrixX3S CV;
-  MatrixX3ES EV;
-  MatrixX3I CF;
-  VectorXJ CJ;
-  Eigen::Matrix<typename DerivedI::Scalar,Dynamic, 1> CI;
-  if(resolve_fun)
-  {
-    resolve_fun(V,F,CV,CF,CJ,CI);
-  }else
-  {
-    libigl_resolve(V,F,EV,CF,CJ,CI);
-    CV.resize(EV.rows(), EV.cols());
-    // Just use f'ing for loops. What if EV and CV don't use the same ordering?
-    for(int i=0;i<EV.rows();i++)
-    {
-      for(int j=0;j<EV.cols();j++)
-      {
-        assign_scalar(EV(i,j),CV(i,j));
-      }
-    }
-  }
-
-  if(type == MESH_BOOLEAN_TYPE_RESOLVE)
-  {
-    FC = CF;
-    VC = CV;
-    J = CJ;
-    I = CI;
-    return;
-  }
-
-#ifdef IGL_MESH_BOOLEAN_DEBUG
-  cout<<"peel..."<<endl;
-#endif
-  Matrix<bool,Dynamic,1> from_A(CF.rows());
-  // peel layers keeping track of odd and even flips
-  VectorXi iter;
-  Matrix<bool,Dynamic,1> flip;
-  peel_outer_hull_layers(EV,CF,iter,flip);
-  //Array<bool,Dynamic,1> even = igl::mod(I,2).array()==0;
-  const auto even = [&](const Index & f)->bool
-  {
-    return (iter(f)%2)==0;
-  };
-
-#ifdef IGL_MESH_BOOLEAN_DEBUG
-  cout<<"categorize..."<<endl;
-#endif
-  const Index m = CF.rows();
-  // Faces of output vG[i] = j means ith face of output should be jth face in F
-  std::vector<Index> vG;
-  // Whether faces of output should be flipped, Gflip[i] = true means ith face
-  // of output should be F.row(vG[i]).reverse() rather than F.row(vG[i])
-  std::vector<bool> Gflip;
-  for(Index f = 0;f<m;f++)
-  {
-    switch(eff_type)
-    {
-      case MESH_BOOLEAN_TYPE_XOR:
-      case MESH_BOOLEAN_TYPE_UNION:
-        if((even(f)&&!flip(f))||(!even(f)&&flip(f)))
-        {
-          vG.push_back(f);
-          Gflip.push_back(false);
-        }else if(eff_type == MESH_BOOLEAN_TYPE_XOR)
-        {
-          vG.push_back(f);
-          Gflip.push_back(true);
-        }
-        break;
-      case MESH_BOOLEAN_TYPE_INTERSECT:
-        if((!even(f) && !flip(f)) || (even(f) && flip(f)))
-        {
-          vG.push_back(f);
-          Gflip.push_back(type == MESH_BOOLEAN_TYPE_MINUS);
-        }
-        break;
-      default:
-        assert(false && "Unknown type");
-        return;
-    }
-  }
-  const Index gm = vG.size();
-  MatrixX3I G(gm,3);
-  VectorXi GJ(gm,1);
-  for(Index g = 0;g<gm;g++)
-  {
-    G.row(g) = Gflip[g] ? CF.row(vG[g]).reverse().eval() : CF.row(vG[g]);
-    GJ(g) = CJ(vG[g]);
-  }
-#ifdef IGL_MESH_BOOLEAN_DEBUG
-  {
-    MatrixXi O;
-    boundary_facets(FC,O);
-    cout<<"# boundary: "<<O.rows()<<endl;
-  }
-  cout<<"# exterior: "<<exterior_edges(FC).rows()<<endl;
-#endif
-#ifdef IGL_MESH_BOOLEAN_DEBUG
-  cout<<"clean..."<<endl;
-#endif
-  // Deal with duplicate faces
-  {
-    VectorXi IA,IC;
-    MatrixX3I uG;
-    unique_simplices(G,uG,IA,IC);
-    assert(IA.rows() == uG.rows());
-    // faces ontop of each unique face
-    vector<vector<Index> > uG2G(uG.rows());
-    // signed counts
-    VectorXi counts = VectorXi::Zero(uG.rows());
-    VectorXi ucounts = VectorXi::Zero(uG.rows());
-    // loop over all faces
-    for(Index g = 0;g<gm;g++)
-    {
-      const int ug = IC(g);
-      assert((size_t) ug < uG2G.size());
-      uG2G[ug].push_back(g);
-      // is uG(g,:) just a rotated version of G(g,:) ?
-      const bool consistent =
-        (G(g,0) == uG(ug,0) && G(g,1) == uG(ug,1) && G(g,2) == uG(ug,2)) ||
-        (G(g,0) == uG(ug,1) && G(g,1) == uG(ug,2) && G(g,2) == uG(ug,0)) ||
-        (G(g,0) == uG(ug,2) && G(g,1) == uG(ug,0) && G(g,2) == uG(ug,1));
-      counts(ug) += consistent ? 1 : -1;
-      ucounts(ug)++;
-    }
-    MatrixX3I oldG = G;
-    // Faces of output vG[i] = j means ith face of output should be jth face in
-    // oldG
-    vG.clear();
-    for(size_t ug = 0;ug < uG2G.size();ug++)
-    {
-      // if signed occurrences is zero or ±two then keep none
-      // else if signed occurrences is ±one then keep just one facet
-      switch(abs(counts(ug)))
-      {
-        case 1:
-          assert(uG2G[ug].size() > 0);
-          vG.push_back(uG2G[ug][0]);
-#ifdef IGL_MESH_BOOLEAN_DEBUG
-          if(abs(ucounts(ug)) != 1)
-          {
-            cout<<"count,ucount of "<<counts(ug)<<","<<ucounts(ug)<<endl;
-          }
-#endif
-          break;
-        case 0:
-#ifdef IGL_MESH_BOOLEAN_DEBUG
-          cout<<"Skipping "<<uG2G[ug].size()<<" facets..."<<endl;
-          if(abs(ucounts(ug)) != 0)
-          {
-            cout<<"count,ucount of "<<counts(ug)<<","<<ucounts(ug)<<endl;
-          }
-#endif
-          break;
-        default:
-#ifdef IGL_MESH_BOOLEAN_DEBUG
-          cout<<"Didn't expect to be here."<<endl;
-#endif
-          assert(false && "Shouldn't count be -1/0/1 ?");
-      }
-    }
-    G.resize(vG.size(),3);
-    J.resize(vG.size());
-    for(size_t g = 0;g<vG.size();g++)
-    {
-      G.row(g) = oldG.row(vG[g]);
-      J(g) = GJ(vG[g]);
-    }
-  }
-  // remove unreferenced vertices
-  {
-    VectorXi newIM;
-    remove_unreferenced(CV,G,VC,FC,newIM);
-    I.resize(CI.rows(),CI.cols());
-    for(int i = 0;i<CI.rows();i++)
-    {
-      I(i) = newIM(CI(i));
-    }
-  }
-  //cerr<<"warning not removing unref"<<endl;
-  //VC = CV;
-  //FC = G;
-#ifdef IGL_MESH_BOOLEAN_DEBUG
-  {
-    MatrixXi O;
-    boundary_facets(FC,O);
-    cout<<"# boundary: "<<O.rows()<<endl;
-  }
-  cout<<"# exterior: "<<exterior_edges(FC).rows()<<endl;
-#endif
-}
-
-
-template <
-  typename DerivedVA,
-  typename DerivedFA,
-  typename DerivedVB,
-  typename DerivedFB,
-  typename DerivedVC,
-  typename DerivedFC,
-  typename DerivedJ,
-  typename DerivedI>
-IGL_INLINE void igl::boolean::mesh_boolean(
-  const Eigen::PlainObjectBase<DerivedVA > & VA,
-  const Eigen::PlainObjectBase<DerivedFA > & FA,
-  const Eigen::PlainObjectBase<DerivedVB > & VB,
-  const Eigen::PlainObjectBase<DerivedFB > & FB,
-  const MeshBooleanType & type,
-  Eigen::PlainObjectBase<DerivedVC > & VC,
-  Eigen::PlainObjectBase<DerivedFC > & FC,
-  Eigen::PlainObjectBase<DerivedJ > & J,
-  Eigen::PlainObjectBase<DerivedI > & I)
-{
-  const std::function<void(
-    const Eigen::Matrix<typename DerivedVC::Scalar,Eigen::Dynamic,3> &,
-    const Eigen::Matrix<typename DerivedFC::Scalar, Eigen::Dynamic,3>&,
-          Eigen::Matrix<typename DerivedVC::Scalar,Eigen::Dynamic,3> &,
-          Eigen::Matrix<typename DerivedFC::Scalar, Eigen::Dynamic,3>&,
-          Eigen::Matrix<typename DerivedJ::Scalar, Eigen::Dynamic,1>&,
-          Eigen::Matrix<typename DerivedI::Scalar, Eigen::Dynamic,1>&) >
-    empty_fun;
-  return mesh_boolean(VA,FA,VB,FB,type,empty_fun,VC,FC,J,I);
-}
-
-template <
-  typename DerivedVA,
-  typename DerivedFA,
-  typename DerivedVB,
-  typename DerivedFB,
-  typename DerivedVC,
-  typename DerivedFC>
-IGL_INLINE void igl::boolean::mesh_boolean(
-  const Eigen::PlainObjectBase<DerivedVA > & VA,
-  const Eigen::PlainObjectBase<DerivedFA > & FA,
-  const Eigen::PlainObjectBase<DerivedVB > & VB,
-  const Eigen::PlainObjectBase<DerivedFB > & FB,
-  const MeshBooleanType & type,
-  Eigen::PlainObjectBase<DerivedVC > & VC,
-  Eigen::PlainObjectBase<DerivedFC > & FC)
-{
-  Eigen::Matrix<typename DerivedFC::Index, Eigen::Dynamic,1> J;
-  typedef Eigen::Matrix<typename DerivedVC::Index, Eigen::Dynamic,1> VectorXI;
-  VectorXI I;
-  const std::function<void(
-    const Eigen::Matrix<typename DerivedVC::Scalar,Eigen::Dynamic,3> &,
-    const Eigen::Matrix<typename DerivedFC::Scalar, Eigen::Dynamic,3>&,
-          Eigen::Matrix<typename DerivedVC::Scalar,Eigen::Dynamic,3> &,
-          Eigen::Matrix<typename DerivedFC::Scalar, Eigen::Dynamic,3>&,
-          Eigen::Matrix<typename DerivedFC::Index, Eigen::Dynamic,1>&,
-          Eigen::Matrix<typename VectorXI::Scalar, Eigen::Dynamic,1>&)>
-    empty_fun;
-  return mesh_boolean(VA,FA,VB,FB,type,empty_fun,VC,FC,J,I);
-}
-
-#ifdef IGL_STATIC_LIBRARY
-// Explicit template specialization
-template void igl::boolean::mesh_boolean<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, igl::boolean::MeshBooleanType const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
-template void igl::boolean::mesh_boolean<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, igl::boolean::MeshBooleanType const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template void igl::boolean::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<long, -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&, igl::boolean::MeshBooleanType 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<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-// This is a hack to discuss. I'm not sure why this _doesn't_ create
-// duplicate symbols.
-#include <igl/remove_unreferenced.cpp>
-template void igl::remove_unreferenced<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-#include <igl/cgal/peel_outer_hull_layers.cpp>
-template unsigned long
-igl::cgal::peel_outer_hull_layers<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&);
-#include <igl/cgal/outer_hull.cpp>
-template void igl::cgal::outer_hull<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&);
-#include <igl/slice.cpp>
-#include <igl/barycenter.cpp>
-template void igl::barycenter<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&);
-#include <igl/mod.cpp>
-template Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > igl::mod<Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int);
-#include <igl/outer_element.cpp>
-template void igl::outer_edge<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, long, Eigen::Matrix<long, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> > const&, long&, long&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&);
-#include <igl/colon.cpp>
-template void igl::colon<int, long, long>(int, long, Eigen::Matrix<long, -1, 1, 0, -1, 1>&);
-
-
-#endif

+ 0 - 110
include/igl/boolean/mesh_boolean.h

@@ -1,110 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_BOOLEAN_MESH_BOOLEAN_H
-#define IGL_BOOLEAN_MESH_BOOLEAN_H
-
-#include <igl/igl_inline.h>
-#include "MeshBooleanType.h"
-#include <Eigen/Core>
-#include <functional>
-
-namespace igl
-{
-  namespace boolean
-  {
-    //  MESH_BOOLEAN Compute boolean csg operations on "solid", consistently
-    //  oriented meshes.
-    // 
-    //  Inputs:
-    //    VA  #VA by 3 list of vertex positions of first mesh
-    //    FA  #FA by 3 list of triangle indices into VA
-    //    VB  #VB by 3 list of vertex positions of second mesh
-    //    FB  #FB by 3 list of triangle indices into VB
-    //    type  type of boolean operation
-    //    resolve_fun  function handle for computing resolve of a
-    //      self-intersections of a mesh and outputting the new mesh.
-    //  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 [FA;FB] revealing "birth" facet
-    //    I  #VA+#VB list of indices into SV (SV=[VA;VB;SVA;SVB], where SVA and
-    //      SVB are the new vertices from resolving intersections) revealing
-    //      "birth" vertices.
-    //
-    //  See also: mesh_boolean_cork, intersect_other, remesh_self_intersections
-    //     
-    template <
-      typename DerivedVA,
-      typename DerivedFA,
-      typename DerivedVB,
-      typename DerivedFB,
-      typename DerivedVC,
-      typename DerivedFC,
-      typename DerivedJ,
-      typename DerivedI>
-    IGL_INLINE void mesh_boolean(
-      const Eigen::PlainObjectBase<DerivedVA > & VA,
-      const Eigen::PlainObjectBase<DerivedFA > & FA,
-      const Eigen::PlainObjectBase<DerivedVB > & VB,
-      const Eigen::PlainObjectBase<DerivedFB > & FB,
-      const MeshBooleanType & type,
-      const std::function<void(
-        const Eigen::Matrix<typename DerivedVC::Scalar,Eigen::Dynamic,3> &,
-        const Eigen::Matrix<typename DerivedFC::Scalar,Eigen::Dynamic,3> &,
-        Eigen::Matrix<typename DerivedVC::Scalar,Eigen::Dynamic,3> &,
-        Eigen::Matrix<typename DerivedFC::Scalar,Eigen::Dynamic,3> &,
-        Eigen::Matrix<typename DerivedJ::Scalar,Eigen::Dynamic,1>&,
-        Eigen::Matrix<typename DerivedI::Scalar,Eigen::Dynamic,1>&)> &
-        resolve_fun,
-      Eigen::PlainObjectBase<DerivedVC > & VC,
-      Eigen::PlainObjectBase<DerivedFC > & FC,
-      Eigen::PlainObjectBase<DerivedJ > & J,
-      Eigen::PlainObjectBase<DerivedI > & I);
-    template <
-      typename DerivedVA,
-      typename DerivedFA,
-      typename DerivedVB,
-      typename DerivedFB,
-      typename DerivedVC,
-      typename DerivedFC,
-      typename DerivedJ,
-      typename DerivedI>
-    IGL_INLINE void mesh_boolean(
-      const Eigen::PlainObjectBase<DerivedVA > & VA,
-      const Eigen::PlainObjectBase<DerivedFA > & FA,
-      const Eigen::PlainObjectBase<DerivedVB > & VB,
-      const Eigen::PlainObjectBase<DerivedFB > & FB,
-      const MeshBooleanType & type,
-      Eigen::PlainObjectBase<DerivedVC > & VC,
-      Eigen::PlainObjectBase<DerivedFC > & FC,
-      Eigen::PlainObjectBase<DerivedJ > & J,
-      Eigen::PlainObjectBase<DerivedI > & I);
-    template <
-      typename DerivedVA,
-      typename DerivedFA,
-      typename DerivedVB,
-      typename DerivedFB,
-      typename DerivedVC,
-      typename DerivedFC>
-    IGL_INLINE void mesh_boolean(
-      const Eigen::PlainObjectBase<DerivedVA > & VA,
-      const Eigen::PlainObjectBase<DerivedFA > & FA,
-      const Eigen::PlainObjectBase<DerivedVB > & VB,
-      const Eigen::PlainObjectBase<DerivedFB > & FB,
-      const MeshBooleanType & type,
-      Eigen::PlainObjectBase<DerivedVC > & VC,
-      Eigen::PlainObjectBase<DerivedFC > & FC);
-
-  }
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "mesh_boolean.cpp"
-#endif
-
-#endif

+ 0 - 54
include/igl/boolean/mesh_boolean_cork.h

@@ -1,54 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_BOOLEAN_MESH_BOOLEAN_CORK_H
-#define IGL_BOOLEAN_MESH_BOOLEAN_CORK_H
-#ifndef IGL_NO_CORK
-#include "MeshBooleanType.h"
-#include <igl/igl_inline.h>
-#include <Eigen/Core>
-#include <cork.h> // for consistent uint
-
-namespace igl
-{
-  namespace boolean
-  {
-    // Compute a boolean operation on two input meshes using the cork library.
-    //
-    // Inputs:
-    //   VA  #VA by 3 list of vertex positions of first mesh
-    //   FA  #FA by 3 list of triangle indices into VA
-    //   VB  #VB by 3 list of vertex positions of second mesh
-    //   FB  #FB by 3 list of triangle indices into VB
-    //   type  of boolean operation see MeshBooleanType.h
-    // Outputs:
-    //   VC  #VC by 3 list of vertex positions of output mesh
-    //   FC  #FC by 3 list of triangle indices into VC
-    template <
-      typename DerivedVA,
-      typename DerivedFA,
-      typename DerivedVB,
-      typename DerivedFB,
-      typename DerivedVC,
-      typename DerivedFC>
-    IGL_INLINE void mesh_boolean_cork(
-      const Eigen::PlainObjectBase<DerivedVA > & VA,
-      const Eigen::PlainObjectBase<DerivedFA > & FA,
-      const Eigen::PlainObjectBase<DerivedVB > & VB,
-      const Eigen::PlainObjectBase<DerivedFB > & FB,
-      const MeshBooleanType & type,
-      Eigen::PlainObjectBase<DerivedVC > & VC,
-      Eigen::PlainObjectBase<DerivedFC > & FC);
-  }
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "mesh_boolean_cork.cpp"
-#endif
-#endif
-
-#endif

+ 0 - 41
include/igl/boolean/string_to_mesh_boolean_type.h

@@ -1,41 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_BOOLEAN_STRING_TO_MESH_BOOLEAN_H
-#define IGL_BOOLEAN_STRING_TO_MESH_BOOLEAN_H
-
-#include <igl/igl_inline.h>
-#include "MeshBooleanType.h"
-#include <string>
-
-namespace igl
-{
-  namespace boolean
-  {
-    // Convert string to boolean type
-    //
-    //  Inputs:
-    //    s  string identifying type, one of the following:
-    //      "union","intersect","minus","xor","resolve"
-    //  Outputs:
-    //    type  type of boolean operation
-    // Returns true only on success
-    //     
-    IGL_INLINE bool string_to_mesh_boolean_type(
-      const std::string & s,
-      MeshBooleanType & type);
-    // Returns type without error handling
-    IGL_INLINE MeshBooleanType string_to_mesh_boolean_type(
-      const std::string & s);
-  }
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "string_to_mesh_boolean_type.cpp"
-#endif
-
-#endif

+ 0 - 38
include/igl/boolean/to_cork_mesh.h

@@ -1,38 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_BOOLEAN_TO_CORK_MESH_H
-#define IGL_BOOLEAN_TO_CORK_MESH_H
-#ifndef IGL_NO_CORK
-#include <igl/igl_inline.h>
-#include <cork.h>
-#include <Eigen/Core>
-namespace igl
-{
-  namespace boolean
-  {
-    // Convert a (V,F) mesh to a cork's triangle mesh representation.
-    //
-    // Inputs:
-    //   V  #V by 3 list of vertex positions
-    //   F  #F by 3 list of triangle indices into V
-    // Outputs:
-    //   mesh  cork representation of mesh
-    template <
-      typename DerivedV,
-      typename DerivedF>
-    IGL_INLINE void to_cork_mesh(
-      const Eigen::PlainObjectBase<DerivedV > & V,
-      const Eigen::PlainObjectBase<DerivedF > & F,
-      CorkTriMesh & mesh);
-  }
-}
-#ifndef IGL_STATIC_LIBRARY
-#  include "to_cork_mesh.cpp"
-#endif
-#endif
-#endif

+ 4 - 1
include/igl/boundary_conditions.cpp

@@ -162,8 +162,11 @@ IGL_INLINE bool igl::boundary_conditions(
 
   // If there's only a single boundary condition, the following tests
   // are overzealous.
-  if(bc.rows() == 1)
+  if(bc.cols() == 1)
   {
+    // If there is only one weight function,
+    // then we expect that there is only one handle.
+    assert(P.rows() + BE.rows() == 1);
     return true;
   }
 

+ 3 - 3
include/igl/boundary_loop.cpp

@@ -23,10 +23,10 @@ IGL_INLINE void igl::boundary_loop(
   if(F.rows() == 0)
     return;
 
-  MatrixXd Vdummy(F.maxCoeff()+1,1);
-  MatrixXi TT,TTi;
+  VectorXd Vdummy(F.maxCoeff()+1,1);
+  DerivedF TT,TTi;
   vector<std::vector<int> > VF, VFi;
-  triangle_triangle_adjacency(Vdummy,F,TT,TTi);
+  triangle_triangle_adjacency(F,TT,TTi);
   vertex_triangle_adjacency(Vdummy,F,VF,VFi);
 
   vector<bool> unvisited = is_border_vertex(Vdummy,F);

+ 0 - 28
include/igl/cgal/RemeshSelfIntersectionsParam.h

@@ -1,28 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_CGAL_REMESH_SELF_INTERSECTIONS_PARAM_H
-#define IGL_CGAL_REMESH_SELF_INTERSECTIONS_PARAM_H
-
-namespace igl
-{
-  namespace cgal
-  {
-    // Optional Parameters
-    //   DetectOnly  Only compute IF, leave VV and FF alone
-    struct RemeshSelfIntersectionsParam
-    {
-      bool detect_only;
-      bool first_only;
-      RemeshSelfIntersectionsParam():detect_only(false),first_only(false){};
-      RemeshSelfIntersectionsParam(bool _detect_only, bool _first_only):
-        detect_only(_detect_only),first_only(_first_only){};
-    };
-  }
-}
-
-#endif

+ 0 - 34
include/igl/cgal/assign_scalar.h

@@ -1,34 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_CGAL_ASSIGN_SCALAR_H
-#define IGL_CGAL_ASSIGN_SCALAR_H
-#include "../igl_inline.h"
-#include "CGAL_includes.hpp"
-namespace igl
-{
-  namespace cgal
-  {
-    // Inputs:
-    //   cgal  cgal scalar
-    // Outputs:
-    //   d  output scalar
-    IGL_INLINE void assign_scalar(
-      const typename CGAL::Epeck::FT & cgal,
-      CGAL::Epeck::FT & d);
-    IGL_INLINE void assign_scalar(
-      const typename CGAL::Epeck::FT & cgal,
-      double & d);
-    IGL_INLINE void assign_scalar(
-      const double & c,
-      double & d);
-  }
-}
-#ifndef IGL_STATIC_LIBRARY
-#  include "assign_scalar.cpp"
-#endif
-#endif

+ 0 - 44
include/igl/cgal/complex_to_mesh.h

@@ -1,44 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_CGAL_COMPLEX_TO_MESH_H
-#define IGL_CGAL_COMPLEX_TO_MESH_H
-#include "../igl_inline.h"
-
-#include <Eigen/Dense>
-#include <CGAL/Complex_2_in_triangulation_3.h>
-
-namespace igl 
-{
-  namespace cgal
-  {
-    // Templates:
-    //   Tr  CGAL triangulation type, e.g.
-    //     CGAL::Surface_mesh_default_triangulation_3
-    // Inputs
-    //   c2t3  2-complex (surface) living in a 3d triangulation (e.g. result of
-    //     CGAL::make_surface_mesh)
-    // Outputs:
-    //   V  #V by 3 list of vertex positions
-    //   F  #F by 3 list of triangle indices
-    // Returns true iff conversion was successful, failure can ok if CGAL code
-    // can't figure out ordering.
-    //
-    template <typename Tr, typename DerivedV, typename DerivedF>
-    IGL_INLINE bool complex_to_mesh(
-      const CGAL::Complex_2_in_triangulation_3<Tr> & c2t3,
-      Eigen::PlainObjectBase<DerivedV> & V, 
-      Eigen::PlainObjectBase<DerivedF> & F);
-  }
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "complex_to_mesh.cpp"
-#endif
-
-#endif
-

+ 0 - 270
include/igl/cgal/intersect_other.cpp

@@ -1,270 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#include "intersect_other.h"
-#include "CGAL_includes.hpp"
-#include "mesh_to_cgal_triangle_list.h"
-#include "remesh_intersections.h"
-
-#ifndef IGL_FIRST_HIT_EXCEPTION
-#define IGL_FIRST_HIT_EXCEPTION 10
-#endif
-
-// Un-exposed helper functions
-namespace igl
-{
-  namespace cgal
-  {
-    template <typename DerivedF>
-    static IGL_INLINE void push_result(
-      const Eigen::PlainObjectBase<DerivedF> & F,
-      const int f,
-      const CGAL::Object & result,
-      std::map<
-        typename DerivedF::Index,
-        std::pair<typename DerivedF::Index,
-          std::vector<CGAL::Object> > > & offending,
-      std::map<
-        std::pair<typename DerivedF::Index,typename DerivedF::Index>,
-        std::vector<typename DerivedF::Index> > & edge2faces)
-    {
-      typedef typename DerivedF::Index Index;
-      typedef std::pair<Index,Index> EMK;
-      if(offending.count(f) == 0)
-      {
-        // first time marking, initialize with new id and empty list
-        Index id = offending.size();
-        offending[f] = {id,{}};
-        for(Index e = 0; e<3;e++)
-        {
-          // 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 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);
-        }
-      }
-      offending[f].second.push_back(result);
-    }
-    template <
-      typename Kernel,
-      typename DerivedVA,
-      typename DerivedFA,
-      typename DerivedVB,
-      typename DerivedFB,
-      typename DerivedIF,
-      typename DerivedVVA,
-      typename DerivedFFA,
-      typename DerivedJA,
-      typename DerivedIMA,
-      typename DerivedVVB,
-      typename DerivedFFB,
-      typename DerivedJB,
-      typename DerivedIMB>
-    static IGL_INLINE bool intersect_other_helper(
-      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)
-    {
-
-      using namespace std;
-      using namespace Eigen;
-
-      typedef typename DerivedFA::Index Index;
-      // 3D Primitives
-      typedef CGAL::Point_3<Kernel>    Point_3;
-      typedef CGAL::Segment_3<Kernel>  Segment_3; 
-      typedef CGAL::Triangle_3<Kernel> Triangle_3; 
-      typedef CGAL::Plane_3<Kernel>    Plane_3;
-      typedef CGAL::Tetrahedron_3<Kernel> Tetrahedron_3; 
-      // 2D Primitives
-      typedef CGAL::Point_2<Kernel>    Point_2;
-      typedef CGAL::Segment_2<Kernel>  Segment_2; 
-      typedef CGAL::Triangle_2<Kernel> Triangle_2; 
-      // 2D Constrained Delaunay Triangulation types
-      typedef CGAL::Triangulation_vertex_base_2<Kernel>  TVB_2;
-      typedef CGAL::Constrained_triangulation_face_base_2<Kernel> CTAB_2;
-      typedef CGAL::Triangulation_data_structure_2<TVB_2,CTAB_2> TDS_2;
-      typedef CGAL::Exact_intersections_tag Itag;
-      typedef CGAL::Constrained_Delaunay_triangulation_2<Kernel,TDS_2,Itag> 
-        CDT_2;
-      typedef CGAL::Constrained_triangulation_plus_2<CDT_2> CDT_plus_2;
-      // Axis-align boxes for all-pairs self-intersection detection
-      typedef std::vector<Triangle_3> Triangles;
-      typedef typename Triangles::iterator TrianglesIterator;
-      typedef typename Triangles::const_iterator TrianglesConstIterator;
-      typedef 
-        CGAL::Box_intersection_d::Box_with_handle_d<double,3,TrianglesIterator> 
-        Box;
-      typedef 
-        std::map<Index,std::pair<Index,std::vector<CGAL::Object> > > 
-        OffendingMap;
-      typedef std::map<std::pair<Index,Index>,std::vector<Index> >  EdgeMap;
-      typedef std::pair<Index,Index> EMK;
-
-      Triangles TA,TB;
-      // Compute and process self intersections
-      mesh_to_cgal_triangle_list(VA,FA,TA);
-      mesh_to_cgal_triangle_list(VB,FB,TB);
-      // http://www.cgal.org/Manual/latest/doc_html/cgal_manual/Box_intersection_d/Chapter_main.html#Section_63.5 
-      // Create the corresponding vector of bounding boxes
-      std::vector<Box> A_boxes,B_boxes;
-      const auto box_up = [](Triangles & T, std::vector<Box> & boxes)
-      {
-        boxes.reserve(T.size());
-        for ( 
-          TrianglesIterator tit = T.begin(); 
-          tit != T.end(); 
-          ++tit)
-        {
-          boxes.push_back(Box(tit->bbox(), tit));
-        }
-      };
-      box_up(TA,A_boxes);
-      box_up(TB,B_boxes);
-      OffendingMap offendingA,offendingB;
-      EdgeMap edge2facesA,edge2facesB;
-
-      std::list<int> lIF;
-      const auto cb = [&](const Box &a, const Box &b)
-      {
-        using namespace std;
-        // index in F and T
-        int fa = a.handle()-TA.begin();
-        int fb = b.handle()-TB.begin();
-        const Triangle_3 & A = *a.handle();
-        const Triangle_3 & B = *b.handle();
-        if(CGAL::do_intersect(A,B))
-        {
-          // There was an intersection
-          lIF.push_back(fa);
-          lIF.push_back(fb);
-          if(params.first_only)
-          {
-            throw IGL_FIRST_HIT_EXCEPTION;
-          }
-          if(!params.detect_only)
-          {
-            CGAL::Object result = CGAL::intersection(A,B);
-
-            push_result(FA,fa,result,offendingA,edge2facesA);
-            push_result(FB,fb,result,offendingB,edge2facesB);
-          }
-        }
-      };
-      try{
-        CGAL::box_intersection_d(
-          A_boxes.begin(), A_boxes.end(),
-          B_boxes.begin(), B_boxes.end(),
-          cb);
-      }catch(int e)
-      {
-        // Rethrow if not FIRST_HIT_EXCEPTION
-        if(e != IGL_FIRST_HIT_EXCEPTION)
-        {
-          throw e;
-        }
-        // Otherwise just fall through
-      }
-
-      // Convert lIF to Eigen matrix
-      assert(lIF.size()%2 == 0);
-      IF.resize(lIF.size()/2,2);
-      {
-        int i=0;
-        for(
-          list<int>::const_iterator ifit = lIF.begin();
-          ifit!=lIF.end();
-          )
-        {
-          IF(i,0) = (*ifit);
-          ifit++; 
-          IF(i,1) = (*ifit);
-          ifit++;
-          i++;
-        }
-      }
-      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);
-      }
-
-      return IF.rows() > 0;
-    }
-  }
-}
-
-template <
-  typename DerivedVA,
-  typename DerivedFA,
-  typename DerivedVB,
-  typename DerivedFB,
-  typename DerivedIF,
-  typename DerivedVVA,
-  typename DerivedFFA,
-  typename DerivedJA,
-  typename DerivedIMA,
-  typename DerivedVVB,
-  typename DerivedFFB,
-  typename DerivedJB,
-  typename DerivedIMB>
-IGL_INLINE bool igl::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)
-{
-  if(params.detect_only)
-  {
-    return intersect_other_helper<CGAL::Epick>
-      (VA,FA,VB,FB,params,IF,VVA,FFA,JA,IMA,VVB,FFB,JB,IMB);
-  }else
-  {
-    return intersect_other_helper<CGAL::Epeck>
-      (VA,FA,VB,FB,params,IF,VVA,FFA,JA,IMA,VVB,FFB,JB,IMB);
-  }
-}
-
-IGL_INLINE bool igl::cgal::intersect_other(
-  const Eigen::MatrixXd & VA,
-  const Eigen::MatrixXi & FA,
-  const Eigen::MatrixXd & VB,
-  const Eigen::MatrixXi & FB,
-  const bool first_only,
-  Eigen::MatrixXi & IF)
-{
-  Eigen::MatrixXd VVA,VVB;
-  Eigen::MatrixXi FFA,FFB;
-  Eigen::VectorXi JA,JB,IMA,IMB;
-  return intersect_other(
-    VA,FA,VB,FB,{true,first_only},IF,VVA,FFA,JA,IMA,VVB,FFB,JB,IMB);
-}
-
-#ifdef IGL_STATIC_LIBRARY
-// Explicit template specialization
-#endif

+ 0 - 106
include/igl/cgal/intersect_other.h

@@ -1,106 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_CGAL_INTERSECT_OTHER_H
-#define IGL_CGAL_INTERSECT_OTHER_H
-#include "../igl_inline.h"
-#include "RemeshSelfIntersectionsParam.h"
-
-#include <Eigen/Dense>
-
-#ifdef MEX
-#  include <mex.h>
-#  include <cassert>
-#  undef assert
-#  define assert( isOK ) ( (isOK) ? (void)0 : (void) mexErrMsgTxt(C_STR(__FILE__<<":"<<__LINE__<<": failed assertion `"<<#isOK<<"'"<<std::endl) ) )
-#endif
-
-namespace igl
-{
-  namespace cgal
-  {
-    // INTERSECT_OTHER Given a triangle mesh (VA,FA) and another mesh (VB,FB)
-    // find all pairs of intersecting faces. Note that self-intersections are
-    // ignored.
-    // 
-    // Inputs:
-    //   VA  #V by 3 list of vertex positions
-    //   FA  #F by 3 list of triangle indices into VA
-    //   VB  #V by 3 list of vertex positions
-    //   FB  #F by 3 list of triangle indices into VB
-    //   params   whether to detect only and then whether to only find first
-    //     intersection
-    // Outputs:
-    //   IF  #intersecting face pairs by 2 list of intersecting face pairs,
-    //     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.
-    template <
-      typename DerivedVA,
-      typename DerivedFA,
-      typename DerivedVB,
-      typename DerivedFB,
-      typename DerivedIF,
-      typename DerivedVVA,
-      typename DerivedFFA,
-      typename DerivedJA,
-      typename DerivedIMA,
-      typename DerivedVVB,
-      typename DerivedFFB,
-      typename DerivedJB,
-      typename DerivedIMB>
-    IGL_INLINE bool 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);
-    // Legacy wrapper for detect only using common types.
-    //
-    // Inputs:
-    //   VA  #V by 3 list of vertex positions
-    //   FA  #F by 3 list of triangle indices into VA
-    //   VB  #V by 3 list of vertex positions
-    //   FB  #F by 3 list of triangle indices into VB
-    //   first_only  whether to only detect the first intersection.
-    // Outputs:
-    //   IF  #intersecting face pairs by 2 list of intersecting face pairs,
-    //     indexing FA and FB
-    // Returns true if any intersections were found
-    //
-    // See also: remesh_self_intersections
-    IGL_INLINE bool intersect_other(
-      const Eigen::MatrixXd & VA,
-      const Eigen::MatrixXi & FA,
-      const Eigen::MatrixXd & VB,
-      const Eigen::MatrixXi & FB,
-      const bool first_only,
-      Eigen::MatrixXi & IF);
-  }
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "intersect_other.cpp"
-#endif
-  
-#endif
-

+ 0 - 63
include/igl/cgal/mesh_to_cgal_triangle_list.cpp

@@ -1,63 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#include "mesh_to_cgal_triangle_list.h"
-#include "assign_scalar.h"
-
-#include <cassert>
-
-template <
-  typename DerivedV,
-  typename DerivedF,
-  typename Kernel>
-IGL_INLINE void igl::cgal::mesh_to_cgal_triangle_list(
-  const Eigen::PlainObjectBase<DerivedV> & V,
-  const Eigen::PlainObjectBase<DerivedF> & F,
-  std::vector<CGAL::Triangle_3<Kernel> > & T)
-{
-  typedef CGAL::Point_3<Kernel>    Point_3;
-  typedef CGAL::Triangle_3<Kernel> Triangle_3; 
-  // Must be 3D
-  assert(V.cols() == 3);
-  // **Copy** to convert to output type (this is especially/only needed if the
-  // input type DerivedV::Scalar is CGAL::Epeck
-  Eigen::Matrix<
-    typename Kernel::FT,
-    DerivedV::RowsAtCompileTime,
-    DerivedV::ColsAtCompileTime> 
-    KV(V.rows(),V.cols());
-  // Just use f'ing for loops. What if V and KV don't use same ordering?
-  for(int i = 0;i<V.rows();i++)
-  {
-    for(int j = 0;j<V.cols();j++)
-    {
-      assign_scalar(V(i,j),KV(i,j));
-    }
-  }
-  // Must be triangles
-  assert(F.cols() == 3);
-  T.reserve(F.rows());
-  // Loop over faces
-  for(int f = 0;f<(int)F.rows();f++)
-  {
-    T.push_back(
-      Triangle_3(
-        Point_3( KV(F(f,0),0), KV(F(f,0),1), KV(F(f,0),2)),
-        Point_3( KV(F(f,1),0), KV(F(f,1),1), KV(F(f,1),2)),
-        Point_3( KV(F(f,2),0), KV(F(f,2),1), KV(F(f,2),2))));
-  }
-}
-
-#ifdef IGL_STATIC_LIBRARY
-// Explicit template specialization
-template void igl::cgal::mesh_to_cgal_triangle_list<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epeck>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epeck>, std::allocator<CGAL::Triangle_3<CGAL::Epeck> > >&);
-template void igl::cgal::mesh_to_cgal_triangle_list<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epick>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > >&);
-template void igl::cgal::mesh_to_cgal_triangle_list<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epeck>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<CGAL::Triangle_3<CGAL::Epeck>, std::allocator<CGAL::Triangle_3<CGAL::Epeck> > >&);
-template void igl::cgal::mesh_to_cgal_triangle_list<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epick>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > >&);
-template void igl::cgal::mesh_to_cgal_triangle_list<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epeck>(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epeck>, std::allocator<CGAL::Triangle_3<CGAL::Epeck> > >&);
-template void igl::cgal::mesh_to_cgal_triangle_list<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epick>(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > >&);
-#endif

+ 0 - 41
include/igl/cgal/mesh_to_cgal_triangle_list.h

@@ -1,41 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_CGAL_MESH_TO_CGAL_TRIANGLE_LIST_H
-#define IGL_CGAL_MESH_TO_CGAL_TRIANGLE_LIST_H
-#include <igl/igl_inline.h>
-#include <Eigen/Core>
-#include "CGAL_includes.hpp"
-namespace igl
-{
-  namespace cgal
-  {
-    // Convert a mesh (V,F) to a list of CGAL triangles
-    //
-    // Templates:
-    //   Kernal  CGAL computation and construction kernel (e.g.
-    //     CGAL::Exact_predicates_exact_constructions_kernel)
-    // Inputs:
-    //   V  #V by 3 list of vertex positions
-    //   F  #F by 3 list of triangle indices
-    // Outputs:
-    //   T  #F list of CGAL triangles
-    template <
-      typename DerivedV,
-      typename DerivedF,
-      typename Kernel>
-    IGL_INLINE void mesh_to_cgal_triangle_list(
-      const Eigen::PlainObjectBase<DerivedV> & V,
-      const Eigen::PlainObjectBase<DerivedF> & F,
-      std::vector<CGAL::Triangle_3<Kernel> > & T);
-  }
-}
-#ifndef IGL_STATIC_LIBRARY
-#  include "mesh_to_cgal_triangle_list.cpp"
-#endif
-
-#endif

+ 0 - 39
include/igl/cgal/mesh_to_polyhedron.h

@@ -1,39 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_CGAL_MESH_TO_POLYHEDRON_H
-#define IGL_CGAL_MESH_TO_POLYHEDRON_H
-#include <igl/igl_inline.h>
-#include <Eigen/Core>
-
-namespace igl
-{
-  namespace cgal
-  {
-    // Convert a mesh (V,F) to a CGAL Polyhedron
-    //
-    // Templates:
-    //   Polyhedron  CGAL Polyhedron type (e.g. Polyhedron_3)
-    // Inputs:
-    //   V  #V by 3 list of vertex positions
-    //   F  #F by 3 list of triangle indices
-    // Outputs:
-    //   poly  cgal polyhedron
-    // Returns true only if (V,F) can be converted to a valid polyhedron (i.e. if
-    // (V,F) is vertex and edge manifold).
-    template <typename Polyhedron>
-    IGL_INLINE bool mesh_to_polyhedron(
-      const Eigen::MatrixXd & V,
-      const Eigen::MatrixXi & F,
-      Polyhedron & poly);
-  }
-}
-#ifndef IGL_STATIC_LIBRARY
-#  include "mesh_to_polyhedron.cpp"
-#endif
-
-#endif

+ 0 - 393
include/igl/cgal/order_facets_around_edge.cpp

@@ -1,393 +0,0 @@
-#include "order_facets_around_edge.h"
-#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
-
-namespace igl
-{
-    namespace cgal
-    {
-        namespace order_facets_around_edges_helper
-        {
-            template<typename T>
-            std::vector<size_t> index_sort(const std::vector<T>& data)
-            {
-                const size_t len = data.size();
-                std::vector<size_t> order(len);
-                for (size_t i=0; i<len; i++) 
-                {
-                    order[i] = i;
-                }
-                auto comp = [&](size_t i, size_t j) 
-                {
-                    return data[i] < data[j];
-                };
-                std::sort(order.begin(), order.end(), comp);
-                return order;
-            }
-        }
-    }
-}
-
-// adj_faces contains signed index starting from +- 1.
-template<
-    typename DerivedV,
-    typename DerivedF,
-    typename DerivedI >
-void igl::cgal::order_facets_around_edge(
-    const Eigen::PlainObjectBase<DerivedV>& V,
-    const Eigen::PlainObjectBase<DerivedF>& F,
-    size_t s,
-    size_t d, 
-    const std::vector<int>& adj_faces,
-    Eigen::PlainObjectBase<DerivedI>& order)
-{
-    using namespace igl::cgal::order_facets_around_edges_helper;
-
-    // Although we only need exact predicates in the algorithm,
-    // exact constructions are needed to avoid degeneracies due to
-    // casting to double.
-    typedef CGAL::Exact_predicates_exact_constructions_kernel K;
-    typedef K::Point_3 Point_3;
-    typedef K::Plane_3 Plane_3;
-
-    auto get_face_index = [&](int adj_f)->size_t
-    {
-        return abs(adj_f) - 1;
-    };
-
-    auto get_opposite_vertex = [&](size_t fid)->size_t
-    {
-        typedef typename DerivedF::Scalar Index;
-        if (F(fid, 0) != (Index)s && F(fid, 0) != (Index)d) return F(fid, 0);
-        if (F(fid, 1) != (Index)s && F(fid, 1) != (Index)d) return F(fid, 1);
-        if (F(fid, 2) != (Index)s && F(fid, 2) != (Index)d) return F(fid, 2);
-        assert(false);
-        return -1;
-    };
-
-    // Handle base cases
-    if (adj_faces.size() == 0) 
-    {
-        order.resize(0, 1);
-        return;
-    } else if (adj_faces.size() == 1)
-    {
-        order.resize(1, 1);
-        order(0, 0) = 0;
-        return;
-    } else if (adj_faces.size() == 2)
-    {
-        const size_t o1 = get_opposite_vertex(get_face_index(adj_faces[0]));
-        const size_t o2 = get_opposite_vertex(get_face_index(adj_faces[1]));
-        const Point_3 ps(V(s, 0), V(s, 1), V(s, 2));
-        const Point_3 pd(V(d, 0), V(d, 1), V(d, 2));
-        const Point_3 p1(V(o1, 0), V(o1, 1), V(o1, 2));
-        const Point_3 p2(V(o2, 0), V(o2, 1), V(o2, 2));
-        order.resize(2, 1);
-        switch (CGAL::orientation(ps, pd, p1, p2))
-        {
-            case CGAL::POSITIVE:
-                order(0, 0) = 1;
-                order(1, 0) = 0;
-                break;
-            case CGAL::NEGATIVE:
-                order(0, 0) = 0;
-                order(1, 0) = 1;
-                break;
-            case CGAL::COPLANAR:
-                {
-                    switch (CGAL::coplanar_orientation(ps, pd, p1, p2)) {
-                        case CGAL::POSITIVE:
-                            // Duplicated face, use index to break tie.
-                            order(0, 0) = adj_faces[0] < adj_faces[1] ? 0:1;
-                            order(1, 0) = adj_faces[0] < adj_faces[1] ? 1:0;
-                            break;
-                        case CGAL::NEGATIVE:
-                            // Coplanar faces, one on each side of the edge.
-                            // It is equally valid to order them (0, 1) or (1, 0).
-                            // I cannot think of any reason to prefer one to the
-                            // other.  So just use (0, 1) ordering by default.
-                            order(0, 0) = 0;
-                            order(1, 0) = 1;
-                            break;
-                        case CGAL::COLLINEAR:
-                            std::cerr << "Degenerated triangle detected." <<
-                                std::endl;
-                            assert(false);
-                            break;
-                        default:
-                            assert(false);
-                    }
-                }
-                break;
-            default:
-                assert(false);
-        }
-        return;
-    }
-
-    const size_t num_adj_faces = adj_faces.size();
-    const size_t o = get_opposite_vertex( get_face_index(adj_faces[0]));
-    const Point_3 p_s(V(s, 0), V(s, 1), V(s, 2));
-    const Point_3 p_d(V(d, 0), V(d, 1), V(d, 2));
-    const Point_3 p_o(V(o, 0), V(o, 1), V(o, 2));
-    const Plane_3 separator(p_s, p_d, p_o);
-    assert(!separator.is_degenerate());
-
-    std::vector<Point_3> opposite_vertices;
-    for (size_t i=0; i<num_adj_faces; i++)
-    {
-        const size_t o = get_opposite_vertex( get_face_index(adj_faces[i]));
-        opposite_vertices.emplace_back(
-                V(o, 0), V(o, 1), V(o, 2));
-    }
-
-    std::vector<int> positive_side;
-    std::vector<int> negative_side;
-    std::vector<int> tie_positive_oriented;
-    std::vector<int> tie_negative_oriented;
-
-    std::vector<size_t> positive_side_index;
-    std::vector<size_t> negative_side_index;
-    std::vector<size_t> tie_positive_oriented_index;
-    std::vector<size_t> tie_negative_oriented_index;
-
-    for (size_t i=0; i<num_adj_faces; i++)
-    {
-        const int f = adj_faces[i];
-        const Point_3& p_a = opposite_vertices[i];
-        auto orientation = separator.oriented_side(p_a);
-        switch (orientation) {
-            case CGAL::ON_POSITIVE_SIDE:
-                positive_side.push_back(f);
-                positive_side_index.push_back(i);
-                break;
-            case CGAL::ON_NEGATIVE_SIDE:
-                negative_side.push_back(f);
-                negative_side_index.push_back(i);
-                break;
-            case CGAL::ON_ORIENTED_BOUNDARY:
-                {
-                    auto inplane_orientation = CGAL::coplanar_orientation(
-                            p_s, p_d, p_o, p_a);
-                    switch (inplane_orientation) {
-                        case CGAL::POSITIVE:
-                            tie_positive_oriented.push_back(f);
-                            tie_positive_oriented_index.push_back(i);
-                            break;
-                        case CGAL::NEGATIVE:
-                            tie_negative_oriented.push_back(f);
-                            tie_negative_oriented_index.push_back(i);
-                            break;
-                        case CGAL::COLLINEAR:
-                        default:
-                            assert(false);
-                            break;
-                    }
-                }
-                break;
-            default:
-                // Should not be here.
-                assert(false);
-        }
-    }
-
-    Eigen::PlainObjectBase<DerivedI> positive_order, negative_order;
-    order_facets_around_edge(V, F, s, d, positive_side, positive_order);
-    order_facets_around_edge(V, F, s, d, negative_side, negative_order);
-    std::vector<size_t> tie_positive_order = index_sort(tie_positive_oriented);
-    std::vector<size_t> tie_negative_order = index_sort(tie_negative_oriented);
-
-    // Copy results into order vector.
-    const size_t tie_positive_size = tie_positive_oriented.size();
-    const size_t tie_negative_size = tie_negative_oriented.size();
-    const size_t positive_size = positive_order.size();
-    const size_t negative_size = negative_order.size();
-
-    order.resize(
-      tie_positive_size + positive_size + tie_negative_size + negative_size,1);
-
-    size_t count=0;
-    for (size_t i=0; i<tie_positive_size; i++)
-    {
-        order(count+i, 0) = tie_positive_oriented_index[tie_positive_order[i]];
-    }
-    count += tie_positive_size;
-
-    for (size_t i=0; i<negative_size; i++) 
-    {
-        order(count+i, 0) = negative_side_index[negative_order(i, 0)];
-    }
-    count += negative_size;
-
-    for (size_t i=0; i<tie_negative_size; i++)
-    {
-        order(count+i, 0) = tie_negative_oriented_index[tie_negative_order[i]];
-    }
-    count += tie_negative_size;
-
-    for (size_t i=0; i<positive_size; i++)
-    {
-        order(count+i, 0) = positive_side_index[positive_order(i, 0)];
-    }
-    count += positive_size;
-    assert(count == num_adj_faces);
-
-    // Find the correct start point.
-    size_t start_idx = 0;
-    for (size_t i=0; i<num_adj_faces; i++)
-    {
-        const Point_3& p_a = opposite_vertices[order(i, 0)];
-        const Point_3& p_b =
-            opposite_vertices[order((i+1)%num_adj_faces, 0)];
-        auto orientation = CGAL::orientation(p_s, p_d, p_a, p_b);
-        if (orientation == CGAL::POSITIVE)
-        {
-            // Angle between triangle (p_s, p_d, p_a) and (p_s, p_d, p_b) is
-            // more than 180 degrees.
-            start_idx = (i+1)%num_adj_faces;
-            break;
-        } else if (orientation == CGAL::COPLANAR &&
-                Plane_3(p_s, p_d, p_a).orthogonal_direction() !=
-                Plane_3(p_s, p_d, p_b).orthogonal_direction())
-        {
-            // All 4 points are coplanar, but p_a and p_b are on each side of
-            // the edge (p_s, p_d).  This means the angle between triangle
-            // (p_s, p_d, p_a) and (p_s, p_d, p_b) is exactly 180 degrees.
-            start_idx = (i+1)%num_adj_faces;
-            break;
-        }
-    }
-    DerivedI circular_order = order;
-    for (size_t i=0; i<num_adj_faces; i++)
-    {
-        order(i, 0) = circular_order((start_idx + i)%num_adj_faces, 0);
-    }
-}
-
-template<
-    typename DerivedV,
-    typename DerivedF,
-    typename DerivedI>
-IGL_INLINE
-void igl::cgal::order_facets_around_edge(
-        const Eigen::PlainObjectBase<DerivedV>& V,
-        const Eigen::PlainObjectBase<DerivedF>& F,
-        size_t s,
-        size_t d, 
-        const std::vector<int>& adj_faces,
-        const Eigen::PlainObjectBase<DerivedV>& pivot_point,
-        Eigen::PlainObjectBase<DerivedI>& order)
-{
-
-    assert(V.cols() == 3);
-    assert(F.cols() == 3);
-    auto signed_index_to_index = [&](int signed_idx)
-    {
-        return abs(signed_idx) -1;
-    };
-    auto get_opposite_vertex_index = [&](size_t fid)
-    {
-        typedef typename DerivedF::Scalar Index;
-        if (F(fid, 0) != (Index)s && F(fid, 0) != (Index)d) return F(fid, 0);
-        if (F(fid, 1) != (Index)s && F(fid, 1) != (Index)d) return F(fid, 1);
-        if (F(fid, 2) != (Index)s && F(fid, 2) != (Index)d) return F(fid, 2);
-        assert(false);
-        // avoid warning
-        return -1;
-    };
-
-    {
-        // Check if s, d and pivot are collinear.
-        typedef CGAL::Exact_predicates_exact_constructions_kernel K;
-        K::Point_3 ps(V(s,0), V(s,1), V(s,2));
-        K::Point_3 pd(V(d,0), V(d,1), V(d,2));
-        K::Point_3 pp(pivot_point(0,0), pivot_point(0,1), pivot_point(0,2));
-        if (CGAL::collinear(ps, pd, pp)) {
-            throw "Pivot point is collinear with the outer edge!";
-        }
-    }
-
-    const size_t N = adj_faces.size();
-    const size_t num_faces = N + 1; // N adj faces + 1 pivot face
-
-    // Because face indices are used for tie breaking, the original face indices
-    // in the new faces array must be ascending.
-    auto comp = [&](int i, int j) {
-        return signed_index_to_index(i) < signed_index_to_index(j);
-    };
-    std::vector<int> ordered_adj_faces(adj_faces);
-    std::sort(ordered_adj_faces.begin(), ordered_adj_faces.end(), comp);
-
-    DerivedV vertices(num_faces + 2, 3);
-    for (size_t i=0; i<N; i++) {
-        const size_t fid = signed_index_to_index(ordered_adj_faces[i]);
-        vertices.row(i) = V.row(get_opposite_vertex_index(fid));
-    }
-    vertices.row(N  ) = pivot_point;
-    vertices.row(N+1) = V.row(s);
-    vertices.row(N+2) = V.row(d);
-
-    DerivedF faces(num_faces, 3);
-    for (size_t i=0; i<N; i++)
-    {
-        if (ordered_adj_faces[i] < 0) {
-            faces(i,0) = N+1; // s
-            faces(i,1) = N+2; // d
-            faces(i,2) = i  ;
-        } else {
-            faces(i,0) = N+2; // d
-            faces(i,1) = N+1; // s
-            faces(i,2) = i  ;
-        }
-    }
-    // Last face is the pivot face.
-    faces(N, 0) = N+1;
-    faces(N, 1) = N+2;
-    faces(N, 2) = N;
-
-    std::vector<int> adj_faces_with_pivot(num_faces);
-    for (size_t i=0; i<num_faces; i++)
-    {
-        if ((size_t)faces(i,0) == N+1 && (size_t)faces(i,1) == N+2)
-        {
-            adj_faces_with_pivot[i] = int(i+1) * -1;
-        } else
-        {
-            adj_faces_with_pivot[i] = int(i+1);
-        }
-    }
-
-    DerivedI order_with_pivot;
-    igl::cgal::order_facets_around_edge(
-            vertices, faces, N+1, N+2,
-            adj_faces_with_pivot, order_with_pivot);
-
-    assert((size_t)order_with_pivot.size() == num_faces);
-    order.resize(N);
-    size_t pivot_index = num_faces + 1;
-    for (size_t i=0; i<num_faces; i++)
-    {
-        if ((size_t)order_with_pivot[i] == N)
-        {
-            pivot_index = i;
-            break;
-        }
-    }
-    assert(pivot_index < num_faces);
-
-    for (size_t i=0; i<N; i++)
-    {
-        order[i] = order_with_pivot[(pivot_index+i+1)%num_faces];
-    }
-}
-
-
-#ifdef IGL_STATIC_LIBRARY
-// Explicit template specialization
-template void igl::cgal::order_facets_around_edge<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, unsigned long, unsigned long, std::vector<int, std::allocator<int> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template void igl::cgal::order_facets_around_edge<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, unsigned long, unsigned long, std::vector<int, std::allocator<int> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template void igl::cgal::order_facets_around_edge<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&, unsigned long, unsigned long, std::vector<int, std::allocator<int> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template void igl::cgal::order_facets_around_edge<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, unsigned long, unsigned long, std::vector<int, std::allocator<int> > 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> >&);
-template void igl::cgal::order_facets_around_edge<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, unsigned long, unsigned long, std::vector<int, std::allocator<int> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template void igl::cgal::order_facets_around_edge<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&, unsigned long, unsigned long, std::vector<int, std::allocator<int> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-#endif

+ 0 - 70
include/igl/cgal/order_facets_around_edge.h

@@ -1,70 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2015 Qingnan Zhou <qnzhou@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-//
-#ifndef ORDER_FACETS_AROUND_EDGE_H
-#define ORDER_FACETS_AROUND_EDGE_H
-#include "../igl_inline.h"
-#include <Eigen/Core>
-#include <vector>
-
-namespace igl {
-    namespace cgal {
-        // Given a directed edge, sort its adjacent faces.  Assuming the
-        // directed edge is (s, d).  Sort the adjacent faces clockwise around the
-        // axis (d - s), i.e. left-hand rule.  An adjacent face is consistently
-        // oriented if it contains (d, s) as a directed edge.
-        //
-        // For overlapping faces, break the tie using signed face index, smaller
-        // signed index comes before the larger signed index.  Signed index is
-        // computed as (consistent? 1:-1) * (face_index + 1).
-        //
-        // Inputs:
-        //   V          #V by 3 list of vertices.
-        //   F          #F by 3 list of faces
-        //   s          Index of source vertex.
-        //   d          Index of desination vertex.
-        //   adj_faces  List of adjacent face signed indices.
-        //
-        // Output:
-        //   order      List of face indices that orders adjacent faces around
-        //              edge (s, d) clockwise.
-        template<
-            typename DerivedV,
-            typename DerivedF,
-            typename DerivedI >
-        IGL_INLINE
-        void order_facets_around_edge(
-                const Eigen::PlainObjectBase<DerivedV>& V,
-                const Eigen::PlainObjectBase<DerivedF>& F,
-                size_t s, size_t d, 
-                const std::vector<int>& adj_faces,
-                Eigen::PlainObjectBase<DerivedI>& order);
-
-        // This funciton is a wrapper around the one above.  Since the ordering
-        // is circular, the pivot point is used to define a starting point.  So
-        // order[0] is the index into adj_face that is immediately after the
-        // pivot face (s, d, pivot point) in clockwise order.
-        template<
-            typename DerivedV,
-            typename DerivedF,
-            typename DerivedI>
-        IGL_INLINE
-        void order_facets_around_edge(
-                const Eigen::PlainObjectBase<DerivedV>& V,
-                const Eigen::PlainObjectBase<DerivedF>& F,
-                size_t s, size_t d, 
-                const std::vector<int>& adj_faces,
-                const Eigen::PlainObjectBase<DerivedV>& pivot_point,
-                Eigen::PlainObjectBase<DerivedI>& order);
-    }
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#include "order_facets_around_edge.cpp"
-#endif
-#endif

+ 0 - 104
include/igl/cgal/order_facets_around_edges.h

@@ -1,104 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_CGAL_ORDER_FACETS_AROUND_EDGES_H
-#define IGL_CGAL_ORDER_FACETS_AROUND_EDGES_H
-#include "../igl_inline.h"
-#include <Eigen/Core>
-#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
-#include <vector>
-
-namespace igl
-{
-  namespace cgal
-  {
-    // For each undirected edge, sort its adjacent faces.  Assuming the
-    // undirected edge is (s, d).  Sort the adjacent faces clockwise around the
-    // axis (d - s), i.e. left-hand rule.  An adjacent face is consistently
-    // oriented if it contains (d, s) as a directed edge.
-    //
-    // For overlapping faces, break the tie using signed face index, smaller
-    // signed index comes before the larger signed index.  Signed index is
-    // computed as (consistent? 1:-1) * index.
-    //
-    // Inputs:
-    //   V    #V by 3 list of vertices.
-    //   F    #F by 3 list of faces
-    //   N    #F by 3 list of face normals.
-    //  uE    #uE by 2 list of vertex_indices, represents undirected edges.
-    //  uE2E  #uE list of lists that maps uE to E. (a one-to-many map)
-    //
-    // Outputs:
-    //   uE2oE #uE list of lists that maps uE to an ordered list of E. (a
-    //         one-to-many map)
-    //   uE2C  #uE list of lists of bools indicates whether each face in
-    //         uE2oE[i] is consistently orientated as the ordering.
-    //
-    template<
-        typename DerivedV,
-        typename DerivedF,
-        typename DerivedN,
-        typename DeriveduE,
-        typename uE2EType,
-        typename uE2oEType,
-        typename uE2CType >
-    IGL_INLINE
-    typename std::enable_if<!std::is_same<typename DerivedV::Scalar,
-    typename CGAL::Exact_predicates_exact_constructions_kernel::FT>::value, void>::type
-    order_facets_around_edges(
-            const Eigen::PlainObjectBase<DerivedV>& V,
-            const Eigen::PlainObjectBase<DerivedF>& F,
-            const Eigen::PlainObjectBase<DerivedN>& N,
-            const Eigen::PlainObjectBase<DeriveduE>& uE,
-            const std::vector<std::vector<uE2EType> >& uE2E,
-            std::vector<std::vector<uE2oEType> >& uE2oE,
-            std::vector<std::vector<uE2CType > >& uE2C );
-
-    template<
-        typename DerivedV,
-        typename DerivedF,
-        typename DerivedN,
-        typename DeriveduE,
-        typename uE2EType,
-        typename uE2oEType,
-        typename uE2CType >
-    IGL_INLINE 
-    typename std::enable_if<std::is_same<typename DerivedV::Scalar,
-    typename CGAL::Exact_predicates_exact_constructions_kernel::FT>::value, void>::type
-    order_facets_around_edges(
-            const Eigen::PlainObjectBase<DerivedV>& V,
-            const Eigen::PlainObjectBase<DerivedF>& F,
-            const Eigen::PlainObjectBase<DerivedN>& N,
-            const Eigen::PlainObjectBase<DeriveduE>& uE,
-            const std::vector<std::vector<uE2EType> >& uE2E,
-            std::vector<std::vector<uE2oEType> >& uE2oE,
-            std::vector<std::vector<uE2CType > >& uE2C );
-
-    // Order faces around each edge. Only exact predicate is used in the algorithm.
-    // Normal is not needed.
-    template<
-        typename DerivedV,
-        typename DerivedF,
-        typename DeriveduE,
-        typename uE2EType,
-        typename uE2oEType,
-        typename uE2CType >
-    IGL_INLINE void order_facets_around_edges(
-            const Eigen::PlainObjectBase<DerivedV>& V,
-            const Eigen::PlainObjectBase<DerivedF>& F,
-            const Eigen::PlainObjectBase<DeriveduE>& uE,
-            const std::vector<std::vector<uE2EType> >& uE2E,
-            std::vector<std::vector<uE2oEType> >& uE2oE,
-            std::vector<std::vector<uE2CType > >& uE2C );
-  }
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#include "order_facets_around_edges.cpp"
-#endif
-
-#endif

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

@@ -1,51 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_CGAL_OUTER_HULL_H
-#define IGL_CGAL_OUTER_HULL_H
-#include "../igl_inline.h"
-#include <Eigen/Core>
-namespace igl
-{
-  namespace cgal
-  {
-    // Compute the "outer hull" of a potentially non-manifold mesh (V,F) whose
-    // intersections have been "resolved" (e.g. using `cork` or
-    // `igl::cgal::selfintersect`). The outer hull is defined to be all facets
-    // (regardless of orientation) for which there exists some path from infinity
-    // to the face without intersecting any other facets. For solids, this is the
-    // surface of the solid. In general this includes any thin "wings" or
-    // "flaps".  This implementation largely follows Section 3.6 of "Direct
-    // repair of self-intersecting meshes" [Attene 2014].
-    //
-    // Inputs:
-    //   V  #V by 3 list of vertex positions
-    //   F  #F by 3 list of triangle indices into V
-    // Outputs:
-    //   G  #G by 3 list of output triangle indices into V
-    //   J  #G list of indices into F
-    //   flip  #F list of whether facet was added to G **and** flipped orientation
-    //     (false for faces not added to G)
-    template <
-      typename DerivedV,
-      typename DerivedF,
-      typename DerivedG,
-      typename DerivedJ,
-      typename Derivedflip>
-    IGL_INLINE void outer_hull(
-      const Eigen::PlainObjectBase<DerivedV> & V,
-      const Eigen::PlainObjectBase<DerivedF> & F,
-      Eigen::PlainObjectBase<DerivedG> & G,
-      Eigen::PlainObjectBase<DerivedJ> & J,
-      Eigen::PlainObjectBase<Derivedflip> & flip);
-  }
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "outer_hull.cpp"
-#endif
-#endif

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

@@ -1,44 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_CGAL_PEEL_OUTER_HULL_LAYERS_H
-#define IGL_CGAL_PEEL_OUTER_HULL_LAYERS_H
-#include "../igl_inline.h"
-#include <Eigen/Core>
-namespace igl
-{
-  namespace cgal
-  {
-    // Computes necessary generic information for boolean operations by
-    // successively "peeling" off the "outer hull" of a mesh (V,F) resulting from
-    // "resolving" all (self-)intersections.
-    //
-    // Inputs:
-    //   V  #V by 3 list of vertex positions
-    //   F  #F by 3 list of triangle indices into V
-    // Outputs:
-    //   I  #F list of which peel Iation a facet belongs 
-    //   flip  #F list of whether a facet's orientation was flipped when facet
-    //     "peeled" into its associated outer hull layer.
-    // Returns number of peels
-    template <
-      typename DerivedV,
-      typename DerivedF,
-      typename DerivedI,
-      typename Derivedflip>
-    IGL_INLINE size_t peel_outer_hull_layers(
-      const Eigen::PlainObjectBase<DerivedV > & V,
-      const Eigen::PlainObjectBase<DerivedF > & F,
-      Eigen::PlainObjectBase<DerivedI > & I,
-      Eigen::PlainObjectBase<Derivedflip > & flip);
-  }
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "peel_outer_hull_layers.cpp"
-#endif
-#endif

+ 0 - 85
include/igl/cgal/point_mesh_squared_distance.h

@@ -1,85 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_CGAL_POINT_MESH_SQUARED_DISTANCE_H
-#define IGL_CGAL_POINT_MESH_SQUARED_DISTANCE_H
-#include <igl/igl_inline.h>
-#include <Eigen/Core>
-#include <vector>
-#include "CGAL_includes.hpp"
-namespace igl
-{
-  namespace cgal
-  {
-    // Compute distances from a set of points P to a triangle mesh (V,F)
-    //
-    // Templates:
-    //   Kernal  CGAL computation and construction kernel (e.g.
-    //     CGAL::Simple_cartesian<double>)
-    // Inputs:
-    //   P  #P by 3 list of query point positions
-    //   V  #V by 3 list of vertex positions
-    //   F  #F by 3 list of triangle indices
-    // Outputs:
-    //   sqrD  #P list of smallest squared distances
-    //   I  #P list of facet indices corresponding to smallest distances
-    //   C  #P by 3 list of closest points
-    //
-    // Known bugs: This only computes distances to triangles. So unreferenced
-    // vertices and degenerate triangles (segments) are ignored.
-    template <typename Kernel>
-    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);
-    // Probably can do this in a way that we don't pass around `tree` and `T`
-    //
-    // Outputs:
-    //   tree  CGAL's AABB tree
-    //   T  list of CGAL triangles in order of F (for determining which was found
-    //     in computation)
-    template <typename Kernel>
-    IGL_INLINE void point_mesh_squared_distance_precompute(
-      const Eigen::MatrixXd & V,
-      const Eigen::MatrixXi & F,
-      CGAL::AABB_tree<
-        CGAL::AABB_traits<Kernel, 
-          CGAL::AABB_triangle_primitive<Kernel, 
-            typename std::vector<CGAL::Triangle_3<Kernel> >::iterator
-          >
-        >
-      > & tree,
-      std::vector<CGAL::Triangle_3<Kernel> > & T);
-    // Inputs:
-    //  see above
-    // Outputs:
-    //  see above
-    template <typename Kernel>
-    IGL_INLINE void point_mesh_squared_distance(
-      const Eigen::MatrixXd & P,
-      const CGAL::AABB_tree<
-        CGAL::AABB_traits<Kernel, 
-          CGAL::AABB_triangle_primitive<Kernel, 
-            typename std::vector<CGAL::Triangle_3<Kernel> >::iterator
-          >
-        >
-      > & tree,
-      const std::vector<CGAL::Triangle_3<Kernel> > & T,
-      Eigen::VectorXd & sqrD,
-      Eigen::VectorXi & I,
-      Eigen::MatrixXd & C);
-  }
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "point_mesh_squared_distance.cpp"
-#endif
-
-#endif

+ 0 - 59
include/igl/cgal/points_inside_component.h

@@ -1,59 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2015 Qingnan Zhou <qnzhou@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef POINTS_INSIDE_COMPONENTS
-#define POINTS_INSIDE_COMPONENTS
-
-#include "../igl_inline.h"
-#include <Eigen/Core>
-#include <vector>
-
-namespace igl {
-    namespace cgal {
-
-        // Determine if queries points P are inside of connected facet component
-        // (V, F, I), where I indicates a subset of facets that forms the
-        // component.
-        //
-        // Precondition:
-        // The input mesh must be a closed, self-intersection free,
-        // non-degenerated surface.  Queries points must be either inside or
-        // outside of the mesh (i.e. not on the surface of the mesh).
-        //
-        // Inputs:
-        //   V  #V by 3 array of vertex positions.
-        //   F  #F by 3 array of triangles.
-        //   I  #I list of triangle indices to consider.
-        //   P  #P by 3 array of query points.
-        //
-        // Outputs:
-        //   inside  #P list of booleans that is true iff the corresponding
-        //           query point is inside of the mesh.
-        template<typename DerivedV, typename DerivedF, typename DerivedI,
-            typename DerivedP, typename DerivedB>
-            IGL_INLINE void points_inside_component(
-                    const Eigen::PlainObjectBase<DerivedV>& V,
-                    const Eigen::PlainObjectBase<DerivedF>& F,
-                    const Eigen::PlainObjectBase<DerivedI>& I,
-                    const Eigen::PlainObjectBase<DerivedP>& P,
-                    Eigen::PlainObjectBase<DerivedB>& inside);
-
-        // Determine if query points P is inside of the mesh (V, F).
-        // See above for precondition and I/O specs.
-        template<typename DerivedV, typename DerivedF, typename DerivedP, typename DerivedB>
-            IGL_INLINE void points_inside_component(
-                    const Eigen::PlainObjectBase<DerivedV>& V,
-                    const Eigen::PlainObjectBase<DerivedF>& F,
-                    const Eigen::PlainObjectBase<DerivedP>& P,
-                    Eigen::PlainObjectBase<DerivedB>& inside);
-    }
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#include "points_inside_component.cpp"
-#endif
-#endif

+ 0 - 37
include/igl/cgal/polyhedron_to_mesh.h

@@ -1,37 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_CGAL_POLYHEDRON_TO_MESH_H
-#define IGL_CGAL_POLYHEDRON_TO_MESH_H
-#include <igl/igl_inline.h>
-#include <Eigen/Core>
-
-namespace igl
-{
-  namespace cgal
-  {
-    // Convert a CGAL Polyhedron to a mesh (V,F)
-    //
-    // Templates:
-    //   Polyhedron  CGAL Polyhedron type (e.g. Polyhedron_3)
-    // Inputs:
-    //   poly  cgal polyhedron
-    // Outputs:
-    //   V  #V by 3 list of vertex positions
-    //   F  #F by 3 list of triangle indices
-    template <typename Polyhedron>
-    IGL_INLINE void polyhedron_to_mesh(
-      const Polyhedron & poly,
-      Eigen::MatrixXd & V,
-      Eigen::MatrixXi & F);
-  }
-}
-#ifndef IGL_STATIC_LIBRARY
-#  include "polyhedron_to_mesh.cpp"
-#endif
-
-#endif

+ 0 - 43
include/igl/cgal/projected_delaunay.h

@@ -1,43 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_CGAL_PROJECTED_DELAUNAY_H
-#define IGL_CGAL_PROJECTED_DELAUNAY_H
-#include "../igl_inline.h"
-#include "CGAL_includes.hpp"
-namespace igl
-{
-  namespace cgal
-  {
-    // Compute 2D delaunay triangulation of a given 3d triangle and a list of
-    // intersection objects (points,segments,triangles). CGAL uses an affine
-    // projection rather than an isometric projection, so we're not guaranteed
-    // that the 2D delaunay triangulation here will be a delaunay triangulation
-    // in 3D.
-    //
-    // Inputs:
-    //   A  triangle in 3D
-    //   A_objects_3  updated list of intersection objects for A
-    // Outputs:
-    //   cdt  Contrained delaunay triangulation in projected 2D plane
-    template <typename Kernel>
-    IGL_INLINE void projected_delaunay(
-      const CGAL::Triangle_3<Kernel> & A,
-      const std::vector<CGAL::Object> & A_objects_3,
-      CGAL::Constrained_triangulation_plus_2<
-        CGAL::Constrained_Delaunay_triangulation_2<
-          Kernel,
-          CGAL::Triangulation_data_structure_2<
-            CGAL::Triangulation_vertex_base_2<Kernel>,
-            CGAL::Constrained_triangulation_face_base_2<Kernel> >,
-          CGAL::Exact_intersections_tag> > & cdt);
-  }
-}
-#ifndef IGL_STATIC_LIBRARY
-#  include "projected_delaunay.cpp"
-#endif
-#endif

+ 0 - 328
include/igl/cgal/remesh_intersections.cpp

@@ -1,328 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#include "remesh_intersections.h"
-#include "SelfIntersectMesh.h"
-#include "assign_scalar.h"
-#include "projected_delaunay.h"
-#include <iostream>
-#include <cassert>
-
-template <
-  typename DerivedV,
-  typename DerivedF,
-  typename Kernel,
-  typename DerivedVV,
-  typename DerivedFF,
-  typename DerivedJ,
-  typename DerivedIM>
-IGL_INLINE void igl::cgal::remesh_intersections(
-  const Eigen::PlainObjectBase<DerivedV> & V,
-  const Eigen::PlainObjectBase<DerivedF> & F,
-  const std::vector<CGAL::Triangle_3<Kernel> > & T,
-  const std::map<
-    typename DerivedF::Index,
-    std::pair<typename DerivedF::Index,
-      std::vector<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<DerivedFF> & FF,
-  Eigen::PlainObjectBase<DerivedJ> & J,
-  Eigen::PlainObjectBase<DerivedIM> & IM)
-{
-  using namespace std;
-  using namespace Eigen;
-  typedef typename DerivedF::Index          Index;
-  typedef CGAL::Point_3<Kernel>    Point_3;
-  //typedef CGAL::Segment_3<Kernel>  Segment_3; 
-  //typedef CGAL::Triangle_3<Kernel> Triangle_3; 
-  typedef CGAL::Plane_3<Kernel>    Plane_3;
-  //typedef CGAL::Point_2<Kernel>    Point_2;
-  //typedef CGAL::Segment_2<Kernel>  Segment_2; 
-  //typedef CGAL::Triangle_2<Kernel> Triangle_2; 
-  typedef CGAL::Triangulation_vertex_base_2<Kernel>  TVB_2;
-  typedef CGAL::Constrained_triangulation_face_base_2<Kernel> CTFB_2;
-  typedef CGAL::Triangulation_data_structure_2<TVB_2,CTFB_2> TDS_2;
-  typedef CGAL::Exact_intersections_tag Itag;
-  typedef CGAL::Constrained_Delaunay_triangulation_2<Kernel,TDS_2,Itag> 
-    CDT_2;
-  typedef CGAL::Constrained_triangulation_plus_2<CDT_2> CDT_plus_2;
-  typedef std::pair<Index,Index> EMK;
-  typedef std::vector<Index> EMV;
-  //typedef std::map<EMK,EMV> EdgeMap;
-  typedef std::pair<Index,Index> EMK;
-  //typedef std::vector<CGAL::Object> ObjectList;
-  typedef std::vector<Index> IndexList;
-
-  int NF_count = 0;
-  // list of new faces, we'll fix F later
-  vector<
-    typename Eigen::Matrix<typename DerivedFF::Scalar,Dynamic,Dynamic>
-    > NF(offending.size());
-  // list of new vertices
-  typedef vector<Point_3> Point_3List;
-  Point_3List NV;
-  Index NV_count = 0;
-  vector<CDT_plus_2> cdt(offending.size());
-  vector<Plane_3> P(offending.size());
-  // Use map for *all* faces
-  map<typename CDT_plus_2::Vertex_handle,Index> v2i;
-#ifdef IGL_SELFINTERSECTMESH_DEBUG
-  double t_proj_del = 0;
-#endif
-  // Unfortunately it looks like CGAL has trouble allocating memory when
-  // multiple openmp threads are running. Crashes durring CDT...
-  //// Loop over offending triangles
-  //const size_t noff = offending.size();
-//# pragma omp parallel for if (noff>1000)
-  for(const auto & okv : offending)
-  {
-    // index in F
-    const Index f = okv.first;
-    const Index o = okv.second.first;
-    {
-#ifdef IGL_SELFINTERSECTMESH_DEBUG
-      const double t_before = get_seconds();
-#endif
-      CDT_plus_2 cdt_o;
-      projected_delaunay(T[f],okv.second.second,cdt_o);
-      cdt[o] = cdt_o;
-#ifdef IGL_SELFINTERSECTMESH_DEBUG
-      t_proj_del += (get_seconds()-t_before);
-#endif
-    }
-    // Q: Is this also delaunay in 3D?
-    // A: No, because the projection is affine and delaunay is not affine
-    // invariant.
-    // Q: Then, can't we first get the 2D delaunay triangulation, then lift it
-    // to 3D and flip any offending edges?
-    // Plane of projection (also used by projected_delaunay)
-    P[o] = Plane_3(T[f].vertex(0),T[f].vertex(1),T[f].vertex(2));
-    // Build index map
-    {
-      Index i=0;
-      for(
-        typename CDT_plus_2::Finite_vertices_iterator vit = cdt[o].finite_vertices_begin();
-        vit != cdt[o].finite_vertices_end();
-        ++vit)
-      {
-        if(i<3)
-        {
-          //cout<<T[f].vertex(i)<<
-          //  (T[f].vertex(i) == P[o].to_3d(vit->point())?" == ":" != ")<<
-          //  P[o].to_3d(vit->point())<<endl;
-#ifndef NDEBUG
-          // I want to be sure that the original corners really show up as the
-          // original corners of the CDT. I.e. I don't trust CGAL to maintain
-          // the order
-          assert(T[f].vertex(i) == P[o].to_3d(vit->point()));
-#endif
-          // For first three, use original index in F
-//#   pragma omp critical
-          v2i[vit] = F(f,i);
-        }else
-        {
-          const Point_3 vit_point_3 = P[o].to_3d(vit->point());
-          // First look up each edge's neighbors to see if exact point has
-          // already been added (This makes everything a bit quadratic)
-          bool found = false;
-          for(int e = 0; e<3 && !found;e++)
-          {
-            // Index of F's eth edge in V
-            Index i = F(f,(e+1)%3);
-            Index j = F(f,(e+2)%3);
-            // Be sure that i<j
-            if(i>j)
-            {
-              swap(i,j);
-            }
-            assert(edge2faces.count(EMK(i,j))==1);
-            const EMV & facesij = edge2faces.find(EMK(i,j))->second;
-            // loop over neighbors
-            for(
-              typename IndexList::const_iterator nit = facesij.begin();
-              nit != facesij.end() && !found;
-              nit++)
-            {
-              // don't consider self
-              if(*nit == f)
-              {
-                continue;
-              }
-              // index of neighbor in offending (to find its cdt)
-              assert(offending.count(*nit) == 1);
-              Index no = offending.find(*nit)->second.first;
-              // Loop over vertices of that neighbor's cdt (might not have been
-              // processed yet, but then it's OK because it'll just be empty)
-              for(
-                  typename CDT_plus_2::Finite_vertices_iterator uit = cdt[no].finite_vertices_begin();
-                  uit != cdt[no].finite_vertices_end() && !found;
-                  ++uit)
-              {
-                if(vit_point_3 == P[no].to_3d(uit->point()))
-                {
-                  assert(v2i.count(uit) == 1);
-//#   pragma omp critical
-                  v2i[vit] = v2i[uit];
-                  found = true;
-                }
-              }
-            }
-          }
-          if(!found)
-          {
-//#   pragma omp critical
-            {
-              v2i[vit] = V.rows()+NV_count;
-              NV.push_back(vit_point_3);
-              NV_count++;
-            }
-          }
-        }
-        i++;
-      }
-    }
-    {
-      Index i = 0;
-      // Resize to fit new number of triangles
-      NF[o].resize(cdt[o].number_of_faces(),3);
-//#   pragma omp atomic
-      NF_count+=NF[o].rows();
-      // Append new faces to NF
-      for(
-        typename CDT_plus_2::Finite_faces_iterator fit = cdt[o].finite_faces_begin();
-        fit != cdt[o].finite_faces_end();
-        ++fit)
-      {
-        NF[o](i,0) = v2i[fit->vertex(0)];
-        NF[o](i,1) = v2i[fit->vertex(1)];
-        NF[o](i,2) = v2i[fit->vertex(2)];
-        i++;
-      }
-    }
-  }
-#ifdef IGL_SELFINTERSECTMESH_DEBUG
-  cout<<"CDT: "<<tictoc()<<"  "<<t_proj_del<<endl;
-#endif
-
-  assert(NV_count == (Index)NV.size());
-  // Build output
-#ifndef NDEBUG
-  //{
-  //  Index off_count = 0;
-  //  for(Index f = 0;f<F.rows();f++)
-  //  {
-  //    off_count+= (offensive[f]?1:0);
-  //  }
-  //  assert(off_count==(Index)offending.size());
-  //}
-#endif
-  // Append faces
-  FF.resize(F.rows()-offending.size()+NF_count,3);
-  J.resize(FF.rows());
-  // First append non-offending original faces
-  // There's an Eigen way to do this in one line but I forget
-  Index off = 0;
-  for(Index f = 0;f<F.rows();f++)
-  {
-    if(!offending.count(f))
-    {
-      FF.row(off) = F.row(f);
-      J(off) = f;
-      off++;
-    }
-  }
-  assert(off == (Index)(F.rows()-offending.size()));
-  // Now append replacement faces for offending faces
-  for(const auto & okv : offending)
-  {
-    // index in F
-    const Index f = okv.first;
-    const Index o = okv.second.first;
-    FF.block(off,0,NF[o].rows(),3) = NF[o];
-    J.block(off,0,NF[o].rows(),1).setConstant(f);
-    off += NF[o].rows();
-  }
-  // Append vertices
-  VV.resize(V.rows()+NV_count,3);
-  VV.block(0,0,V.rows(),3) = V.template cast<typename DerivedVV::Scalar>();
-  {
-    Index i = 0;
-    for(
-      typename Point_3List::const_iterator nvit = NV.begin();
-      nvit != NV.end();
-      nvit++)
-    {
-      for(Index d = 0;d<3;d++)
-      {
-        const Point_3 & p = *nvit;
-        // Don't convert via double if output type is same as Kernel
-        assign_scalar(p[d], VV(V.rows()+i,d));
-      }
-      i++;
-    }
-  }
-  IM.resize(VV.rows(),1);
-  map<Point_3,Index> vv2i;
-  // Safe to check for duplicates using double for original vertices: if
-  // incoming reps are different then the points are unique.
-  for(Index v = 0;v<V.rows();v++)
-  {
-    typename Kernel::FT p0,p1,p2;
-    assign_scalar(V(v,0),p0);
-    assign_scalar(V(v,1),p1);
-    assign_scalar(V(v,2),p2);
-    const Point_3 p(p0,p1,p2);
-    if(vv2i.count(p)==0)
-    {
-      vv2i[p] = v;
-    }
-    assert(vv2i.count(p) == 1);
-    IM(v) = vv2i[p];
-  }
-  // Must check for duplicates of new vertices using exact.
-  {
-    Index v = V.rows();
-    for(
-      typename Point_3List::const_iterator nvit = NV.begin();
-      nvit != NV.end();
-      nvit++)
-    {
-      const Point_3 & p = *nvit;
-      if(vv2i.count(p)==0)
-      {
-        vv2i[p] = v;
-      }
-      assert(vv2i.count(p) == 1);
-      IM(v) = vv2i[p];
-      v++;
-    }
-  }
-#ifdef IGL_SELFINTERSECTMESH_DEBUG
-  cout<<"Output + dupes: "<<tictoc()<<endl;
-#endif
-}
-
-#ifdef IGL_STATIC_LIBRARY
-// Explicit template specialization
-template void igl::cgal::remesh_intersections<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epeck, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epeck>, std::allocator<CGAL::Triangle_3<CGAL::Epeck> > > const&, std::map<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > >, std::less<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index const, std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > > > > > const&, std::map<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::vector<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::allocator<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> >, std::less<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> >, std::allocator<std::pair<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> const, std::vector<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::allocator<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> > > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template void igl::cgal::remesh_intersections<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epeck, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epeck>, std::allocator<CGAL::Triangle_3<CGAL::Epeck> > > const&, std::map<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > >, std::less<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index const, std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > > > > > const&, std::map<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::vector<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::allocator<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> >, std::less<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> >, std::allocator<std::pair<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> const, std::vector<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::allocator<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> > > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template void igl::cgal::remesh_intersections<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epeck, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epeck>, std::allocator<CGAL::Triangle_3<CGAL::Epeck> > > const&, std::map<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > >, std::less<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index const, std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > > > > > const&, std::map<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::vector<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::allocator<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> >, std::less<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> >, std::allocator<std::pair<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> const, std::vector<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::allocator<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> > > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template void igl::cgal::remesh_intersections<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epeck, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epeck>, std::allocator<CGAL::Triangle_3<CGAL::Epeck> > > const&, std::map<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > >, std::less<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index const, std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > > > > > const&, std::map<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::vector<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::allocator<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> >, std::less<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> >, std::allocator<std::pair<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> const, std::vector<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::allocator<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> > > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template void igl::cgal::remesh_intersections<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epick, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > > const&, std::map<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > >, std::less<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index const, std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > > > > > const&, std::map<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::vector<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::allocator<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> >, std::less<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> >, std::allocator<std::pair<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> const, std::vector<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::allocator<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> > > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template void igl::cgal::remesh_intersections<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epick, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > > const&, std::map<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > >, std::less<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index const, std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > > > > > const&, std::map<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::vector<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::allocator<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> >, std::less<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> >, std::allocator<std::pair<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> const, std::vector<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::allocator<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> > > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template void igl::cgal::remesh_intersections<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epick, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > > const&, std::map<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > >, std::less<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index const, std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > > > > > const&, std::map<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::vector<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::allocator<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> >, std::less<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> >, std::allocator<std::pair<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> const, std::vector<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::allocator<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> > > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template void igl::cgal::remesh_intersections<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epick, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > > const&, std::map<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > >, std::less<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index const, std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > > > > > const&, std::map<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::vector<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::allocator<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> >, std::less<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> >, std::allocator<std::pair<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> const, std::vector<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::allocator<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> > > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template void igl::cgal::remesh_intersections<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epeck, 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&, std::vector<CGAL::Triangle_3<CGAL::Epeck>, std::allocator<CGAL::Triangle_3<CGAL::Epeck> > > const&, std::map<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > >, std::less<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index>, std::allocator<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index const, std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > > > > > const&, std::map<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index>, std::vector<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, std::allocator<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index> >, std::less<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index> >, std::allocator<std::pair<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index> const, std::vector<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, std::allocator<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index> > > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template void igl::cgal::remesh_intersections<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epick, 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&, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > > const&, std::map<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > >, std::less<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index>, std::allocator<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index const, std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > > > > > const&, std::map<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index>, std::vector<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, std::allocator<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index> >, std::less<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index> >, std::allocator<std::pair<std::pair<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index> const, std::vector<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index, std::allocator<Eigen::Matrix<int, -1, -1, 0, -1, -1>::Index> > > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template void igl::cgal::remesh_intersections<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epeck, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -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, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epeck>, std::allocator<CGAL::Triangle_3<CGAL::Epeck> > > const&, std::map<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > >, std::less<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index const, std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > > > > > const&, std::map<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::vector<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::allocator<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> >, std::less<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> >, std::allocator<std::pair<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> const, std::vector<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::allocator<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> > > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template void igl::cgal::remesh_intersections<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epick, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -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, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > > const&, std::map<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > >, std::less<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index const, std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > > > > > const&, std::map<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::vector<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::allocator<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> >, std::less<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> >, std::allocator<std::pair<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> const, std::vector<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::allocator<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> > > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template void igl::cgal::remesh_intersections<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epeck, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<long, -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&, std::vector<CGAL::Triangle_3<CGAL::Epeck>, std::allocator<CGAL::Triangle_3<CGAL::Epeck> > > const&, std::map<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > >, std::less<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index const, std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > > > > > const&, std::map<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::vector<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::allocator<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> >, std::less<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> >, std::allocator<std::pair<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> const, std::vector<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::allocator<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> > > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&);
-template void igl::cgal::remesh_intersections<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epick, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<long, -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&, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > > const&, std::map<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > >, std::less<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::allocator<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index const, std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::vector<CGAL::Object, std::allocator<CGAL::Object> > > > > > const&, std::map<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index>, std::vector<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::allocator<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> >, std::less<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> >, std::allocator<std::pair<std::pair<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> const, std::vector<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index, std::allocator<Eigen::Matrix<int, -1, 3, 0, -1, 3>::Index> > > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&);
-#endif

+ 0 - 77
include/igl/cgal/remesh_intersections.h

@@ -1,77 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_CGAL_REMESH_INTERSECTIONS_H
-#define IGL_CGAL_REMESH_INTERSECTIONS_H
-#include <igl/igl_inline.h>
-
-#include <Eigen/Dense>
-#include "CGAL_includes.hpp"
-
-#ifdef MEX
-#  include <mex.h>
-#  include <cassert>
-#  undef assert
-#  define assert( isOK ) ( (isOK) ? (void)0 : (void) mexErrMsgTxt(C_STR(__FILE__<<":"<<__LINE__<<": failed assertion `"<<#isOK<<"'"<<std::endl) ) )
-#endif
-  
-namespace igl
-{
-  namespace cgal
-  {
-    // Remesh faces according to results of intersection detection and
-    // construction (e.g. from `igl::cgal::intersect_other` or
-    // `igl::cgal::SelfIntersectMesh`)
-    //
-    // Inputs:
-    //   V  #V by 3 list of vertex positions
-    //   F  #F by 3 list of triangle indices into V
-    //   T  #F list of cgal triangles
-    //   offending #offending map taking face indices into F to pairs of order
-    //     of first finding and list of intersection objects from all
-    //     intersections
-    //   edge2faces  #edges <= #offending*3 to incident offending faces 
-    // Outputs:
-    //   VV  #VV by 3 list of vertex positions
-    //   FF  #FF by 3 list of triangle indices into V
-    //   IF  #intersecting face pairs by 2  list of intersecting face pairs,
-    //     indexing F
-    //   J  #FF list of indices into F denoting birth triangle
-    //   IM  #VV list of indices into VV of unique vertices.
-    //
-    template <
-      typename DerivedV,
-      typename DerivedF,
-      typename Kernel,
-      typename DerivedVV,
-      typename DerivedFF,
-      typename DerivedJ,
-      typename DerivedIM>
-    IGL_INLINE void remesh_intersections(
-      const Eigen::PlainObjectBase<DerivedV> & V,
-      const Eigen::PlainObjectBase<DerivedF> & F,
-      const std::vector<CGAL::Triangle_3<Kernel> > & T,
-      const std::map<
-        typename DerivedF::Index,
-        std::pair<typename DerivedF::Index,
-          std::vector<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<DerivedFF> & FF,
-      Eigen::PlainObjectBase<DerivedJ> & J,
-      Eigen::PlainObjectBase<DerivedIM> & IM);
-  }
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "remesh_intersections.cpp"
-#endif
-  
-#endif
-

+ 0 - 92
include/igl/cgal/remesh_self_intersections.cpp

@@ -1,92 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
-//
-// This Source Code Form is subject to the terms of the Mozilla Public License
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can
-// obtain one at http://mozilla.org/MPL/2.0/.
-#include "remesh_self_intersections.h"
-#include "SelfIntersectMesh.h"
-#include <igl/C_STR.h>
-#include <list>
-#include <iostream>
-
-template <
-  typename DerivedV,
-  typename DerivedF,
-  typename DerivedVV,
-  typename DerivedFF,
-  typename DerivedIF,
-  typename DerivedJ,
-  typename DerivedIM>
-IGL_INLINE void igl::cgal::remesh_self_intersections(
-  const Eigen::PlainObjectBase<DerivedV> & V,
-  const Eigen::PlainObjectBase<DerivedF> & F,
-  const RemeshSelfIntersectionsParam & params,
-  Eigen::PlainObjectBase<DerivedVV> & VV,
-  Eigen::PlainObjectBase<DerivedFF> & FF,
-  Eigen::PlainObjectBase<DerivedIF> & IF,
-  Eigen::PlainObjectBase<DerivedJ> & J,
-  Eigen::PlainObjectBase<DerivedIM> & IM)
-{
-  using namespace std;
-  if(params.detect_only)
-  {
-    //// This is probably a terrible idea, but CGAL is throwing floating point
-    //// exceptions.
-
-//#ifdef __APPLE__
-//#define IGL_THROW_FPE 11
-//    const auto & throw_fpe = [](int e)
-//    {
-//      throw "IGL_THROW_FPE";
-//    };
-//    signal(SIGFPE,throw_fpe);
-//#endif
-
-    typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
-    typedef
-      SelfIntersectMesh<
-        Kernel,
-        DerivedV,
-        DerivedF,
-        DerivedVV,
-        DerivedFF,
-        DerivedIF,
-        DerivedJ,
-        DerivedIM>
-      SelfIntersectMeshK;
-    SelfIntersectMeshK SIM = SelfIntersectMeshK(V,F,params,VV,FF,IF,J,IM);
-
-//#ifdef __APPLE__
-//    signal(SIGFPE,SIG_DFL);
-//#endif
-
-  }else
-  {
-    typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
-    typedef
-      SelfIntersectMesh<
-        Kernel,
-        DerivedV,
-        DerivedF,
-        DerivedVV,
-        DerivedFF,
-        DerivedIF,
-        DerivedJ,
-        DerivedIM>
-      SelfIntersectMeshK;
-    SelfIntersectMeshK SIM = SelfIntersectMeshK(V,F,params,VV,FF,IF,J,IM);
-  }
-}
-
-#ifdef IGL_STATIC_LIBRARY
-// Explicit template specialization
-template void igl::cgal::remesh_self_intersections<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, igl::cgal::RemeshSelfIntersectionsParam const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template void igl::cgal::remesh_self_intersections<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::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<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, igl::cgal::RemeshSelfIntersectionsParam const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, 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::cgal::remesh_self_intersections<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::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, igl::cgal::RemeshSelfIntersectionsParam const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template void igl::cgal::remesh_self_intersections<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, igl::cgal::RemeshSelfIntersectionsParam const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template void igl::cgal::remesh_self_intersections<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, igl::cgal::RemeshSelfIntersectionsParam const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 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::cgal::remesh_self_intersections<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<long, -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, 3, 0, -1, 3> > const&, igl::cgal::RemeshSelfIntersectionsParam const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template void igl::cgal::remesh_self_intersections<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 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, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, igl::cgal::RemeshSelfIntersectionsParam const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&);
-#endif

+ 0 - 85
include/igl/cgal/remesh_self_intersections.h

@@ -1,85 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_CGAL_REMESH_SELF_INTERSECTIONS_H
-#define IGL_CGAL_REMESH_SELF_INTERSECTIONS_H
-#include <igl/igl_inline.h>
-#include "RemeshSelfIntersectionsParam.h"
-
-#include <Eigen/Dense>
-
-#ifdef MEX
-#  include <mex.h>
-#  include <cassert>
-#  undef assert
-#  define assert( isOK ) ( (isOK) ? (void)0 : (void) mexErrMsgTxt(C_STR(__FILE__<<":"<<__LINE__<<": failed assertion `"<<#isOK<<"'"<<std::endl) ) )
-#endif
-  
-namespace igl
-{
-  namespace cgal
-  {
-    // Given a triangle mesh (V,F) compute a new mesh (VV,FF) which is the same
-    // as (V,F) except that any self-intersecting triangles in (V,F) have been
-    // subdivided (new vertices and face created) so that the self-intersection
-    // contour lies exactly on edges in (VV,FF). New vertices will appear in
-    // original faces or on original edges. New vertices on edges are "merged"
-    // only across original faces sharing that edge. This means that if the input
-    // triangle mesh is a closed manifold the output will be too.
-    //
-    // Inputs:
-    //   V  #V by 3 list of vertex positions
-    //   F  #F by 3 list of triangle indices into V
-    //   params  struct of optional parameters
-    // Outputs:
-    //   VV  #VV by 3 list of vertex positions
-    //   FF  #FF by 3 list of triangle indices into VV
-    //   IF  #intersecting face pairs by 2  list of intersecting face pairs,
-    //     indexing F
-    //   J  #FF list of indices into F denoting birth triangle
-    //   IM  #VV list of indices into VV of unique vertices.
-    //
-    // Known bugs: If an existing edge in (V,F) lies exactly on another face then
-    // any resulting additional vertices along that edge may not get properly
-    // connected so that the output mesh has the same global topology. This is
-    // because 
-    //
-    // Example:
-    //     // resolve intersections
-    //     igl::cgal::remesh_self_intersections(V,F,params,VV,FF,IF,J,IM);
-    //     // _apply_ duplicate vertex mapping IM to FF
-    //     for_each(FF.data(),FF.data()+FF.size(),[&IM](int & a){a=IM(a);});
-    //     // remove any vertices now unreferenced after duplicate mapping.
-    //     igl::remove_unreferenced(VV,FF,SV,SF,UIM);
-    //     // Now (SV,SF) is ready to extract outer hull
-    //     igl::cgal::outer_hull(SV,SF,G,J,flip);
-    //
-    template <
-      typename DerivedV,
-      typename DerivedF,
-      typename DerivedVV,
-      typename DerivedFF,
-      typename DerivedIF,
-      typename DerivedJ,
-      typename DerivedIM>
-    IGL_INLINE void remesh_self_intersections(
-      const Eigen::PlainObjectBase<DerivedV> & V,
-      const Eigen::PlainObjectBase<DerivedF> & F,
-      const RemeshSelfIntersectionsParam & params,
-      Eigen::PlainObjectBase<DerivedVV> & VV,
-      Eigen::PlainObjectBase<DerivedFF> & FF,
-      Eigen::PlainObjectBase<DerivedIF> & IF,
-      Eigen::PlainObjectBase<DerivedJ> & J,
-      Eigen::PlainObjectBase<DerivedIM> & IM);
-  }
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "remesh_self_intersections.cpp"
-#endif
-  
-#endif

+ 0 - 51
include/igl/cgal/signed_distance_isosurface.h

@@ -1,51 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_CGAL_SIGNED_DISTANCE_ISOSURFACE_H
-#define IGL_CGAL_SIGNED_DISTANCE_ISOSURFACE_H
-#include "../igl_inline.h"
-#include "../signed_distance.h"
-#include <Eigen/Core>
-namespace igl
-{
-  namespace cgal
-  {
-    // SIGNED_DISTANCE_ISOSURFACE Compute the contour of an iso-level of the
-    // signed distance field to a given mesh.
-    //
-    // Inputs:
-    //   IV  #IV by 3 list of input mesh vertex positions
-    //   IF  #IF by 3 list of input triangle indices
-    //   level  iso-level to contour in world coords, negative is inside.
-    //   angle_bound  lower bound on triangle angles (mesh quality) (e.g. 28)
-    //   radius_bound  upper bound on triangle size (mesh density?) (e.g. 0.02)
-    //   distance_bound  cgal mysterious parameter (mesh density?) (e.g. 0.01)
-    //   sign_type  method for computing distance _sign_ (see
-    //     ../signed_distance.h)
-    // Outputs:
-    //   V  #V by 3 list of input mesh vertex positions
-    //   F  #F by 3 list of input triangle indices
-    //  
-    IGL_INLINE bool signed_distance_isosurface(
-      const Eigen::MatrixXd & IV,
-      const Eigen::MatrixXi & IF,
-      const double level,
-      const double angle_bound,
-      const double radius_bound,
-      const double distance_bound,
-      const SignedDistanceType sign_type,
-      Eigen::MatrixXd & V,
-      Eigen::MatrixXi & F);
-  }
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "signed_distance_isosurface.cpp"
-#endif
-
-#endif
-

+ 1 - 0
include/igl/colon.cpp

@@ -52,4 +52,5 @@ template void igl::colon<int, long, int>(int, long, Eigen::Matrix<int, -1, 1, 0,
 template void igl::colon<int, int, int>(int, int, Eigen::Matrix<int, -1, 1, 0, -1, 1>&);
 template void igl::colon<int,long long int,int>(int,long long int,Eigen::Matrix<int,-1,1,0,-1,1> &);
 template void igl::colon<int, int, int, int>(int, int, int, Eigen::Matrix<int, -1, 1, 0, -1, 1>&);
+template void igl::colon<int, long, long>(int, long, Eigen::Matrix<long, -1, 1, 0, -1, 1>&);
 #endif

+ 2 - 1
include/igl/comb_cross_field.cpp

@@ -27,6 +27,7 @@ namespace igl {
     const Eigen::PlainObjectBase<DerivedF> &F;
     const Eigen::PlainObjectBase<DerivedV> &PD1;
     const Eigen::PlainObjectBase<DerivedV> &PD2;
+#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
     Eigen::PlainObjectBase<DerivedV> N;
 
   private:
@@ -72,7 +73,7 @@ namespace igl {
     PD2(_PD2)
     {
       igl::per_face_normals(V,F,N);
-      igl::triangle_triangle_adjacency(V,F,TT,TTi);
+      igl::triangle_triangle_adjacency(F,TT,TTi);
     }
     inline void comb(Eigen::PlainObjectBase<DerivedV> &PD1out,
               Eigen::PlainObjectBase<DerivedV> &PD2out)

+ 1 - 1
include/igl/comb_frame_field.cpp

@@ -24,7 +24,7 @@ IGL_INLINE void igl::comb_frame_field(const Eigen::PlainObjectBase<DerivedV> &V,
                                       Eigen::PlainObjectBase<DerivedP> &PD1_combed,
                                       Eigen::PlainObjectBase<DerivedP> &PD2_combed)
 {
-  Eigen::PlainObjectBase<DerivedV> B1, B2, B3;
+  DerivedV B1, B2, B3;
   igl::local_basis(V,F,B1,B2,B3);
 
   PD1_combed.resize(BIS1_combed.rows(),3);

+ 3 - 1
include/igl/comb_line_field.cpp

@@ -25,10 +25,12 @@ public:
     const Eigen::PlainObjectBase<DerivedV> &V;
     const Eigen::PlainObjectBase<DerivedF> &F;
     const Eigen::PlainObjectBase<DerivedV> &PD1;
+#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
     Eigen::PlainObjectBase<DerivedV> N;
 
 private:
     // internal
+#warning "Constructing Eigen::PlainObjectBase directly is deprecated"
     Eigen::PlainObjectBase<DerivedF> TT;
     Eigen::PlainObjectBase<DerivedF> TTi;
 
@@ -65,7 +67,7 @@ public:
         PD1(_PD1)
     {
         igl::per_face_normals(V,F,N);
-        igl::triangle_triangle_adjacency(V,F,TT,TTi);
+        igl::triangle_triangle_adjacency(F,TT,TTi);
     }
 
     inline void comb(Eigen::PlainObjectBase<DerivedV> &PD1out)

+ 1 - 1
include/igl/comiso/frame_field.cpp

@@ -115,7 +115,7 @@ FrameInterpolator::FrameInterpolator(const Eigen::MatrixXd& _V, const Eigen::Mat
 
 
   // Generate topological relations
-  igl::triangle_triangle_adjacency(V,F,TT,TTi);
+  igl::triangle_triangle_adjacency(F,TT,TTi);
   igl::edge_topology(V,F, EV, FE, EF);
 
   // Flag border edges

+ 1 - 1
include/igl/comiso/miq.cpp

@@ -1191,7 +1191,7 @@ F(F_)
   igl::cut_mesh(V, F, Handle_Seams, Vcut, Fcut);
 
   igl::local_basis(V,F,B1,B2,B3);
-  igl::triangle_triangle_adjacency(V,F,TT,TTi);
+  igl::triangle_triangle_adjacency(F,TT,TTi);
 
   // Prepare indexing for the linear system
   VertexIndexing<DerivedV, DerivedF> VInd(V, F, Vcut, Fcut, TT, TTi, Handle_MMatch, Handle_Singular, Handle_Seams);

+ 1 - 1
include/igl/comiso/nrosy.cpp

@@ -165,7 +165,7 @@ igl::comiso::NRosyField::NRosyField(const Eigen::MatrixXd& _V, const Eigen::Matr
 
 
   // Generate topological relations
-  igl::triangle_triangle_adjacency(V,F,TT,TTi);
+  igl::triangle_triangle_adjacency(F,TT,TTi);
   igl::edge_topology(V,F, EV, FE, EF);
 
   // Flag border edges

+ 1 - 1
include/igl/compute_frame_field_bisectors.cpp

@@ -70,7 +70,7 @@ IGL_INLINE void igl::compute_frame_field_bisectors(
                                                    Eigen::PlainObjectBase<DerivedV>& BIS1,
                                                    Eigen::PlainObjectBase<DerivedV>& BIS2)
 {
-  Eigen::PlainObjectBase<DerivedV> B1, B2, B3;
+  DerivedV B1, B2, B3;
   igl::local_basis(V,F,B1,B2,B3);
 
   compute_frame_field_bisectors( V, F, B1, B2, PD1, PD2, BIS1, BIS2);

+ 14 - 0
include/igl/copyleft/README.md

@@ -0,0 +1,14 @@
+## IGL copyleft subdirectory
+
+Functions in the `include/igl/copyleft/` subdirectory are in the
+`igl::copyleft::` namespace to indicate that they are under a more aggressive
+[copyleft](https://en.wikipedia.org/wiki/Copyleft) than
+[MPL2](https://en.wikipedia.org/wiki/Mozilla_Public_License) used for the main
+`include/igl` directory and `igl::` namespace. Most notably, this subdirectory
+includes code that is under
+[GPL](https://en.wikipedia.org/wiki/GNU_General_Public_License).
+
+Typically a company planning on developing software without releasing its
+source code will avoid or purchase licenses for such dependencies. If you do
+obtain such a license for the dependencies employed here, you are free to use
+the libigl functions here as per their MPL2 license.

+ 131 - 0
include/igl/copyleft/boolean/BinaryWindingNumberOperations.h

@@ -0,0 +1,131 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Qingnan Zhou <qnzhou@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+//
+#ifndef IGL_COPYLEFT_BOOLEAN_BINARY_WINDING_NUMBER_OPERATIONS_H
+#define IGL_COPYLEFT_BOOLEAN_BINARY_WINDING_NUMBER_OPERATIONS_H
+
+#include <stdexcept>
+#include "../../igl_inline.h"
+#include "MeshBooleanType.h"
+#include <Eigen/Core>
+
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace boolean
+    {
+      template <igl::copyleft::boolean::MeshBooleanType Op>
+      class BinaryWindingNumberOperations {
+        public:
+          template<typename DerivedW>
+            typename DerivedW::Scalar operator()(
+                const Eigen::PlainObjectBase<DerivedW>& /*win_nums*/) const {
+              throw (std::runtime_error("not implemented!"));
+            }
+      };
+
+      template <>
+      class BinaryWindingNumberOperations<MESH_BOOLEAN_TYPE_UNION> {
+        public:
+          template<typename DerivedW>
+          typename DerivedW::Scalar operator()(
+              const Eigen::PlainObjectBase<DerivedW>& win_nums) const {
+            return win_nums(0) > 0 || win_nums(1) > 0;
+          }
+      };
+
+      template <>
+      class BinaryWindingNumberOperations<MESH_BOOLEAN_TYPE_INTERSECT> {
+        public:
+          template<typename DerivedW>
+          typename DerivedW::Scalar operator()(
+              const Eigen::PlainObjectBase<DerivedW>& win_nums) const {
+            return win_nums(0) > 0 && win_nums(1) > 0;
+          }
+      };
+
+      template <>
+      class BinaryWindingNumberOperations<MESH_BOOLEAN_TYPE_MINUS> {
+        public:
+          template<typename DerivedW>
+          typename DerivedW::Scalar operator()(
+              const Eigen::PlainObjectBase<DerivedW>& win_nums) const {
+            return win_nums(0) > 0 && win_nums(1) <= 0;
+          }
+      };
+
+      template <>
+      class BinaryWindingNumberOperations<MESH_BOOLEAN_TYPE_XOR> {
+        public:
+          template<typename DerivedW>
+          typename DerivedW::Scalar operator()(
+              const Eigen::PlainObjectBase<DerivedW>& win_nums) const {
+            return (win_nums(0) > 0 && win_nums(1) <= 0) ||
+              (win_nums(0) <= 0 && win_nums(1) > 0);
+          }
+      };
+
+      template <>
+      class BinaryWindingNumberOperations<igl::copyleft::boolean::MESH_BOOLEAN_TYPE_RESOLVE> {
+        public:
+          template<typename DerivedW>
+            typename DerivedW::Scalar operator()(
+                const Eigen::PlainObjectBase<DerivedW>& /*win_nums*/) const {
+              return true;
+            }
+      };
+
+      typedef BinaryWindingNumberOperations<MESH_BOOLEAN_TYPE_UNION> BinaryUnion;
+      typedef BinaryWindingNumberOperations<MESH_BOOLEAN_TYPE_INTERSECT> BinaryIntersect;
+      typedef BinaryWindingNumberOperations<MESH_BOOLEAN_TYPE_MINUS> BinaryMinus;
+      typedef BinaryWindingNumberOperations<MESH_BOOLEAN_TYPE_XOR> BinaryXor;
+      typedef BinaryWindingNumberOperations<MESH_BOOLEAN_TYPE_RESOLVE> BinaryResolve;
+
+      enum KeeperType {
+        KEEP_INSIDE,
+        KEEP_ALL
+      };
+
+      template<KeeperType T>
+      class WindingNumberFilter {
+        public:
+          template<typename DerivedW>
+            short operator()(
+                const Eigen::PlainObjectBase<DerivedW>& /*win_nums*/) const {
+              throw std::runtime_error("Not implemented");
+            }
+      };
+
+      template<>
+      class WindingNumberFilter<KEEP_INSIDE> {
+        public:
+          template<typename T>
+          short operator()(T out_w, T in_w) const {
+            if (in_w > 0 && out_w <= 0) return 1;
+            else if (in_w <= 0 && out_w > 0) return -1;
+            else return 0;
+          }
+      };
+
+      template<>
+      class WindingNumberFilter<KEEP_ALL> {
+        public:
+          template<typename T>
+            short operator()(T /*out_w*/, T /*in_w*/) const {
+              return 1;
+            }
+      };
+
+      typedef WindingNumberFilter<KEEP_INSIDE> KeepInside;
+      typedef WindingNumberFilter<KEEP_ALL> KeepAll;
+    }
+  }
+}
+
+#endif

+ 189 - 0
include/igl/copyleft/boolean/CSGTree.h

@@ -0,0 +1,189 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_COPYLEFT_BOOLEAN_CSG_TREE_H
+#define IGL_COPYLEFT_BOOLEAN_CSG_TREE_H
+
+#include "string_to_mesh_boolean_type.h"
+#include "MeshBooleanType.h"
+#include "mesh_boolean.h"
+#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+#include <CGAL/number_utils.h>
+
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace boolean
+    {
+      // Class for defining and computing a constructive solid geometry result
+      // out of a tree of boolean operations on "solid" triangle meshes.
+      //
+      //template <typename DerivedF>
+      class CSGTree
+      {
+        public:
+          typedef CGAL::Epeck::FT ExactScalar;
+          //typedef Eigen::PlainObjectBase<DerivedF> POBF;
+          typedef Eigen::MatrixXi POBF;
+          typedef POBF::Index FIndex;
+          typedef Eigen::Matrix<ExactScalar,Eigen::Dynamic,3> MatrixX3E;
+          typedef Eigen::Matrix<FIndex,Eigen::Dynamic,1> VectorJ;
+        private:
+          // Resulting mesh
+          MatrixX3E m_V;
+          POBF m_F;
+          VectorJ m_J;
+          // Number of birth faces in A + those in B. I.e. sum of original "leaf"
+          // faces involved in result.
+          size_t m_number_of_birth_faces;
+        public:
+          CSGTree()
+          {
+          }
+          //typedef Eigen::MatrixXd MatrixX3E;
+          //typedef Eigen::MatrixXi POBF;
+          // http://stackoverflow.com/a/3279550/148668
+          CSGTree(const CSGTree & other)
+            :
+            // copy things
+            m_V(other.m_V),
+            // This is an issue if m_F is templated
+            // https://forum.kde.org/viewtopic.php?f=74&t=128414
+            m_F(other.m_F),
+            m_J(other.m_J),
+            m_number_of_birth_faces(other.m_number_of_birth_faces)
+          {
+          }
+          // copy-swap idiom
+          friend void swap(CSGTree& first, CSGTree& second)
+          {
+            using std::swap;
+            // swap things
+            swap(first.m_V,second.m_V);
+            // This is an issue if m_F is templated, similar to
+            // https://forum.kde.org/viewtopic.php?f=74&t=128414
+            swap(first.m_F,second.m_F);
+            swap(first.m_J,second.m_J);
+            swap(first.m_number_of_birth_faces,second.m_number_of_birth_faces);
+          }
+          // Pass-by-value (aka copy)
+          CSGTree& operator=(CSGTree other)
+          {
+            swap(*this,other);
+            return *this;
+          }
+          CSGTree(CSGTree&& other):
+            // initialize via default constructor
+            CSGTree() 
+          {
+            swap(*this,other);
+          }
+          // Construct and compute a boolean operation on existing CSGTree nodes.
+          //
+          // Inputs:
+          //   A  Solid result of previous CSG operation (or identity, see below)
+          //   B  Solid result of previous CSG operation (or identity, see below)
+          //   type  type of mesh boolean to compute 
+          CSGTree(
+            const CSGTree & A,
+            const CSGTree & B,
+            const MeshBooleanType & type)
+          {
+            // conduct boolean operation
+            mesh_boolean(A.V(),A.F(),B.V(),B.F(),type,m_V,m_F,m_J);
+            // reindex m_J
+            std::for_each(m_J.data(),m_J.data()+m_J.size(),
+              [&](typename VectorJ::Scalar & j) -> void
+              {
+                if(j < A.F().rows())
+                {
+                  j = A.J()(j);
+                }else
+                {
+                  assert(j<(A.F().rows()+B.F().rows()));
+                  j = A.number_of_birth_faces()+(B.J()(j-A.F().rows()));
+                }
+              });
+            m_number_of_birth_faces = 
+              A.number_of_birth_faces() + B.number_of_birth_faces();
+          }
+          // Overload using string for type
+          CSGTree(
+            const CSGTree & A,
+            const CSGTree & B,
+            const std::string & s):
+            CSGTree(A,B,string_to_mesh_boolean_type(s))
+          {
+            // do nothing (all done in constructor).
+          }
+          // "Leaf" node with identity operation on assumed "solid" mesh (V,F)
+          //
+          // Inputs:
+          //   V  #V by 3 list of mesh vertices (in any precision, will be
+          //     converted to exact)
+          //   F  #F by 3 list of mesh face indices into V
+          template <typename DerivedV>
+          CSGTree(const Eigen::PlainObjectBase<DerivedV> & V, const POBF & F)//:
+          // Possible Eigen bug:
+          // https://forum.kde.org/viewtopic.php?f=74&t=128414
+            //m_V(V.template cast<ExactScalar>()),m_F(F)
+          {
+            m_V = V.template cast<ExactScalar>();
+            m_F = F;
+            // number of faces
+            m_number_of_birth_faces = m_F.rows();
+            // identity birth index
+            m_J = VectorJ::LinSpaced(
+              m_number_of_birth_faces,0,m_number_of_birth_faces-1);
+          }
+          // Returns reference to resulting mesh vertices m_V in exact scalar
+          // representation
+          const MatrixX3E & V() const
+          {
+            return m_V;
+          }
+          // Returns mesh vertices in the desired output type, casting when
+          // appropriate to floating precision.
+          template <typename DerivedV>
+          Eigen::PlainObjectBase<DerivedV> cast_V() const
+          {
+            Eigen::PlainObjectBase<DerivedV> dV;
+            dV.resize(m_V.rows(),m_V.cols());
+            for(int i = 0;i<m_V.rows();i++)
+            {
+              for(int j = 0;j<m_V.cols();j++)
+              {
+                dV(i,j) = CGAL::to_double(m_V(i,j));
+              }
+            }
+            return dV;
+          }
+          // Returns reference to resulting mesh faces m_F
+          const POBF & F() const
+          {
+            return m_F;
+          }
+          // Returns reference to "birth parents" indices into [F1;F2;...;Fn]
+          // where F1, ... , Fn are the face lists of the leaf ("original") input
+          // meshes.
+          const VectorJ & J() const
+          {
+            return m_J;
+          }
+          // The number of leaf faces = #F1 + #F2 + ... + #Fn
+          const size_t & number_of_birth_faces() const
+          {
+            return m_number_of_birth_faces;
+          }
+      };
+    }
+  }
+}
+
+
+#endif

+ 29 - 0
include/igl/copyleft/boolean/MeshBooleanType.h

@@ -0,0 +1,29 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_COPYLEFT_BOOLEAN_MESH_BOOLEAN_TYPE_H
+#define IGL_COPYLEFT_BOOLEAN_MESH_BOOLEAN_TYPE_H
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace boolean
+    {
+      enum MeshBooleanType
+      {
+        MESH_BOOLEAN_TYPE_UNION = 0,
+        MESH_BOOLEAN_TYPE_INTERSECT = 1,
+        MESH_BOOLEAN_TYPE_MINUS = 2,
+        MESH_BOOLEAN_TYPE_XOR = 3,
+        MESH_BOOLEAN_TYPE_RESOLVE = 4,
+        NUM_MESH_BOOLEAN_TYPES = 5
+      };
+    }
+  }
+};
+
+#endif

+ 3 - 3
include/igl/boolean/from_cork_mesh.cpp → include/igl/copyleft/boolean/from_cork_mesh.cpp

@@ -11,7 +11,7 @@
 template <
   typename DerivedV,
   typename DerivedF>
-IGL_INLINE void igl::boolean::from_cork_mesh(
+IGL_INLINE void igl::copyleft::boolean::from_cork_mesh(
   const CorkTriMesh & mesh,
   Eigen::PlainObjectBase<DerivedV > & V,
   Eigen::PlainObjectBase<DerivedF > & F)
@@ -37,8 +37,8 @@ IGL_INLINE void igl::boolean::from_cork_mesh(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
-template void igl::boolean::from_cork_mesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(CorkTriMesh const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
-template void igl::boolean::from_cork_mesh<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(CorkTriMesh const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
+template void igl::copyleft::boolean::from_cork_mesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(CorkTriMesh const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template void igl::copyleft::boolean::from_cork_mesh<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(CorkTriMesh const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
 #endif
 
 #endif

+ 41 - 0
include/igl/copyleft/boolean/from_cork_mesh.h

@@ -0,0 +1,41 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_COPYLEFT_BOOLEAN_FROM_CORK_MESH_H
+#define IGL_COPYLEFT_BOOLEAN_FROM_CORK_MESH_H
+#ifndef IGL_NO_CORK
+#include "../../igl_inline.h"
+#include <cork.h>
+#include <Eigen/Core>
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace boolean
+    {
+      // Convert cork's triangle mesh representation to a (V,F) mesh.
+      //
+      // Inputs:
+      //   mesh  cork representation of mesh
+      // Outputs:
+      //   V  #V by 3 list of vertex positions
+      //   F  #F by 3 list of triangle indices into V
+      template <
+        typename DerivedV,
+        typename DerivedF>
+      IGL_INLINE void from_cork_mesh(
+        const CorkTriMesh & mesh,
+        Eigen::PlainObjectBase<DerivedV > & V,
+        Eigen::PlainObjectBase<DerivedF > & F);
+    }
+  }
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "from_cork_mesh.cpp"
+#endif
+#endif
+#endif

+ 349 - 0
include/igl/copyleft/boolean/mesh_boolean.cpp

@@ -0,0 +1,349 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
+//                    Qingnan Zhou <qnzhou@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+//
+#include "mesh_boolean.h"
+#include "BinaryWindingNumberOperations.h"
+#include "../cgal/assign_scalar.h"
+#include "../cgal/propagate_winding_numbers.h"
+#include "../cgal/remesh_self_intersections.h"
+#include "../../remove_unreferenced.h"
+#include "../../unique_simplices.h"
+#include "../../slice.h"
+#include "../../resolve_duplicated_faces.h"
+
+#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+#include <algorithm>
+
+//#define MESH_BOOLEAN_TIMING
+
+template <
+  typename DerivedVA,
+  typename DerivedFA,
+  typename DerivedVB,
+  typename DerivedFB,
+  typename WindingNumberOp,
+  typename KeepFunc,
+  typename ResolveFunc,
+  typename DerivedVC,
+  typename DerivedFC,
+  typename DerivedJ>
+IGL_INLINE void igl::copyleft::boolean::mesh_boolean(
+    const Eigen::PlainObjectBase<DerivedVA> & VA,
+    const Eigen::PlainObjectBase<DerivedFA> & FA,
+    const Eigen::PlainObjectBase<DerivedVB> & VB,
+    const Eigen::PlainObjectBase<DerivedFB> & FB,
+    const WindingNumberOp& wind_num_op,
+    const KeepFunc& keep,
+    const ResolveFunc& resolve_fun,
+    Eigen::PlainObjectBase<DerivedVC > & VC,
+    Eigen::PlainObjectBase<DerivedFC > & FC,
+    Eigen::PlainObjectBase<DerivedJ > & J) {
+
+#ifdef MESH_BOOLEAN_TIMING
+  const auto & tictoc = []() -> double
+  {
+    static double t_start = igl::get_seconds();
+    double diff = igl::get_seconds()-t_start;
+    t_start += diff;
+    return diff;
+  };
+  const auto log_time = [&](const std::string& label) -> void {
+    std::cout << "mesh_boolean." << label << ": "
+      << tictoc() << std::endl;
+  };
+  tictoc();
+#endif
+
+  typedef typename DerivedVC::Scalar Scalar;
+  //typedef typename DerivedFC::Scalar Index;
+  typedef CGAL::Epeck Kernel;
+  typedef Kernel::FT ExactScalar;
+  typedef Eigen::Matrix<Scalar,Eigen::Dynamic,3> MatrixX3S;
+  //typedef Eigen::Matrix<Index,Eigen::Dynamic,Eigen::Dynamic> MatrixXI;
+  typedef Eigen::Matrix<typename DerivedJ::Scalar,Eigen::Dynamic,1> VectorXJ;
+
+  // Generate combined mesh.
+  typedef Eigen::Matrix<
+    ExactScalar,
+    Eigen::Dynamic,
+    Eigen::Dynamic,
+    DerivedVC::IsRowMajor> MatrixXES;
+  MatrixXES V;
+  DerivedFC F;
+  VectorXJ  CJ;
+  {
+      DerivedVA VV(VA.rows() + VB.rows(), 3);
+      DerivedFC FF(FA.rows() + FB.rows(), 3);
+      VV << VA, VB;
+      FF << FA, FB.array() + VA.rows();
+      //// Handle annoying empty cases
+      //if(VA.size()>0)
+      //{
+      //  VV<<VA;
+      //}
+      //if(VB.size()>0)
+      //{
+      //  VV<<VB;
+      //}
+      //if(FA.size()>0)
+      //{
+      //  FF<<FA;
+      //}
+      //if(FB.size()>0)
+      //{
+      //  FF<<FB.array()+VA.rows();
+      //}
+      resolve_fun(VV, FF, V, F, CJ);
+  }
+#ifdef MESH_BOOLEAN_TIMING
+  log_time("resolve_self_intersection");
+#endif
+
+  // Compute winding numbers on each side of each facet.
+  const size_t num_faces = F.rows();
+  Eigen::MatrixXi W;
+  Eigen::VectorXi labels(num_faces);
+  std::transform(CJ.data(), CJ.data()+CJ.size(), labels.data(),
+      [&](int i) { return i<FA.rows() ? 0:1; });
+  if (num_faces > 0) {
+    igl::copyleft::cgal::propagate_winding_numbers(V, F, labels, W);
+  } else {
+    W.resize(0, 4);
+  }
+  assert((size_t)W.rows() == num_faces);
+  if (W.cols() == 2) {
+    assert(FB.rows() == 0);
+    Eigen::MatrixXi W_tmp(num_faces, 4);
+    W_tmp << W, Eigen::MatrixXi::Zero(num_faces, 2);
+    W = W_tmp;
+  } else {
+    assert(W.cols() == 4);
+  }
+#ifdef MESH_BOOLEAN_TIMING
+  log_time("propagate_input_winding_number");
+#endif
+
+  // Compute resulting winding number.
+  Eigen::MatrixXi Wr(num_faces, 2);
+  for (size_t i=0; i<num_faces; i++) {
+    Eigen::MatrixXi w_out(1,2), w_in(1,2);
+    w_out << W(i,0), W(i,2);
+    w_in  << W(i,1), W(i,3);
+    Wr(i,0) = wind_num_op(w_out);
+    Wr(i,1) = wind_num_op(w_in);
+  }
+#ifdef MESH_BOOLEAN_TIMING
+  log_time("compute_output_winding_number");
+#endif
+
+  // Extract boundary separating inside from outside.
+  auto index_to_signed_index = [&](size_t i, bool ori) -> int{
+    return (i+1)*(ori?1:-1);
+  };
+  //auto signed_index_to_index = [&](int i) -> size_t {
+  //    return abs(i) - 1;
+  //};
+  std::vector<int> selected;
+  for(size_t i=0; i<num_faces; i++) {
+    auto should_keep = keep(Wr(i,0), Wr(i,1));
+    if (should_keep > 0) {
+      selected.push_back(index_to_signed_index(i, true));
+    } else if (should_keep < 0) {
+      selected.push_back(index_to_signed_index(i, false));
+    }
+  }
+
+  const size_t num_selected = selected.size();
+  DerivedFC kept_faces(num_selected, 3);
+  DerivedJ  kept_face_indices(num_selected, 1);
+  for (size_t i=0; i<num_selected; i++) {
+    size_t idx = abs(selected[i]) - 1;
+    if (selected[i] > 0) {
+      kept_faces.row(i) = F.row(idx);
+    } else {
+      kept_faces.row(i) = F.row(idx).reverse();
+    }
+    kept_face_indices(i, 0) = CJ[idx];
+  }
+#ifdef MESH_BOOLEAN_TIMING
+  log_time("extract_output");
+#endif
+
+  // Finally, remove duplicated faces and unreferenced vertices.
+  {
+    DerivedFC G;
+    DerivedJ JJ;
+    igl::resolve_duplicated_faces(kept_faces, G, JJ);
+    igl::slice(kept_face_indices, JJ, 1, J);
+
+    MatrixX3S Vs(V.rows(), V.cols());
+    for (size_t i=0; i<(size_t)V.rows(); i++)
+    {
+      for (size_t j=0; j<(size_t)V.cols(); j++)
+      {
+        igl::copyleft::cgal::assign_scalar(V(i,j), Vs(i,j));
+      }
+    }
+    Eigen::VectorXi newIM;
+    igl::remove_unreferenced(Vs,G,VC,FC,newIM);
+  }
+#ifdef MESH_BOOLEAN_TIMING
+  log_time("clean_up");
+#endif
+}
+
+template <
+  typename DerivedVA,
+  typename DerivedFA,
+  typename DerivedVB,
+  typename DerivedFB,
+  typename ResolveFunc,
+  typename DerivedVC,
+  typename DerivedFC,
+  typename DerivedJ>
+IGL_INLINE void igl::copyleft::boolean::mesh_boolean(
+    const Eigen::PlainObjectBase<DerivedVA > & VA,
+    const Eigen::PlainObjectBase<DerivedFA > & FA,
+    const Eigen::PlainObjectBase<DerivedVB > & VB,
+    const Eigen::PlainObjectBase<DerivedFB > & FB,
+    const MeshBooleanType & type,
+    const ResolveFunc& resolve_func,
+    Eigen::PlainObjectBase<DerivedVC > & VC,
+    Eigen::PlainObjectBase<DerivedFC > & FC,
+    Eigen::PlainObjectBase<DerivedJ > & J)
+{
+  //typedef CGAL::Epeck Kernel;
+  //typedef Kernel::FT ExactScalar;
+  //typedef Eigen::Matrix<
+  //  ExactScalar,
+  //  Eigen::Dynamic,
+  //  Eigen::Dynamic,
+  //  DerivedVC::IsRowMajor> MatrixXES;
+
+  switch (type) {
+    case MESH_BOOLEAN_TYPE_UNION:
+      igl::copyleft::boolean::mesh_boolean(
+          VA, FA, VB, FB, igl::copyleft::boolean::BinaryUnion(),
+          igl::copyleft::boolean::KeepInside(), resolve_func, VC, FC, J);
+      break;
+    case MESH_BOOLEAN_TYPE_INTERSECT:
+      igl::copyleft::boolean::mesh_boolean(
+          VA, FA, VB, FB, igl::copyleft::boolean::BinaryIntersect(),
+          igl::copyleft::boolean::KeepInside(), resolve_func, VC, FC, J);
+      break;
+    case MESH_BOOLEAN_TYPE_MINUS:
+      igl::copyleft::boolean::mesh_boolean(
+          VA, FA, VB, FB, igl::copyleft::boolean::BinaryMinus(),
+          igl::copyleft::boolean::KeepInside(), resolve_func, VC, FC, J);
+      break;
+    case MESH_BOOLEAN_TYPE_XOR:
+      igl::copyleft::boolean::mesh_boolean(
+          VA, FA, VB, FB, igl::copyleft::boolean::BinaryXor(),
+          igl::copyleft::boolean::KeepInside(), resolve_func, VC, FC, J);
+      break;
+    case MESH_BOOLEAN_TYPE_RESOLVE:
+      //op = binary_resolve();
+      igl::copyleft::boolean::mesh_boolean(
+          VA, FA, VB, FB, igl::copyleft::boolean::BinaryResolve(),
+          igl::copyleft::boolean::KeepAll(), resolve_func, VC, FC, J);
+      break;
+    default:
+      throw std::runtime_error("Unsupported boolean type.");
+  }
+}
+
+template <
+  typename DerivedVA,
+  typename DerivedFA,
+  typename DerivedVB,
+  typename DerivedFB,
+  typename DerivedVC,
+  typename DerivedFC,
+  typename DerivedJ>
+IGL_INLINE void igl::copyleft::boolean::mesh_boolean(
+  const Eigen::PlainObjectBase<DerivedVA > & VA,
+  const Eigen::PlainObjectBase<DerivedFA > & FA,
+  const Eigen::PlainObjectBase<DerivedVB > & VB,
+  const Eigen::PlainObjectBase<DerivedFB > & FB,
+  const MeshBooleanType & type,
+  Eigen::PlainObjectBase<DerivedVC > & VC,
+  Eigen::PlainObjectBase<DerivedFC > & FC,
+  Eigen::PlainObjectBase<DerivedJ > & J)
+{
+  typedef CGAL::Epeck Kernel;
+  typedef Kernel::FT ExactScalar;
+  typedef Eigen::Matrix<
+    ExactScalar,
+    Eigen::Dynamic,
+    Eigen::Dynamic,
+    DerivedVC::IsRowMajor> MatrixXES;
+
+  std::function<void(
+      const Eigen::PlainObjectBase<DerivedVA>&,
+      const Eigen::PlainObjectBase<DerivedFA>&,
+      Eigen::PlainObjectBase<MatrixXES>&,
+      Eigen::PlainObjectBase<DerivedFC>&,
+      Eigen::PlainObjectBase<DerivedJ>&)> resolve_func =
+    [](const Eigen::PlainObjectBase<DerivedVA>& V,
+        const Eigen::PlainObjectBase<DerivedFA>& F,
+        Eigen::PlainObjectBase<MatrixXES>& Vo,
+        Eigen::PlainObjectBase<DerivedFC>& Fo,
+        Eigen::PlainObjectBase<DerivedJ>& J) {
+      Eigen::VectorXi I;
+      igl::copyleft::cgal::RemeshSelfIntersectionsParam params;
+
+      MatrixXES Vr;
+      DerivedFC Fr;
+      Eigen::MatrixXi IF;
+      igl::copyleft::cgal::remesh_self_intersections(
+          V, F, params, Vr, Fr, IF, J, I);
+      assert(I.size() == Vr.rows());
+
+      // Merge coinciding vertices into non-manifold vertices.
+      std::for_each(Fr.data(), Fr.data()+Fr.size(),
+          [&I](typename DerivedFC::Scalar& a) { a=I[a]; });
+
+      // Remove unreferenced vertices.
+      Eigen::VectorXi UIM;
+      igl::remove_unreferenced(Vr, Fr, Vo, Fo, UIM);
+    };
+
+  return mesh_boolean(VA,FA,VB,FB,type,resolve_func,VC,FC,J);
+}
+
+template <
+typename DerivedVA,
+typename DerivedFA,
+typename DerivedVB,
+typename DerivedFB,
+typename DerivedVC,
+typename DerivedFC>
+IGL_INLINE void igl::copyleft::boolean::mesh_boolean(
+    const Eigen::PlainObjectBase<DerivedVA > & VA,
+    const Eigen::PlainObjectBase<DerivedFA > & FA,
+    const Eigen::PlainObjectBase<DerivedVB > & VB,
+    const Eigen::PlainObjectBase<DerivedFB > & FB,
+    const MeshBooleanType & type,
+    Eigen::PlainObjectBase<DerivedVC > & VC,
+    Eigen::PlainObjectBase<DerivedFC > & FC) {
+  Eigen::Matrix<typename DerivedFC::Index, Eigen::Dynamic,1> J;
+  return igl::copyleft::boolean::mesh_boolean(VA,FA,VB,FB,type,VC,FC,J);
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template specialization
+template void igl::copyleft::boolean::mesh_boolean<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, igl::copyleft::boolean::MeshBooleanType const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template void igl::copyleft::boolean::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<long, -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&, igl::copyleft::boolean::MeshBooleanType 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<long, -1, 1, 0, -1, 1> >&);
+template void igl::copyleft::boolean::mesh_boolean<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, igl::copyleft::boolean::MeshBooleanType const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+#undef IGL_STATIC_LIBRARY
+#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> >&);
+#include "../../slice.cpp"
+template void igl::slice<Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > >(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&, int, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&);
+#endif

+ 166 - 0
include/igl/copyleft/boolean/mesh_boolean.h

@@ -0,0 +1,166 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
+//                    Qingnan Zhou <qnzhou@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+//
+#ifndef IGL_COPYLEFT_BOOLEAN_MESH_BOOLEAN_H
+#define IGL_COPYLEFT_BOOLEAN_MESH_BOOLEAN_H
+
+#include "../../igl_inline.h"
+#include "MeshBooleanType.h"
+#include <Eigen/Core>
+#include <functional>
+
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace boolean
+    {
+      //  MESH_BOOLEAN Compute boolean csg operations on "solid", consistently
+      //  oriented meshes.
+      //
+      //  Inputs:
+      //    VA  #VA by 3 list of vertex positions of first mesh
+      //    FA  #FA by 3 list of triangle indices into VA
+      //    VB  #VB by 3 list of vertex positions of second mesh
+      //    FB  #FB by 3 list of triangle indices into VB
+      //    wind_num_op  function handle for filtering winding numbers from
+      //      tuples of integer values to [0,1] outside/inside values
+      //    keep  function handle for determining if a patch should be "kept"
+      //      in the output based on the winding number on either side
+      //    resolve_fun  function handle for computing resolve of a
+      //      self-intersections of a mesh and outputting the new mesh.
+      //  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 [FA;FB] revealing "birth" facet
+      //
+      //  See also: mesh_boolean_cork, intersect_other,
+      //  remesh_self_intersections
+      template <
+        typename DerivedVA,
+        typename DerivedFA,
+        typename DerivedVB,
+        typename DerivedFB,
+        typename WindingNumberOp,
+        typename KeepFunc,
+        typename ResolveFunc,
+        typename DerivedVC,
+        typename DerivedFC,
+        typename DerivedJ>
+      IGL_INLINE void mesh_boolean(
+          const Eigen::PlainObjectBase<DerivedVA> & VA,
+          const Eigen::PlainObjectBase<DerivedFA> & FA,
+          const Eigen::PlainObjectBase<DerivedVB> & VB,
+          const Eigen::PlainObjectBase<DerivedFB> & FB,
+          const WindingNumberOp& wind_num_op,
+          const KeepFunc& keep,
+          const ResolveFunc& resolve_fun,
+          Eigen::PlainObjectBase<DerivedVC > & VC,
+          Eigen::PlainObjectBase<DerivedFC > & FC,
+          Eigen::PlainObjectBase<DerivedJ > & J);
+
+      //  Inputs:
+      //    VA  #VA by 3 list of vertex positions of first mesh
+      //    FA  #FA by 3 list of triangle indices into VA
+      //    VB  #VB by 3 list of vertex positions of second mesh
+      //    FB  #FB by 3 list of triangle indices into VB
+      //    type  type of boolean operation
+      //    resolve_fun  function handle for computing resolve of a
+      //      self-intersections of a mesh and outputting the new mesh.
+      //  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 [FA;FB] revealing "birth" facet
+      //
+      //  See also: mesh_boolean_cork, intersect_other,
+      //  remesh_self_intersections
+      template <
+        typename DerivedVA,
+        typename DerivedFA,
+        typename DerivedVB,
+        typename DerivedFB,
+        typename ResolveFunc,
+        typename DerivedVC,
+        typename DerivedFC,
+        typename DerivedJ>
+      IGL_INLINE void mesh_boolean(
+          const Eigen::PlainObjectBase<DerivedVA > & VA,
+          const Eigen::PlainObjectBase<DerivedFA > & FA,
+          const Eigen::PlainObjectBase<DerivedVB > & VB,
+          const Eigen::PlainObjectBase<DerivedFB > & FB,
+          const MeshBooleanType & type,
+        const ResolveFunc& resolve_func,
+          Eigen::PlainObjectBase<DerivedVC > & VC,
+          Eigen::PlainObjectBase<DerivedFC > & FC,
+          Eigen::PlainObjectBase<DerivedJ > & J);
+
+      //  Inputs:
+      //    VA  #VA by 3 list of vertex positions of first mesh
+      //    FA  #FA by 3 list of triangle indices into VA
+      //    VB  #VB by 3 list of vertex positions of second mesh
+      //    FB  #FB by 3 list of triangle indices into VB
+      //    type  type of boolean operation
+      //  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 [FA;FB] revealing "birth" facet
+      //
+      //  See also: mesh_boolean_cork, intersect_other,
+      //  remesh_self_intersections
+      template <
+        typename DerivedVA,
+        typename DerivedFA,
+        typename DerivedVB,
+        typename DerivedFB,
+        typename DerivedVC,
+        typename DerivedFC,
+        typename DerivedJ>
+      IGL_INLINE void mesh_boolean(
+        const Eigen::PlainObjectBase<DerivedVA > & VA,
+        const Eigen::PlainObjectBase<DerivedFA > & FA,
+        const Eigen::PlainObjectBase<DerivedVB > & VB,
+        const Eigen::PlainObjectBase<DerivedFB > & FB,
+        const MeshBooleanType & type,
+        Eigen::PlainObjectBase<DerivedVC > & VC,
+        Eigen::PlainObjectBase<DerivedFC > & FC,
+        Eigen::PlainObjectBase<DerivedJ > & J);
+
+      //  Inputs:
+      //    VA  #VA by 3 list of vertex positions of first mesh
+      //    FA  #FA by 3 list of triangle indices into VA
+      //    VB  #VB by 3 list of vertex positions of second mesh
+      //    FB  #FB by 3 list of triangle indices into VB
+      //    type  type of boolean operation
+      //  Outputs:
+      //    VC  #VC by 3 list of vertex positions of boolean result mesh
+      //    FC  #FC by 3 list of triangle indices into VC
+      template <
+        typename DerivedVA,
+        typename DerivedFA,
+        typename DerivedVB,
+        typename DerivedFB,
+        typename DerivedVC,
+        typename DerivedFC>
+      IGL_INLINE void mesh_boolean(
+          const Eigen::PlainObjectBase<DerivedVA > & VA,
+          const Eigen::PlainObjectBase<DerivedFA > & FA,
+          const Eigen::PlainObjectBase<DerivedVB > & VB,
+          const Eigen::PlainObjectBase<DerivedFB > & FB,
+          const MeshBooleanType & type,
+          Eigen::PlainObjectBase<DerivedVC > & VC,
+          Eigen::PlainObjectBase<DerivedFC > & FC);
+    }
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "mesh_boolean.cpp"
+#endif
+
+#endif

+ 3 - 3
include/igl/boolean/mesh_boolean_cork.cpp → include/igl/copyleft/boolean/mesh_boolean_cork.cpp

@@ -17,7 +17,7 @@ template <
   typename DerivedFB,
   typename DerivedVC,
   typename DerivedFC>
-IGL_INLINE void igl::boolean::mesh_boolean_cork(
+IGL_INLINE void igl::copyleft::boolean::mesh_boolean_cork(
   const Eigen::PlainObjectBase<DerivedVA > & VA,
   const Eigen::PlainObjectBase<DerivedFA > & FA,
   const Eigen::PlainObjectBase<DerivedVB > & VB,
@@ -94,8 +94,8 @@ IGL_INLINE void igl::boolean::mesh_boolean_cork(
 }
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
-template void igl::boolean::mesh_boolean_cork<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, MeshBooleanType const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
-template void igl::boolean::mesh_boolean_cork<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::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, igl::boolean::MeshBooleanType const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
+template void igl::copyleft::boolean::mesh_boolean_cork<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, MeshBooleanType const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template void igl::copyleft::boolean::mesh_boolean_cork<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::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, igl::copyleft::boolean::MeshBooleanType const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
 #endif
 
 #endif

+ 57 - 0
include/igl/copyleft/boolean/mesh_boolean_cork.h

@@ -0,0 +1,57 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_COPYLEFT_BOOLEAN_MESH_BOOLEAN_CORK_H
+#define IGL_COPYLEFT_BOOLEAN_MESH_BOOLEAN_CORK_H
+#ifndef IGL_NO_CORK
+#include "MeshBooleanType.h"
+#include "../../igl_inline.h"
+#include <Eigen/Core>
+#include <cork.h> // for consistent uint
+
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace boolean
+    {
+      // Compute a boolean operation on two input meshes using the cork library.
+      //
+      // Inputs:
+      //   VA  #VA by 3 list of vertex positions of first mesh
+      //   FA  #FA by 3 list of triangle indices into VA
+      //   VB  #VB by 3 list of vertex positions of second mesh
+      //   FB  #FB by 3 list of triangle indices into VB
+      //   type  of boolean operation see MeshBooleanType.h
+      // Outputs:
+      //   VC  #VC by 3 list of vertex positions of output mesh
+      //   FC  #FC by 3 list of triangle indices into VC
+      template <
+        typename DerivedVA,
+        typename DerivedFA,
+        typename DerivedVB,
+        typename DerivedFB,
+        typename DerivedVC,
+        typename DerivedFC>
+      IGL_INLINE void mesh_boolean_cork(
+        const Eigen::PlainObjectBase<DerivedVA > & VA,
+        const Eigen::PlainObjectBase<DerivedFA > & FA,
+        const Eigen::PlainObjectBase<DerivedVB > & VB,
+        const Eigen::PlainObjectBase<DerivedFB > & FB,
+        const MeshBooleanType & type,
+        Eigen::PlainObjectBase<DerivedVC > & VC,
+        Eigen::PlainObjectBase<DerivedFC > & FC);
+    }
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "mesh_boolean_cork.cpp"
+#endif
+#endif
+
+#endif

+ 367 - 0
include/igl/copyleft/boolean/minkowski_sum.cpp

@@ -0,0 +1,367 @@
+// 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 "minkowski_sum.h"
+#include "mesh_boolean.h"
+
+#include "../../slice_mask.h"
+#include "../../unique.h"
+#include "../../get_seconds.h"
+#include "../../edges.h"
+#include "../cgal/assign_scalar.h"
+#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+#include <cassert>
+#include <vector>
+template <
+  typename DerivedVA,
+  typename DerivedFA,
+  typename DerivedVB,
+  typename DerivedFB,
+  typename DerivedW,
+  typename DerivedG,
+  typename DerivedJ>
+IGL_INLINE void igl::copyleft::boolean::minkowski_sum(
+  const Eigen::PlainObjectBase<DerivedVA> & VA,
+  const Eigen::PlainObjectBase<DerivedFA> & FA,
+  const Eigen::PlainObjectBase<DerivedVB> & VB,
+  const Eigen::PlainObjectBase<DerivedFB> & FB,
+  const bool resolve_overlaps,
+  Eigen::PlainObjectBase<DerivedW> & W,
+  Eigen::PlainObjectBase<DerivedG> & G,
+  Eigen::PlainObjectBase<DerivedJ> & J)
+{
+  using namespace std;
+  using namespace Eigen;
+  assert(FA.cols() == 3 && "FA must contain a closed triangle mesh");
+  assert(FB.cols() <= FA.cols() && 
+    "FB must contain lower diemnsional simplices than FA");
+  const auto tictoc = []()->double
+  {
+    static double t_start;
+    double now = igl::get_seconds();
+    double interval = now-t_start;
+    t_start = now;
+    return interval;
+  };
+  tictoc();
+  Matrix<typename DerivedFB::Scalar,Dynamic,2> EB;
+  edges(FB,EB);
+  Matrix<typename DerivedFA::Scalar,Dynamic,2> EA(0,2);
+  if(FB.cols() == 3)
+  {
+    edges(FA,EA);
+  }
+  // number of copies of A along edges of B
+  const int n_ab = EB.rows();
+  // number of copies of B along edges of A
+  const int n_ba = EA.rows();
+
+  vector<DerivedW> vW(n_ab + n_ba);
+  vector<DerivedG> vG(n_ab + n_ba);
+  vector<DerivedJ> vJ(n_ab + n_ba);
+  vector<int> offsets(n_ab + n_ba + 1);
+  offsets[0] = 0;
+  // sweep A along edges of B
+  for(int e = 0;e<n_ab;e++)
+  {
+    Matrix<typename DerivedJ::Scalar,Dynamic,1> eJ;
+    minkowski_sum(
+      VA,
+      FA,
+      VB.row(EB(e,0)).eval(),
+      VB.row(EB(e,1)).eval(),
+      false,
+      vW[e],
+      vG[e],
+      eJ);
+    assert(vG[e].rows() == eJ.rows());
+    assert(eJ.cols() == 1);
+    vJ[e].resize(vG[e].rows(),2);
+    vJ[e].col(0) = eJ;
+    vJ[e].col(1).setConstant(e);
+    offsets[e+1] = offsets[e] + vW[e].rows();
+  }
+  // sweep B along edges of A
+  for(int e = 0;e<n_ba;e++)
+  {
+    Matrix<typename DerivedJ::Scalar,Dynamic,1> eJ;
+    const int ee = n_ab+e;
+    minkowski_sum(
+      VB,
+      FB,
+      VA.row(EA(e,0)).eval(),
+      VA.row(EA(e,1)).eval(),
+      false,
+      vW[ee],
+      vG[ee],
+      eJ);
+    vJ[ee].resize(vG[ee].rows(),2);
+    vJ[ee].col(0) = eJ.array() + (FA.rows()+1);
+    vJ[ee].col(1).setConstant(ee);
+  }
+  // Combine meshes
+  int n=0,m=0;
+  for_each(vW.begin(),vW.end(),[&n](const DerivedW & w){n+=w.rows();});
+  for_each(vG.begin(),vG.end(),[&m](const DerivedG & g){m+=g.rows();});
+  assert(n == offsets.back());
+
+  W.resize(n,3);
+  G.resize(m,3);
+  J.resize(m,2);
+  {
+    int m_off = 0,n_off = 0;
+    for(int i = 0;i<vG.size();i++)
+    {
+      W.block(n_off,0,vW[i].rows(),3) = vW[i];
+      G.block(m_off,0,vG[i].rows(),3) = vG[i].array()+offsets[i];
+      J.block(m_off,0,vJ[i].rows(),2) = vJ[i];
+      n_off += vW[i].rows();
+      m_off += vG[i].rows();
+    }
+    assert(n == n_off);
+    assert(m == m_off);
+  }
+  if(resolve_overlaps)
+  {
+    Eigen::Matrix<typename DerivedJ::Scalar, Eigen::Dynamic,1> SJ;
+    mesh_boolean(
+      DerivedW(W),
+      DerivedG(G),
+      Matrix<typename DerivedW::Scalar,Dynamic,Dynamic>(),
+      Matrix<typename DerivedG::Scalar,Dynamic,Dynamic>(),
+      MESH_BOOLEAN_TYPE_UNION,
+      W,
+      G,
+      SJ);
+    J = slice(DerivedJ(J),SJ,1);
+  }
+}
+
+template <
+  typename DerivedVA,
+  typename DerivedFA,
+  typename sType, int sCols, int sOptions,
+  typename dType, int dCols, int dOptions,
+  typename DerivedW,
+  typename DerivedG,
+  typename DerivedJ>
+IGL_INLINE void igl::copyleft::boolean::minkowski_sum(
+  const Eigen::PlainObjectBase<DerivedVA> & VA,
+  const Eigen::PlainObjectBase<DerivedFA> & FA,
+  const Eigen::Matrix<sType,1,sCols,sOptions> & s,
+  const Eigen::Matrix<dType,1,dCols,dOptions> & d,
+  const bool resolve_overlaps, 
+  Eigen::PlainObjectBase<DerivedW> & W,
+  Eigen::PlainObjectBase<DerivedG> & G,
+  Eigen::PlainObjectBase<DerivedJ> & J)
+{
+  using namespace Eigen;
+  using namespace std;
+  assert(s.cols() == 3 && "s should be a 3d point");
+  assert(d.cols() == 3 && "d should be a 3d point");
+  // silly base case
+  if(FA.size() == 0)
+  {
+    W.resize(0,3);
+    G.resize(0,3);
+    return;
+  }
+  const int dim = VA.cols();
+  assert(dim == 3 && "dim must be 3D");
+  assert(s.size() == 3 && "s must be 3D point");
+  assert(d.size() == 3 && "d must be 3D point");
+  // segment vector
+  const CGAL::Vector_3<CGAL::Epeck> v(d(0)-s(0),d(1)-s(1),d(2)-s(2));
+  // number of vertices
+  const int n = VA.rows();
+  // duplicate vertices at s and d, we'll remove unreferernced later
+  W.resize(2*n,dim);
+  for(int i = 0;i<n;i++)
+  {
+    for(int j = 0;j<dim;j++)
+    {
+      W  (i,j) = VA(i,j) + s(j);
+      W(i+n,j) = VA(i,j) + d(j);
+    }
+  }
+  // number of faces
+  const int m = FA.rows();
+  // Mask whether positive dot product, or negative: because of exactly zero,
+  // these are not necessarily complementary
+  Matrix<bool,Dynamic,1> P(m,1),N(m,1);
+  // loop over faces
+  int mp = 0,mn = 0;
+  for(int f = 0;f<m;f++)
+  {
+    const CGAL::Plane_3<CGAL::Epeck> plane(
+      CGAL::Point_3<CGAL::Epeck>(VA(FA(f,0),0),VA(FA(f,0),1),VA(FA(f,0),2)),
+      CGAL::Point_3<CGAL::Epeck>(VA(FA(f,1),0),VA(FA(f,1),1),VA(FA(f,1),2)),
+      CGAL::Point_3<CGAL::Epeck>(VA(FA(f,2),0),VA(FA(f,2),1),VA(FA(f,2),2)));
+    const auto normal = plane.orthogonal_vector();
+    const auto dt = normal * v;
+    if(dt > 0)
+    {
+      P(f) = true;
+      N(f) = false;
+      mp++;
+    }else if(dt < 0)
+    {
+      P(f) = false;
+      N(f) = true;
+      mn++;
+    }else
+    {
+      P(f) = false;
+      N(f) = false;
+    }
+  }
+
+  typedef Matrix<typename DerivedG::Scalar,Dynamic,Dynamic> MatrixXI;
+  typedef Matrix<typename DerivedG::Scalar,Dynamic,1> VectorXI;
+  MatrixXI GT(mp+mn,3);
+  GT<< slice_mask(FA,N,1), slice_mask((FA.array()+n).eval(),P,1);
+  // J indexes FA for parts at s and m+FA for parts at d
+  J = DerivedJ::LinSpaced(m,0,m-1);
+  DerivedJ JT(mp+mn);
+  JT << slice_mask(J,P,1), slice_mask(J,N,1);
+  JT.block(mp,0,mn,1).array()+=m;
+
+  // Original non-co-planar faces with positively oriented reversed
+  MatrixXI BA(mp+mn,3);
+  BA << slice_mask(FA,P,1).rowwise().reverse(), slice_mask(FA,N,1);
+  // Quads along **all** sides
+  MatrixXI GQ((mp+mn)*3,4);
+  GQ<< 
+    BA.col(1), BA.col(0), BA.col(0).array()+n, BA.col(1).array()+n,
+    BA.col(2), BA.col(1), BA.col(1).array()+n, BA.col(2).array()+n,
+    BA.col(0), BA.col(2), BA.col(2).array()+n, BA.col(0).array()+n;
+
+  MatrixXI uGQ;
+  VectorXI S,sI,sJ;
+  //const auto & total_signed_distance = 
+  [](
+      const MatrixXI & F,
+      VectorXI & S,
+      MatrixXI & uF,
+      VectorXI & I,
+      VectorXI & J)
+  {
+    const int m = F.rows();
+    const int d = F.cols();
+    MatrixXI sF = F;
+    const auto MN = sF.rowwise().minCoeff().eval();
+    // rotate until smallest index is first
+    for(int p = 0;p<d;p++)
+    {
+      for(int f = 0;f<m;f++)
+      {
+        if(sF(f,0) != MN(f))
+        {
+          for(int r = 0;r<d-1;r++)
+          {
+            std::swap(sF(f,r),sF(f,r+1));
+          }
+        }
+      }
+    }
+    // swap orienation
+    for(int f = 0;f<m;f++)
+    {
+      if(sF(f,d-1) < sF(f,1))
+      {
+        sF.block(f,1,1,d-1) = sF.block(f,1,1,d-1).reverse().eval();
+      }
+    }
+    Matrix<bool,Dynamic,1> M = Matrix<bool,Dynamic,1>::Zero(m,1);
+    {
+      VectorXI P = VectorXI::LinSpaced(d,0,d-1);
+      for(int p = 0;p<d;p++)
+      {
+        for(int f = 0;f<m;f++)
+        {
+          bool all = true;
+          for(int r = 0;r<d;r++)
+          {
+            all = all && (sF(f,P(r)) == F(f,r));
+          }
+          M(f) = M(f) || all;
+        }
+        for(int r = 0;r<d-1;r++)
+        {
+          std::swap(P(r),P(r+1));
+        }
+      }
+    }
+    unique_rows(sF,uF,I,J);
+    S = VectorXI::Zero(uF.rows(),1);
+    assert(m == J.rows());
+    for(int f = 0;f<m;f++)
+    {
+      S(J(f)) += M(f) ? 1 : -1;
+    }
+  }(MatrixXI(GQ),S,uGQ,sI,sJ);
+  assert(S.rows() == uGQ.rows());
+  const int nq = (S.array().abs()==2).count();
+  GQ.resize(nq,4);
+  {
+    int k = 0;
+    for(int q = 0;q<uGQ.rows();q++)
+    {
+      switch(S(q))
+      {
+        case -2:
+          GQ.row(k++) = uGQ.row(q).reverse().eval();
+          break;
+        case 2:
+          GQ.row(k++) = uGQ.row(q);
+          break;
+        default:
+        // do not add
+          break;
+      }
+    }
+    assert(nq == k);
+  }
+
+  G.resize(GT.rows()+2*GQ.rows(),3);
+  G<< 
+    GT,
+    GQ.col(0), GQ.col(1), GQ.col(2), 
+    GQ.col(0), GQ.col(2), GQ.col(3);
+  J.resize(JT.rows()+2*GQ.rows(),1);
+  J<<JT,DerivedJ::Constant(2*GQ.rows(),1,2*m+1);
+  if(resolve_overlaps)
+  {
+    Eigen::Matrix<typename DerivedJ::Scalar, Eigen::Dynamic,1> SJ;
+    mesh_boolean(
+      DerivedW(W),DerivedG(G),
+      Matrix<typename DerivedVA::Scalar,Dynamic,Dynamic>(),MatrixXI(),
+      MESH_BOOLEAN_TYPE_UNION,
+      W,G,SJ);
+    J = slice(DerivedJ(J),SJ,1);
+  }
+}
+
+template <
+  typename DerivedVA,
+  typename DerivedFA,
+  typename sType, int sCols, int sOptions,
+  typename dType, int dCols, int dOptions,
+  typename DerivedW,
+  typename DerivedG,
+  typename DerivedJ>
+IGL_INLINE void igl::copyleft::boolean::minkowski_sum(
+  const Eigen::PlainObjectBase<DerivedVA> & VA,
+  const Eigen::PlainObjectBase<DerivedFA> & FA,
+  const Eigen::Matrix<sType,1,sCols,sOptions> & s,
+  const Eigen::Matrix<dType,1,dCols,dOptions> & d,
+  Eigen::PlainObjectBase<DerivedW> & W,
+  Eigen::PlainObjectBase<DerivedG> & G,
+  Eigen::PlainObjectBase<DerivedJ> & J)
+{
+  return minkowski_sum(VA,FA,s,d,true,W,G,J);
+}

+ 110 - 0
include/igl/copyleft/boolean/minkowski_sum.h

@@ -0,0 +1,110 @@
+// 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_MINKOWSKI_SUM_H
+#define IGL_COPYLEFT_CGAL_MINKOWSKI_SUM_H
+
+#include "../../igl_inline.h"
+#include <Eigen/Core>
+
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace boolean
+    {
+      // Compute the Minkowski sum of a closed triangle mesh (V,F) and a
+      // set of simplices in 3D.
+      //
+      // Inputs:
+      //   VA  #VA by 3 list of mesh vertices in 3D
+      //   FA  #FA by 3 list of triangle indices into VA
+      //   VB  #VB by 3 list of mesh vertices in 3D
+      //   FB  #FB by ss list of simplex indices into VB, ss<=3
+      //   resolve_overlaps  whether or not to resolve self-union. If false
+      //     then result may contain self-intersections if input mesh is
+      //     non-convex.
+      // Outputs:
+      //   W  #W by 3 list of mesh vertices in 3D
+      //   G  #G by 3 list of triangle indices into W
+      //   J  #G by 2 list of indices into 
+      //   
+      template <
+        typename DerivedVA,
+        typename DerivedFA,
+        typename DerivedVB,
+        typename DerivedFB,
+        typename DerivedW,
+        typename DerivedG,
+        typename DerivedJ>
+      IGL_INLINE void minkowski_sum(
+        const Eigen::PlainObjectBase<DerivedVA> & VA,
+        const Eigen::PlainObjectBase<DerivedFA> & FA,
+        const Eigen::PlainObjectBase<DerivedVB> & VB,
+        const Eigen::PlainObjectBase<DerivedFB> & FB,
+        const bool resolve_overlaps,
+        Eigen::PlainObjectBase<DerivedW> & W,
+        Eigen::PlainObjectBase<DerivedG> & G,
+        Eigen::PlainObjectBase<DerivedJ> & J);
+      // Compute the Minkowski sum of a closed triangle mesh (V,F) and a
+      // segment [s,d] in 3D.
+      //
+      // Inputs:
+      //   VA  #VA by 3 list of mesh vertices in 3D
+      //   FA  #FA by 3 list of triangle indices into VA
+      //   s  segment source endpoint in 3D
+      //   d  segment source endpoint in 3D
+      //   resolve_overlaps  whether or not to resolve self-union. If false
+      //     then result may contain self-intersections if input mesh is
+      //     non-convex.
+      // Outputs:
+      //   W  #W by 3 list of mesh vertices in 3D
+      //   G  #G by 3 list of triangle indices into W
+      //   J  #G list of indices into [F;#V+F;[s d]] of birth parents
+      //
+      template <
+        typename DerivedVA,
+        typename DerivedFA,
+        typename sType, int sCols, int sOptions,
+        typename dType, int dCols, int dOptions,
+        typename DerivedW,
+        typename DerivedG,
+        typename DerivedJ>
+      IGL_INLINE void minkowski_sum(
+        const Eigen::PlainObjectBase<DerivedVA> & VA,
+        const Eigen::PlainObjectBase<DerivedFA> & FA,
+        const Eigen::Matrix<sType,1,sCols,sOptions> & s,
+        const Eigen::Matrix<dType,1,dCols,dOptions> & d,
+        const bool resolve_overlaps,
+        Eigen::PlainObjectBase<DerivedW> & W,
+        Eigen::PlainObjectBase<DerivedG> & G,
+        Eigen::PlainObjectBase<DerivedJ> & J);
+      template <
+        typename DerivedVA,
+        typename DerivedFA,
+        typename sType, int sCols, int sOptions,
+        typename dType, int dCols, int dOptions,
+        typename DerivedW,
+        typename DerivedG,
+        typename DerivedJ>
+      IGL_INLINE void minkowski_sum(
+        const Eigen::PlainObjectBase<DerivedVA> & VA,
+        const Eigen::PlainObjectBase<DerivedFA> & FA,
+        const Eigen::Matrix<sType,1,sCols,sOptions> & s,
+        const Eigen::Matrix<dType,1,dCols,dOptions> & d,
+        Eigen::PlainObjectBase<DerivedW> & W,
+        Eigen::PlainObjectBase<DerivedG> & G,
+        Eigen::PlainObjectBase<DerivedJ> & J);
+    }
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "minkowski_sum.cpp"
+#endif
+
+#endif

+ 2 - 2
include/igl/boolean/string_to_mesh_boolean_type.cpp → include/igl/copyleft/boolean/string_to_mesh_boolean_type.cpp

@@ -3,7 +3,7 @@
 #include <cassert>
 #include <vector>
 
-IGL_INLINE bool igl::boolean::string_to_mesh_boolean_type( 
+IGL_INLINE bool igl::copyleft::boolean::string_to_mesh_boolean_type( 
   const std::string & s,
   MeshBooleanType & type)
 {
@@ -38,7 +38,7 @@ IGL_INLINE bool igl::boolean::string_to_mesh_boolean_type(
   return true;
 }
 
-IGL_INLINE igl::boolean::MeshBooleanType igl::boolean::string_to_mesh_boolean_type( 
+IGL_INLINE igl::copyleft::boolean::MeshBooleanType igl::copyleft::boolean::string_to_mesh_boolean_type( 
   const std::string & s)
 {
   MeshBooleanType type;

+ 44 - 0
include/igl/copyleft/boolean/string_to_mesh_boolean_type.h

@@ -0,0 +1,44 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_COPYLEFT_BOOLEAN_STRING_TO_MESH_BOOLEAN_H
+#define IGL_COPYLEFT_BOOLEAN_STRING_TO_MESH_BOOLEAN_H
+
+#include "../../igl_inline.h"
+#include "MeshBooleanType.h"
+#include <string>
+
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace boolean
+    {
+      // Convert string to boolean type
+      //
+      //  Inputs:
+      //    s  string identifying type, one of the following:
+      //      "union","intersect","minus","xor","resolve"
+      //  Outputs:
+      //    type  type of boolean operation
+      // Returns true only on success
+      //     
+      IGL_INLINE bool string_to_mesh_boolean_type(
+        const std::string & s,
+        MeshBooleanType & type);
+      // Returns type without error handling
+      IGL_INLINE MeshBooleanType string_to_mesh_boolean_type(
+        const std::string & s);
+    }
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "string_to_mesh_boolean_type.cpp"
+#endif
+
+#endif

+ 3 - 3
include/igl/boolean/to_cork_mesh.cpp → include/igl/copyleft/boolean/to_cork_mesh.cpp

@@ -10,7 +10,7 @@
 template <
   typename DerivedV,
   typename DerivedF>
-IGL_INLINE void igl::boolean::to_cork_mesh(
+IGL_INLINE void igl::copyleft::boolean::to_cork_mesh(
   const Eigen::PlainObjectBase<DerivedV > & V,
   const Eigen::PlainObjectBase<DerivedF > & F,
   CorkTriMesh & mesh)
@@ -39,7 +39,7 @@ IGL_INLINE void igl::boolean::to_cork_mesh(
 }
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
-template void igl::boolean::to_cork_mesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, CorkTriMesh&);
-template void igl::boolean::to_cork_mesh<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&, CorkTriMesh&);
+template void igl::copyleft::boolean::to_cork_mesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, CorkTriMesh&);
+template void igl::copyleft::boolean::to_cork_mesh<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&, CorkTriMesh&);
 #endif
 #endif

+ 41 - 0
include/igl/copyleft/boolean/to_cork_mesh.h

@@ -0,0 +1,41 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_COPYLEFT_BOOLEAN_TO_CORK_MESH_H
+#define IGL_COPYLEFT_BOOLEAN_TO_CORK_MESH_H
+#ifndef IGL_NO_CORK
+#include "../../igl_inline.h"
+#include <cork.h>
+#include <Eigen/Core>
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace boolean
+    {
+      // Convert a (V,F) mesh to a cork's triangle mesh representation.
+      //
+      // Inputs:
+      //   V  #V by 3 list of vertex positions
+      //   F  #F by 3 list of triangle indices into V
+      // Outputs:
+      //   mesh  cork representation of mesh
+      template <
+        typename DerivedV,
+        typename DerivedF>
+      IGL_INLINE void to_cork_mesh(
+        const Eigen::PlainObjectBase<DerivedV > & V,
+        const Eigen::PlainObjectBase<DerivedF > & F,
+        CorkTriMesh & mesh);
+    }
+  }
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "to_cork_mesh.cpp"
+#endif
+#endif
+#endif

+ 0 - 0
include/igl/cgal/CGAL_includes.hpp → include/igl/copyleft/cgal/CGAL_includes.hpp


+ 31 - 0
include/igl/copyleft/cgal/RemeshSelfIntersectionsParam.h

@@ -0,0 +1,31 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_COPYLEFT_CGAL_REMESH_SELF_INTERSECTIONS_PARAM_H
+#define IGL_COPYLEFT_CGAL_REMESH_SELF_INTERSECTIONS_PARAM_H
+
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // Optional Parameters
+      //   DetectOnly  Only compute IF, leave VV and FF alone
+      struct RemeshSelfIntersectionsParam
+      {
+        bool detect_only;
+        bool first_only;
+        RemeshSelfIntersectionsParam():detect_only(false),first_only(false){};
+        RemeshSelfIntersectionsParam(bool _detect_only, bool _first_only):
+          detect_only(_detect_only),first_only(_first_only){};
+      };
+    }
+  }
+}
+
+#endif

+ 362 - 329
include/igl/cgal/SelfIntersectMesh.h → include/igl/copyleft/cgal/SelfIntersectMesh.h

@@ -5,8 +5,8 @@
 // This Source Code Form is subject to the terms of the Mozilla Public License 
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can 
 // obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_CGAL_SELFINTERSECTMESH_H
-#define IGL_CGAL_SELFINTERSECTMESH_H
+#ifndef IGL_COPYLEFT_CGAL_SELFINTERSECTMESH_H
+#define IGL_COPYLEFT_CGAL_SELFINTERSECTMESH_H
 
 #include "CGAL_includes.hpp"
 #include "RemeshSelfIntersectionsParam.h"
@@ -15,6 +15,8 @@
 #include <list>
 #include <map>
 #include <vector>
+#include <thread>
+#include <mutex>
 
 //#define IGL_SELFINTERSECTMESH_DEBUG
 #ifndef IGL_FIRST_HIT_EXCEPTION
@@ -25,199 +27,207 @@
 
 namespace igl
 {
-  namespace cgal
+  namespace copyleft
   {
-    // Kernel is a CGAL kernel like:
-    //     CGAL::Exact_predicates_inexact_constructions_kernel
-    // or 
-    //     CGAL::Exact_predicates_exact_constructions_kernel
-  
-    template <
-      typename Kernel,
-      typename DerivedV,
-      typename DerivedF,
-      typename DerivedVV,
-      typename DerivedFF,
-      typename DerivedIF,
-      typename DerivedJ,
-      typename DerivedIM>
-    class SelfIntersectMesh
+    namespace cgal
     {
-      typedef 
-        SelfIntersectMesh<
-        Kernel,
-        DerivedV,
-        DerivedF,
-        DerivedVV,
-        DerivedFF,
-        DerivedIF,
-        DerivedJ,
-        DerivedIM> Self;
-      public:
-        // 3D Primitives
-        typedef CGAL::Point_3<Kernel>    Point_3;
-        typedef CGAL::Segment_3<Kernel>  Segment_3; 
-        typedef CGAL::Triangle_3<Kernel> Triangle_3; 
-        typedef CGAL::Plane_3<Kernel>    Plane_3;
-        typedef CGAL::Tetrahedron_3<Kernel> Tetrahedron_3; 
-        //typedef CGAL::Polyhedron_3<Kernel> Polyhedron_3; 
-        //typedef CGAL::Nef_polyhedron_3<Kernel> Nef_polyhedron_3; 
-        // 2D Primitives
-        typedef CGAL::Point_2<Kernel>    Point_2;
-        typedef CGAL::Segment_2<Kernel>  Segment_2; 
-        typedef CGAL::Triangle_2<Kernel> Triangle_2; 
-        // 2D Constrained Delaunay Triangulation types
-        typedef CGAL::Triangulation_vertex_base_2<Kernel>  TVB_2;
-        typedef CGAL::Constrained_triangulation_face_base_2<Kernel> CTFB_2;
-        typedef CGAL::Triangulation_data_structure_2<TVB_2,CTFB_2> TDS_2;
-        typedef CGAL::Exact_intersections_tag Itag;
-        typedef CGAL::Constrained_Delaunay_triangulation_2<Kernel,TDS_2,Itag> 
-          CDT_2;
-        typedef CGAL::Constrained_triangulation_plus_2<CDT_2> CDT_plus_2;
-        // Axis-align boxes for all-pairs self-intersection detection
-        typedef std::vector<Triangle_3> Triangles;
-        typedef typename Triangles::iterator TrianglesIterator;
-        typedef typename Triangles::const_iterator TrianglesConstIterator;
+      // Kernel is a CGAL kernel like:
+      //     CGAL::Exact_predicates_inexact_constructions_kernel
+      // or 
+      //     CGAL::Exact_predicates_exact_constructions_kernel
+    
+      template <
+        typename Kernel,
+        typename DerivedV,
+        typename DerivedF,
+        typename DerivedVV,
+        typename DerivedFF,
+        typename DerivedIF,
+        typename DerivedJ,
+        typename DerivedIM>
+      class SelfIntersectMesh
+      {
         typedef 
-          CGAL::Box_intersection_d::Box_with_handle_d<double,3,TrianglesIterator> 
-          Box;
-  
-        // Input mesh
-        const Eigen::PlainObjectBase<DerivedV> & V;
-        const Eigen::PlainObjectBase<DerivedF> & F;
-        // Number of self-intersecting triangle pairs
-        typedef typename DerivedF::Index Index;
-        Index count;
-        typedef std::vector<CGAL::Object> ObjectList;
-        // Using a vector here makes this **not** output sensitive
-        Triangles T;
-        typedef std::vector<Index> IndexList;
-        IndexList lIF;
-        // #F-long list of faces with intersections mapping to the order in
-        // which they were first found
-        std::map<Index,std::pair<Index,ObjectList> > offending;
-        // Make a short name for the edge map's key
-        typedef std::pair<Index,Index> EMK;
-        // Make a short name for the type stored at each edge, the edge map's
-        // value
-        typedef std::vector<Index> EMV;
-        // Make a short name for the edge map
-        typedef std::map<EMK,EMV> EdgeMap;
-        // Maps edges of offending faces to all incident offending faces
-        EdgeMap edge2faces;
-      public:
-        RemeshSelfIntersectionsParam params;
-      public:
-        // Constructs (VV,FF) a new mesh with self-intersections of (V,F)
-        // subdivided
-        //
-        // See also: remesh_self_intersections.h
-        inline SelfIntersectMesh(
-            const Eigen::PlainObjectBase<DerivedV> & V,
-            const Eigen::PlainObjectBase<DerivedF> & F,
-            const RemeshSelfIntersectionsParam & params,
-            Eigen::PlainObjectBase<DerivedVV> & VV,
-            Eigen::PlainObjectBase<DerivedFF> & FF,
-            Eigen::PlainObjectBase<DerivedIF> & IF,
-            Eigen::PlainObjectBase<DerivedJ> & J,
-            Eigen::PlainObjectBase<DerivedIM> & IM);
-      private:
-        // Helper function to mark a face as offensive
-        //
-        // Inputs:
-        //   f  index of face in F
-        inline void mark_offensive(const Index f);
-        // Helper function to count intersections between faces
-        //
-        // Input:
-        //   fa  index of face A in F
-        //   fb  index of face B in F
-        inline void count_intersection( const Index fa, const Index fb);
-        // Helper function for box_intersect. Intersect two triangles A and B,
-        // append the intersection object (point,segment,triangle) to a running
-        // list for A and B
-        //
-        // Inputs:
-        //   A  triangle in 3D
-        //   B  triangle in 3D
-        //   fa  index of A in F (and key into offending)
-        //   fb  index of A in F (and key into offending)
-        // Returns true only if A intersects B
-        //
-        inline bool intersect(
-            const Triangle_3 & A, 
-            const Triangle_3 & B, 
-            const Index fa,
-            const Index fb);
-        // Helper function for box_intersect. In the case where A and B have
-        // already been identified to share a vertex, then we only want to add
-        // possible segment intersections. Assumes truly duplicate triangles are
-        // not given as input
-        //
-        // Inputs:
-        //   A  triangle in 3D
-        //   B  triangle in 3D
-        //   fa  index of A in F (and key into offending)
-        //   fb  index of B in F (and key into offending)
-        //   va  index of shared vertex in A (and key into offending)
-        //   vb  index of shared vertex in B (and key into offending)
-        //// Returns object of intersection (should be Segment or point)
-        //   Returns true if intersection (besides shared point)
-        //
-        inline bool single_shared_vertex(
-            const Triangle_3 & A,
-            const Triangle_3 & B,
-            const Index fa,
-            const Index fb,
-            const Index va,
-            const Index vb);
-        // Helper handling one direction
-        inline bool single_shared_vertex(
-            const Triangle_3 & A,
-            const Triangle_3 & B,
-            const Index fa,
-            const Index fb,
-            const Index va);
-        // Helper function for box_intersect. In the case where A and B have
-        // already been identified to share two vertices, then we only want to add
-        // a possible coplanar (Triangle) intersection. Assumes truly degenerate
-        // facets are not givin as input.
-        inline bool double_shared_vertex(
-            const Triangle_3 & A,
-            const Triangle_3 & B,
-            const Index fa,
-            const Index fb,
-            const std::vector<std::pair<Index,Index> > shared);
-  
-      public:
-        // Callback function called during box self intersections test. Means
-        // boxes a and b intersect. This method then checks if the triangles in
-        // each box intersect and if so, then processes the intersections
-        //
-        // Inputs:
-        //   a  box containing a triangle
-        //   b  box containing a triangle
-        inline void box_intersect(const Box& a, const Box& b);
-      private:
-        // Compute 2D delaunay triangulation of a given 3d triangle and a list of
-        // intersection objects (points,segments,triangles). CGAL uses an affine
-        // projection rather than an isometric projection, so we're not
-        // guaranteed that the 2D delaunay triangulation here will be a delaunay
-        // triangulation in 3D.
-        //
-        // Inputs:
-        //   A  triangle in 3D
-        //   A_objects_3  updated list of intersection objects for A
-        // Outputs:
-        //   cdt  Contrained delaunay triangulation in projected 2D plane
-      public:
-        // Getters:
-        //const IndexList& get_lIF() const{ return lIF;}
-        static inline void box_intersect_static(
-          SelfIntersectMesh * SIM, 
-          const Box &a, 
-          const Box &b);
-    };
+          SelfIntersectMesh<
+          Kernel,
+          DerivedV,
+          DerivedF,
+          DerivedVV,
+          DerivedFF,
+          DerivedIF,
+          DerivedJ,
+          DerivedIM> Self;
+        public:
+          // 3D Primitives
+          typedef CGAL::Point_3<Kernel>    Point_3;
+          typedef CGAL::Segment_3<Kernel>  Segment_3; 
+          typedef CGAL::Triangle_3<Kernel> Triangle_3; 
+          typedef CGAL::Plane_3<Kernel>    Plane_3;
+          typedef CGAL::Tetrahedron_3<Kernel> Tetrahedron_3; 
+          //typedef CGAL::Polyhedron_3<Kernel> Polyhedron_3; 
+          //typedef CGAL::Nef_polyhedron_3<Kernel> Nef_polyhedron_3; 
+          // 2D Primitives
+          typedef CGAL::Point_2<Kernel>    Point_2;
+          typedef CGAL::Segment_2<Kernel>  Segment_2; 
+          typedef CGAL::Triangle_2<Kernel> Triangle_2; 
+          // 2D Constrained Delaunay Triangulation types
+          typedef CGAL::Triangulation_vertex_base_2<Kernel>  TVB_2;
+          typedef CGAL::Constrained_triangulation_face_base_2<Kernel> CTFB_2;
+          typedef CGAL::Triangulation_data_structure_2<TVB_2,CTFB_2> TDS_2;
+          typedef CGAL::Exact_intersections_tag Itag;
+          typedef CGAL::Constrained_Delaunay_triangulation_2<Kernel,TDS_2,Itag> 
+            CDT_2;
+          typedef CGAL::Constrained_triangulation_plus_2<CDT_2> CDT_plus_2;
+          // Axis-align boxes for all-pairs self-intersection detection
+          typedef std::vector<Triangle_3> Triangles;
+          typedef typename Triangles::iterator TrianglesIterator;
+          typedef typename Triangles::const_iterator TrianglesConstIterator;
+          typedef 
+            CGAL::Box_intersection_d::Box_with_handle_d<double,3,TrianglesIterator> 
+            Box;
+    
+          // Input mesh
+          const Eigen::PlainObjectBase<DerivedV> & V;
+          const Eigen::PlainObjectBase<DerivedF> & F;
+          // Number of self-intersecting triangle pairs
+          typedef typename DerivedF::Index Index;
+          Index count;
+          typedef std::vector<std::pair<Index, CGAL::Object>> ObjectList;
+          // Using a vector here makes this **not** output sensitive
+          Triangles T;
+          typedef std::vector<Index> IndexList;
+          IndexList lIF;
+          // #F-long list of faces with intersections mapping to the order in
+          // which they were first found
+          std::map<Index,ObjectList> offending;
+          // Make a short name for the edge map's key
+          typedef std::pair<Index,Index> EMK;
+          // Make a short name for the type stored at each edge, the edge map's
+          // value
+          typedef std::vector<Index> EMV;
+          // Make a short name for the edge map
+          typedef std::map<EMK,EMV> EdgeMap;
+          // Maps edges of offending faces to all incident offending faces
+          EdgeMap edge2faces;
+          std::vector<std::pair<const Box, const Box> > candidate_box_pairs;
+
+        public:
+          RemeshSelfIntersectionsParam params;
+        public:
+          // Constructs (VV,FF) a new mesh with self-intersections of (V,F)
+          // subdivided
+          //
+          // See also: remesh_self_intersections.h
+          inline SelfIntersectMesh(
+              const Eigen::PlainObjectBase<DerivedV> & V,
+              const Eigen::PlainObjectBase<DerivedF> & F,
+              const RemeshSelfIntersectionsParam & params,
+              Eigen::PlainObjectBase<DerivedVV> & VV,
+              Eigen::PlainObjectBase<DerivedFF> & FF,
+              Eigen::PlainObjectBase<DerivedIF> & IF,
+              Eigen::PlainObjectBase<DerivedJ> & J,
+              Eigen::PlainObjectBase<DerivedIM> & IM);
+        private:
+          // Helper function to mark a face as offensive
+          //
+          // Inputs:
+          //   f  index of face in F
+          inline void mark_offensive(const Index f);
+          // Helper function to count intersections between faces
+          //
+          // Input:
+          //   fa  index of face A in F
+          //   fb  index of face B in F
+          inline void count_intersection( const Index fa, const Index fb);
+          // Helper function for box_intersect. Intersect two triangles A and B,
+          // append the intersection object (point,segment,triangle) to a running
+          // list for A and B
+          //
+          // Inputs:
+          //   A  triangle in 3D
+          //   B  triangle in 3D
+          //   fa  index of A in F (and key into offending)
+          //   fb  index of B in F (and key into offending)
+          // Returns true only if A intersects B
+          //
+          inline bool intersect(
+              const Triangle_3 & A, 
+              const Triangle_3 & B, 
+              const Index fa,
+              const Index fb);
+          // Helper function for box_intersect. In the case where A and B have
+          // already been identified to share a vertex, then we only want to add
+          // possible segment intersections. Assumes truly duplicate triangles are
+          // not given as input
+          //
+          // Inputs:
+          //   A  triangle in 3D
+          //   B  triangle in 3D
+          //   fa  index of A in F (and key into offending)
+          //   fb  index of B in F (and key into offending)
+          //   va  index of shared vertex in A (and key into offending)
+          //   vb  index of shared vertex in B (and key into offending)
+          //// Returns object of intersection (should be Segment or point)
+          //   Returns true if intersection (besides shared point)
+          //
+          inline bool single_shared_vertex(
+              const Triangle_3 & A,
+              const Triangle_3 & B,
+              const Index fa,
+              const Index fb,
+              const Index va,
+              const Index vb);
+          // Helper handling one direction
+          inline bool single_shared_vertex(
+              const Triangle_3 & A,
+              const Triangle_3 & B,
+              const Index fa,
+              const Index fb,
+              const Index va);
+          // Helper function for box_intersect. In the case where A and B have
+          // already been identified to share two vertices, then we only want to add
+          // a possible coplanar (Triangle) intersection. Assumes truly degenerate
+          // facets are not givin as input.
+          inline bool double_shared_vertex(
+              const Triangle_3 & A,
+              const Triangle_3 & B,
+              const Index fa,
+              const Index fb,
+              const std::vector<std::pair<Index,Index> > shared);
+    
+        public:
+          // Callback function called during box self intersections test. Means
+          // boxes a and b intersect. This method then checks if the triangles in
+          // each box intersect and if so, then processes the intersections
+          //
+          // Inputs:
+          //   a  box containing a triangle
+          //   b  box containing a triangle
+          inline void box_intersect(const Box& a, const Box& b);
+          inline void process_intersecting_boxes();
+        private:
+          // Compute 2D delaunay triangulation of a given 3d triangle and a list of
+          // intersection objects (points,segments,triangles). CGAL uses an affine
+          // projection rather than an isometric projection, so we're not
+          // guaranteed that the 2D delaunay triangulation here will be a delaunay
+          // triangulation in 3D.
+          //
+          // Inputs:
+          //   A  triangle in 3D
+          //   A_objects_3  updated list of intersection objects for A
+          // Outputs:
+          //   cdt  Contrained delaunay triangulation in projected 2D plane
+        public:
+          // Getters:
+          //const IndexList& get_lIF() const{ return lIF;}
+          static inline void box_intersect_static(
+            SelfIntersectMesh * SIM, 
+            const Box &a, 
+            const Box &b);
+        private:
+          std::mutex m_offending_lock;
+      };
+    }
   }
 }
 
@@ -225,10 +235,11 @@ namespace igl
 
 #include "mesh_to_cgal_triangle_list.h"
 #include "remesh_intersections.h"
+#include "remesh_intersections.h"
 
-#include <igl/REDRUM.h>
-#include <igl/get_seconds.h>
-#include <igl/C_STR.h>
+#include "../../REDRUM.h"
+#include "../../get_seconds.h"
+#include "../../C_STR.h"
 
 
 #include <functional>
@@ -271,7 +282,7 @@ template <
   typename DerivedIF,
   typename DerivedJ,
   typename DerivedIM>
-inline void igl::cgal::SelfIntersectMesh<
+inline void igl::copyleft::cgal::SelfIntersectMesh<
   Kernel,
   DerivedV,
   DerivedF,
@@ -296,7 +307,7 @@ template <
   typename DerivedIF,
   typename DerivedJ,
   typename DerivedIM>
-inline igl::cgal::SelfIntersectMesh<
+inline igl::copyleft::cgal::SelfIntersectMesh<
   Kernel,
   DerivedV,
   DerivedF,
@@ -326,20 +337,24 @@ inline igl::cgal::SelfIntersectMesh<
   using namespace Eigen;
 
 #ifdef IGL_SELFINTERSECTMESH_DEBUG
-  const auto & tictoc = []()
+  const auto & tictoc = []() -> double
   {
     static double t_start = igl::get_seconds();
     double diff = igl::get_seconds()-t_start;
     t_start += diff;
     return diff;
   };
+  const auto log_time = [&](const std::string& label) -> void{
+    std::cout << "SelfIntersectMesh." << label << ": "
+      << tictoc() << std::endl;
+  };
   tictoc();
 #endif
 
   // Compute and process self intersections
   mesh_to_cgal_triangle_list(V,F,T);
 #ifdef IGL_SELFINTERSECTMESH_DEBUG
-  cout<<"mesh_to_cgal_triangle_list: "<<tictoc()<<endl;
+  log_time("convert_to_triangle_list");
 #endif
   // http://www.cgal.org/Manual/latest/doc_html/cgal_manual/Box_intersection_d/Chapter_main.html#Section_63.5 
   // Create the corresponding vector of bounding boxes
@@ -350,7 +365,10 @@ inline igl::cgal::SelfIntersectMesh<
     tit != T.end(); 
     ++tit)
   {
-    boxes.push_back(Box(tit->bbox(), tit));
+    if (!tit->is_degenerate())
+    {
+      boxes.push_back(Box(tit->bbox(), tit));
+    }
   }
   // Leapfrog callback
   std::function<void(const Box &a,const Box &b)> cb = 
@@ -360,7 +378,7 @@ inline igl::cgal::SelfIntersectMesh<
       std::placeholders::_1,
       std::placeholders::_2);
 #ifdef IGL_SELFINTERSECTMESH_DEBUG
-  cout<<"boxes and bind: "<<tictoc()<<endl;
+  log_time("box_and_bind");
 #endif
   // Run the self intersection algorithm with all defaults
   try{
@@ -374,8 +392,9 @@ inline igl::cgal::SelfIntersectMesh<
     }
     // Otherwise just fall through
   }
+  process_intersecting_boxes();
 #ifdef IGL_SELFINTERSECTMESH_DEBUG
-  cout<<"box_self_intersection_d: "<<tictoc()<<endl;
+  log_time("box_intersection_d");
 #endif
 
   // Convert lIF to Eigen matrix
@@ -396,7 +415,7 @@ inline igl::cgal::SelfIntersectMesh<
     }
   }
 #ifdef IGL_SELFINTERSECTMESH_DEBUG
-  cout<<"IF: "<<tictoc()<<endl;
+  log_time("store_intersecting_face_pairs");
 #endif
 
   if(params.detect_only)
@@ -406,6 +425,10 @@ inline igl::cgal::SelfIntersectMesh<
 
   remesh_intersections(V,F,T,offending,edge2faces,VV,FF,J,IM);
 
+#ifdef IGL_SELFINTERSECTMESH_DEBUG
+  log_time("remesh_intersection");
+#endif
+
   // Q: Does this give the same result as TETGEN?
   // A: For the cow and beast, yes.
 
@@ -429,7 +452,7 @@ template <
   typename DerivedIF,
   typename DerivedJ,
   typename DerivedIM>
-inline void igl::cgal::SelfIntersectMesh<
+inline void igl::copyleft::cgal::SelfIntersectMesh<
   Kernel,
   DerivedV,
   DerivedF,
@@ -444,8 +467,7 @@ inline void igl::cgal::SelfIntersectMesh<
   if(offending.count(f) == 0)
   {
     // first time marking, initialize with new id and empty list
-    const Index id = offending.size();
-    offending[f] = {id,{}};
+    offending[f] = {};
     for(Index e = 0; e<3;e++)
     {
       // append face to edge's list
@@ -465,7 +487,7 @@ template <
   typename DerivedIF,
   typename DerivedJ,
   typename DerivedIM>
-inline void igl::cgal::SelfIntersectMesh<
+inline void igl::copyleft::cgal::SelfIntersectMesh<
   Kernel,
   DerivedV,
   DerivedF,
@@ -477,6 +499,7 @@ inline void igl::cgal::SelfIntersectMesh<
   const Index fa,
   const Index fb)
 {
+  std::lock_guard<std::mutex> guard(m_offending_lock);
   mark_offensive(fa);
   mark_offensive(fb);
   this->count++;
@@ -496,7 +519,7 @@ template <
   typename DerivedIF,
   typename DerivedJ,
   typename DerivedIM>
-inline bool igl::cgal::SelfIntersectMesh<
+inline bool igl::copyleft::cgal::SelfIntersectMesh<
   Kernel,
   DerivedV,
   DerivedF,
@@ -520,8 +543,9 @@ inline bool igl::cgal::SelfIntersectMesh<
   {
     // Construct intersection
     CGAL::Object result = CGAL::intersection(A,B);
-    offending[fa].second.push_back(result);
-    offending[fb].second.push_back(result);
+    std::lock_guard<std::mutex> guard(m_offending_lock);
+    offending[fa].push_back({fb, result});
+    offending[fb].push_back({fa, result});
   }
   return true;
 }
@@ -535,7 +559,7 @@ template <
   typename DerivedIF,
   typename DerivedJ,
   typename DerivedIM>
-inline bool igl::cgal::SelfIntersectMesh<
+inline bool igl::copyleft::cgal::SelfIntersectMesh<
   Kernel,
   DerivedV,
   DerivedF,
@@ -581,7 +605,7 @@ template <
   typename DerivedIF,
   typename DerivedJ,
   typename DerivedIM>
-inline bool igl::cgal::SelfIntersectMesh<
+inline bool igl::copyleft::cgal::SelfIntersectMesh<
   Kernel,
   DerivedV,
   DerivedF,
@@ -619,8 +643,9 @@ inline bool igl::cgal::SelfIntersectMesh<
         A.vertex(va),
         *p));
       count_intersection(fa,fb);
-      offending[fa].second.push_back(seg);
-      offending[fb].second.push_back(seg);
+      std::lock_guard<std::mutex> guard(m_offending_lock);
+      offending[fa].push_back({fb, seg});
+      offending[fb].push_back({fa, seg});
       return true;
     }else if(CGAL::object_cast<Segment_3 >(&result))
     {
@@ -660,7 +685,7 @@ template <
   typename DerivedIF,
   typename DerivedJ,
   typename DerivedIM>
-inline bool igl::cgal::SelfIntersectMesh<
+inline bool igl::copyleft::cgal::SelfIntersectMesh<
   Kernel,
   DerivedV,
   DerivedF,
@@ -677,6 +702,8 @@ inline bool igl::cgal::SelfIntersectMesh<
 {
   using namespace std;
 
+  {
+    std::lock_guard<std::mutex> guard(m_offending_lock);
   // must be co-planar
   if(
     A.supporting_plane() != B.supporting_plane() &&
@@ -684,6 +711,7 @@ inline bool igl::cgal::SelfIntersectMesh<
   {
     return false;
   }
+  }
   // Since A and B are non-degenerate the intersection must be a polygon
   // (triangle). Either
   //   - the vertex of A (B) opposite the shared edge of lies on B (A), or
@@ -766,8 +794,9 @@ inline bool igl::cgal::SelfIntersectMesh<
       } else
       {
         // Triangle object
-        offending[fa].second.push_back(result);
-        offending[fb].second.push_back(result);
+        std::lock_guard<std::mutex> guard(m_offending_lock);
+        offending[fa].push_back({fb, result});
+        offending[fb].push_back({fa, result});
         //cerr<<REDRUM("Coplanar at: "<<fa<<" & "<<fb<<" (double shared).")<<endl;
         return true;
       }
@@ -802,7 +831,7 @@ template <
   typename DerivedIF,
   typename DerivedJ,
   typename DerivedIM>
-inline void igl::cgal::SelfIntersectMesh<
+inline void igl::copyleft::cgal::SelfIntersectMesh<
   Kernel,
   DerivedV,
   DerivedF,
@@ -814,125 +843,129 @@ inline void igl::cgal::SelfIntersectMesh<
   const Box& a, 
   const Box& b)
 {
-  using namespace std;
-  // Could we write this as a static function of:
-  //
-  // F.row(fa)
-  // F.row(fb)
-  // A
-  // B
-
-  // index in F and T
-  Index fa = a.handle()-T.begin();
-  Index fb = b.handle()-T.begin();
-  const Triangle_3 & A = *a.handle();
-  const Triangle_3 & B = *b.handle();
-  // I'm not going to deal with degenerate triangles, though at some point we
-  // should
-  assert(!a.handle()->is_degenerate());
-  assert(!b.handle()->is_degenerate());
-  // Number of combinatorially shared vertices
-  Index comb_shared_vertices = 0;
-  // Number of geometrically shared vertices (*not* including combinatorially
-  // shared)
-  Index geo_shared_vertices = 0;
-  // Keep track of shared vertex indices
-  std::vector<std::pair<Index,Index> > shared;
-  Index ea,eb;
-  for(ea=0;ea<3;ea++)
-  {
-    for(eb=0;eb<3;eb++)
-    {
-      if(F(fa,ea) == F(fb,eb))
+  candidate_box_pairs.push_back({a, b});
+}
+
+template <
+  typename Kernel,
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedVV,
+  typename DerivedFF,
+  typename DerivedIF,
+  typename DerivedJ,
+  typename DerivedIM>
+inline void igl::copyleft::cgal::SelfIntersectMesh<
+  Kernel,
+  DerivedV,
+  DerivedF,
+  DerivedVV,
+  DerivedFF,
+  DerivedIF,
+  DerivedJ,
+  DerivedIM>::process_intersecting_boxes()
+{
+  CGAL::Identity_transformation I;
+  std::vector<std::mutex> triangle_locks(T.size());
+  auto process_chunk = [&](size_t first, size_t last) -> void{
+    assert(last >= first);
+
+    for (size_t i=first; i<last; i++) {
+      const auto& box_pair = candidate_box_pairs[i];
+      const auto& a = box_pair.first;
+      const auto& b = box_pair.second;
+      Index fa = a.handle()-T.begin();
+      Index fb = b.handle()-T.begin();
+
+      std::lock_guard<std::mutex> guard_A(triangle_locks[fa]);
+      std::lock_guard<std::mutex> guard_B(triangle_locks[fb]);
+      const Triangle_3& A = *a.handle();
+      const Triangle_3& B = *b.handle();
+
+      // Number of combinatorially shared vertices
+      Index comb_shared_vertices = 0;
+      // Number of geometrically shared vertices (*not* including combinatorially
+      // shared)
+      Index geo_shared_vertices = 0;
+      // Keep track of shared vertex indices
+      std::vector<std::pair<Index,Index> > shared;
+      Index ea,eb;
+      for(ea=0;ea<3;ea++)
+      {
+        for(eb=0;eb<3;eb++)
+        {
+          if(F(fa,ea) == F(fb,eb))
+          {
+            comb_shared_vertices++;
+            shared.emplace_back(ea,eb);
+          }else if(A.vertex(ea) == B.vertex(eb))
+          {
+            geo_shared_vertices++;
+            shared.emplace_back(ea,eb);
+          }
+        }
+      }
+      const Index total_shared_vertices = comb_shared_vertices + geo_shared_vertices;
+
+      if(comb_shared_vertices== 3)
       {
-        comb_shared_vertices++;
-        shared.emplace_back(ea,eb);
-      }else if(A.vertex(ea) == B.vertex(eb))
+        assert(shared.size() == 3);
+        //// Combinatorially duplicate face, these should be removed by preprocessing
+        //cerr<<REDRUM("Facets "<<fa<<" and "<<fb<<" are combinatorial duplicates")<<endl;
+        continue;
+      }
+      if(total_shared_vertices== 3)
       {
-        geo_shared_vertices++;
-        shared.emplace_back(ea,eb);
+        assert(shared.size() == 3);
+        //// Geometrically duplicate face, these should be removed by preprocessing
+        //cerr<<REDRUM("Facets "<<fa<<" and "<<fb<<" are geometrical duplicates")<<endl;
+        continue;
+      }
+      if(total_shared_vertices == 2)
+      {
+        assert(shared.size() == 2);
+        // Q: What about coplanar?
+        //
+        // o    o
+        // |\  /|
+        // | \/ |
+        // | /\ |
+        // |/  \|
+        // o----o
+        double_shared_vertex(A,B,fa,fb,shared);
+        continue;
+      }
+      assert(total_shared_vertices<=1);
+      if(total_shared_vertices==1)
+      {
+        single_shared_vertex(A,B,fa,fb,shared[0].first,shared[0].second);
+      }else
+      {
+        intersect(*a.handle(),*b.handle(),fa,fb);
       }
     }
+  };
+  size_t num_threads=0;
+  const size_t hardware_limit = std::thread::hardware_concurrency();
+  if (const char* igl_num_threads = std::getenv("LIBIGL_NUM_THREADS")) {
+    num_threads = atoi(igl_num_threads);
   }
-  const Index total_shared_vertices = comb_shared_vertices + geo_shared_vertices;
-  if(comb_shared_vertices== 3)
-  {
-    assert(shared.size() == 3);
-    //// Combinatorially duplicate face, these should be removed by preprocessing
-    //cerr<<REDRUM("Facets "<<fa<<" and "<<fb<<" are combinatorial duplicates")<<endl;
-    goto done;
+  if (num_threads == 0 || num_threads > hardware_limit) {
+    num_threads = hardware_limit;
   }
-  if(total_shared_vertices== 3)
-  {
-    assert(shared.size() == 3);
-    //// Geometrically duplicate face, these should be removed by preprocessing
-    //cerr<<REDRUM("Facets "<<fa<<" and "<<fb<<" are geometrical duplicates")<<endl;
-    goto done;
+  assert(num_threads > 0);
+  const size_t num_pairs = candidate_box_pairs.size();
+  const size_t chunk_size = num_pairs / num_threads;
+  std::vector<std::thread> threads;
+  for (size_t i=0; i<num_threads-1; i++) {
+    threads.emplace_back(process_chunk, i*chunk_size, (i+1)*chunk_size);
   }
-  //// SPECIAL CASES ARE BROKEN FOR COPLANAR TRIANGLES
-  //if(total_shared_vertices > 0)
-  //{
-  //  bool coplanar = 
-  //    CGAL::coplanar(A.vertex(0),A.vertex(1),A.vertex(2),B.vertex(0)) &&
-  //    CGAL::coplanar(A.vertex(0),A.vertex(1),A.vertex(2),B.vertex(1)) &&
-  //    CGAL::coplanar(A.vertex(0),A.vertex(1),A.vertex(2),B.vertex(2));
-  //  if(coplanar)
-  //  {
-  //    cerr<<MAGENTAGIN("Facets "<<fa<<" and "<<fb<<
-  //      " are coplanar and share vertices")<<endl;
-  //    goto full;
-  //  }
-  //}
-
-  if(total_shared_vertices == 2)
-  {
-    assert(shared.size() == 2);
-    // Q: What about coplanar?
-    //
-    // o    o
-    // |\  /|
-    // | \/ |
-    // | /\ |
-    // |/  \|
-    // o----o
-    double_shared_vertex(A,B,fa,fb,shared);
-
-    goto done;
+  // Do some work in the master thread.
+  process_chunk((num_threads-1)*chunk_size, num_pairs);
+  for (auto& t : threads) {
+    if (t.joinable()) t.join();
   }
-  assert(total_shared_vertices<=1);
-  if(total_shared_vertices==1)
-  {
-//#ifndef NDEBUG
-//    CGAL::Object result =
-//#endif
-    single_shared_vertex(A,B,fa,fb,shared[0].first,shared[0].second);
-//#ifndef NDEBUG
-//    if(!CGAL::object_cast<Segment_3 >(&result))
-//    {
-//      const Point_3 * p = CGAL::object_cast<Point_3 >(&result);
-//      assert(p);
-//      for(int ea=0;ea<3;ea++)
-//      {
-//        for(int eb=0;eb<3;eb++)
-//        {
-//          if(F(fa,ea) == F(fb,eb))
-//          {
-//            assert(*p==A.vertex(ea));
-//            assert(*p==B.vertex(eb));
-//          }
-//        }
-//      }
-//    }
-//#endif
-  }else
-  {
-//full:
-    // No geometrically shared vertices, do general intersect
-    intersect(*a.handle(),*b.handle(),fa,fb);
-  }
-done:
-  return;
+  //process_chunk(0, candidate_box_pairs.size());
 }
 
 #endif
-

+ 10 - 4
include/igl/cgal/assign_scalar.cpp → include/igl/copyleft/cgal/assign_scalar.cpp

@@ -7,21 +7,27 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "assign_scalar.h"
 
-IGL_INLINE void igl::cgal::assign_scalar(
+IGL_INLINE void igl::copyleft::cgal::assign_scalar(
   const typename CGAL::Epeck::FT & cgal,
   CGAL::Epeck::FT & d)
 {
   d = cgal;
 }
 
-IGL_INLINE void igl::cgal::assign_scalar(
+IGL_INLINE void igl::copyleft::cgal::assign_scalar(
   const typename CGAL::Epeck::FT & cgal,
   double & d)
 {
-  d = CGAL::to_double(cgal);
+  const auto interval = CGAL::to_interval(cgal);
+  d = interval.first;
+  do {
+      const double next = nextafter(d, interval.second);
+      if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break;
+      d = next;
+  } while (d < interval.second);
 }
 
-IGL_INLINE void igl::cgal::assign_scalar(
+IGL_INLINE void igl::copyleft::cgal::assign_scalar(
   const double & c,
   double & d)
 {

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

@@ -0,0 +1,37 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_COPYLEFT_CGAL_ASSIGN_SCALAR_H
+#define IGL_COPYLEFT_CGAL_ASSIGN_SCALAR_H
+#include "../../igl_inline.h"
+#include "CGAL_includes.hpp"
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // Inputs:
+      //   cgal  cgal scalar
+      // Outputs:
+      //   d  output scalar
+      IGL_INLINE void assign_scalar(
+        const typename CGAL::Epeck::FT & cgal,
+        CGAL::Epeck::FT & d);
+      IGL_INLINE void assign_scalar(
+        const typename CGAL::Epeck::FT & cgal,
+        double & d);
+      IGL_INLINE void assign_scalar(
+        const double & c,
+        double & d);
+    }
+  }
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "assign_scalar.cpp"
+#endif
+#endif

+ 453 - 0
include/igl/copyleft/cgal/closest_facet.cpp

@@ -0,0 +1,453 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Qingnan Zhou <qnzhou@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+//
+#include "closest_facet.h"
+
+#include <vector>
+#include <stdexcept>
+#include <unordered_map>
+
+#include <CGAL/AABB_tree.h>
+#include <CGAL/AABB_traits.h>
+#include <CGAL/AABB_triangle_primitive.h>
+#include <CGAL/intersections.h>
+#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+
+#include "order_facets_around_edge.h"
+#include "../../vertex_triangle_adjacency.h"
+#include "../../writePLY.h"
+
+template<
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedI,
+  typename DerivedP,
+  typename uE2EType,
+  typename DerivedEMAP,
+  typename DerivedR,
+  typename DerivedS >
+IGL_INLINE void igl::copyleft::cgal::closest_facet(
+    const Eigen::PlainObjectBase<DerivedV>& V,
+    const Eigen::PlainObjectBase<DerivedF>& F,
+    const Eigen::PlainObjectBase<DerivedI>& I,
+    const Eigen::PlainObjectBase<DerivedP>& P,
+    const std::vector<std::vector<uE2EType> >& uE2E,
+    const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
+    Eigen::PlainObjectBase<DerivedR>& R,
+    Eigen::PlainObjectBase<DerivedS>& S) {
+  typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
+  typedef Kernel::Point_3 Point_3;
+  typedef Kernel::Plane_3 Plane_3;
+  typedef Kernel::Segment_3 Segment_3;
+  typedef Kernel::Triangle_3 Triangle;
+  typedef std::vector<Triangle>::iterator Iterator;
+  typedef CGAL::AABB_triangle_primitive<Kernel, Iterator> Primitive;
+  typedef CGAL::AABB_traits<Kernel, Primitive> AABB_triangle_traits;
+  typedef CGAL::AABB_tree<AABB_triangle_traits> Tree;
+
+  if (F.rows() <= 0 || I.rows() <= 0) {
+    throw std::runtime_error(
+        "Closest facet cannot be computed on empty mesh.");
+  }
+
+  std::vector<std::vector<size_t> > VF;
+  std::vector<std::vector<size_t> > VFi;
+  igl::vertex_triangle_adjacency(V.rows(), F, VF, VFi);
+
+  std::vector<bool> in_I(F.rows(), false);
+  const size_t num_faces = I.rows();
+  std::vector<Triangle> triangles;
+  for (size_t i=0; i<num_faces; i++) {
+    const Eigen::Vector3i f = F.row(I(i, 0));
+    in_I[I(i,0)] = true;
+    triangles.emplace_back(
+        Point_3(V(f[0], 0), V(f[0], 1), V(f[0], 2)),
+        Point_3(V(f[1], 0), V(f[1], 1), V(f[1], 2)),
+        Point_3(V(f[2], 0), V(f[2], 1), V(f[2], 2)));
+    if (triangles.back().is_degenerate()) {
+      throw std::runtime_error(
+          "Input facet components contains degenerated triangles");
+    }
+  }
+  Tree tree(triangles.begin(), triangles.end());
+  tree.accelerate_distance_queries();
+
+  auto on_the_positive_side = [&](size_t fid, const Point_3& p) -> bool{
+    const auto& f = F.row(fid).eval();
+    Point_3 v0(V(f[0], 0), V(f[0], 1), V(f[0], 2));
+    Point_3 v1(V(f[1], 0), V(f[1], 1), V(f[1], 2));
+    Point_3 v2(V(f[2], 0), V(f[2], 1), V(f[2], 2));
+    auto ori = CGAL::orientation(v0, v1, v2, p);
+    switch (ori) {
+      case CGAL::POSITIVE:
+        return true;
+      case CGAL::NEGATIVE:
+        return false;
+      case CGAL::COPLANAR:
+        // Warning:
+        // This can only happen if fid contains a boundary edge.
+        // Catergorized this ambiguous case as negative side.
+        return false;
+      default:
+        throw std::runtime_error("Unknown CGAL state.");
+    }
+    return false;
+  };
+
+  auto get_orientation = [&](size_t fid, size_t s, size_t d) -> bool {
+    const auto& f = F.row(fid);
+    if      ((size_t)f[0] == s && (size_t)f[1] == d) return false;
+    else if ((size_t)f[1] == s && (size_t)f[2] == d) return false;
+    else if ((size_t)f[2] == s && (size_t)f[0] == d) return false;
+    else if ((size_t)f[0] == d && (size_t)f[1] == s) return true;
+    else if ((size_t)f[1] == d && (size_t)f[2] == s) return true;
+    else if ((size_t)f[2] == d && (size_t)f[0] == s) return true;
+    else {
+      throw std::runtime_error(
+          "Cannot compute orientation due to incorrect connectivity");
+      return false;
+    }
+  };
+  auto index_to_signed_index = [&](size_t index, bool ori) -> int{
+    return (index+1) * (ori? 1:-1);
+  };
+  //auto signed_index_to_index = [&](int signed_index) -> size_t {
+  //    return abs(signed_index) - 1;
+  //};
+
+  enum ElementType { VERTEX, EDGE, FACE };
+  auto determine_element_type = [&](const Point_3& p, const size_t fid,
+      size_t& element_index) -> ElementType {
+    const auto& tri = triangles[fid];
+    const Point_3 p0 = tri[0];
+    const Point_3 p1 = tri[1];
+    const Point_3 p2 = tri[2];
+
+    if (p == p0) { element_index = 0; return VERTEX; }
+    if (p == p1) { element_index = 1; return VERTEX; }
+    if (p == p2) { element_index = 2; return VERTEX; }
+    if (CGAL::collinear(p0, p1, p)) { element_index = 2; return EDGE; }
+    if (CGAL::collinear(p1, p2, p)) { element_index = 0; return EDGE; }
+    if (CGAL::collinear(p2, p0, p)) { element_index = 1; return EDGE; }
+
+    element_index = 0;
+    return FACE;
+  };
+
+  auto process_edge_case = [&](
+      size_t query_idx,
+      const size_t s, const size_t d,
+      size_t preferred_facet,
+      bool& orientation) -> size_t {
+    Point_3 query_point(
+        P(query_idx, 0),
+        P(query_idx, 1),
+        P(query_idx, 2));
+
+    size_t corner_idx = std::numeric_limits<size_t>::max();
+    if ((s == F(preferred_facet, 0) && d == F(preferred_facet, 1)) ||
+        (s == F(preferred_facet, 1) && d == F(preferred_facet, 0))) {
+      corner_idx = 2;
+    } else if ((s == F(preferred_facet, 0) && d == F(preferred_facet, 2)) ||
+        (s == F(preferred_facet, 2) && d == F(preferred_facet, 0))) {
+      corner_idx = 1;
+    } else if ((s == F(preferred_facet, 1) && d == F(preferred_facet, 2)) ||
+        (s == F(preferred_facet, 2) && d == F(preferred_facet, 1))) {
+      corner_idx = 0;
+    } else {
+      std::cerr << "s: " << s << "\t d:" << d << std::endl;
+      std::cerr << F.row(preferred_facet) << std::endl;
+      throw std::runtime_error(
+          "Invalid connectivity, edge does not belong to facet");
+    }
+
+    auto ueid = EMAP(preferred_facet + corner_idx * F.rows());
+    auto eids = uE2E[ueid];
+    std::vector<size_t> intersected_face_indices;
+    for (auto eid : eids) {
+      const size_t fid = eid % F.rows();
+      if (in_I[fid]) {
+        intersected_face_indices.push_back(fid);
+      }
+    }
+
+    const size_t num_intersected_faces = intersected_face_indices.size();
+    std::vector<int> intersected_face_signed_indices(num_intersected_faces);
+    std::transform(
+        intersected_face_indices.begin(),
+        intersected_face_indices.end(),
+        intersected_face_signed_indices.begin(),
+        [&](size_t index) {
+        return index_to_signed_index(
+          index, get_orientation(index, s,d));
+        });
+
+    assert(num_intersected_faces >= 1);
+    if (num_intersected_faces == 1) {
+      // The edge must be a boundary edge.  Thus, the orientation can be
+      // simply determined by checking if the query point is on the
+      // positive side of the facet.
+      const size_t fid = intersected_face_indices[0];
+      orientation = on_the_positive_side(fid, query_point);
+      return fid;
+    }
+
+    Eigen::VectorXi order;
+    DerivedP pivot = P.row(query_idx).eval();
+    igl::copyleft::cgal::order_facets_around_edge(V, F, s, d,
+        intersected_face_signed_indices,
+        pivot, order);
+
+    // Although first and last are equivalent, make the choice based on
+    // preferred_facet.
+    const size_t first = order[0];
+    const size_t last = order[num_intersected_faces-1];
+    if (intersected_face_indices[first] == preferred_facet) {
+      orientation = intersected_face_signed_indices[first] < 0;
+      return intersected_face_indices[first];
+    } else if (intersected_face_indices[last] == preferred_facet) {
+      orientation = intersected_face_signed_indices[last] > 0;
+      return intersected_face_indices[last];
+    } else {
+      orientation = intersected_face_signed_indices[order[0]] < 0;
+      return intersected_face_indices[order[0]];
+    }
+  };
+
+  auto process_face_case = [&](
+      const size_t query_idx, const Point_3& closest_point,
+      const size_t fid, bool& orientation) -> size_t {
+    const auto& f = F.row(I(fid, 0));
+    return process_edge_case(query_idx, f[0], f[1], I(fid, 0), orientation);
+  };
+
+  // Given that the closest point to query point P(query_idx,:) on (V,F(I,:))
+  // is the vertex at V(s,:) which is incident at least on triangle
+  // F(preferred_facet,:), determine a facet incident on V(s,:) that is
+  // _exposed_ to the query point and determine whether that facet is facing
+  // _toward_ or _away_ from the query point.
+  //
+  // Inputs:
+  //   query_idx  index into P of query point
+  //   s  index into V of closest point at vertex
+  //   preferred_facet  facet incident on s
+  // Outputs:
+  //   orientation  whether returned face is facing toward or away from
+  //     query (parity unclear)
+  // Returns face guaranteed to be "exposed" to P(query_idx,:)
+  auto process_vertex_case = [&](
+    const size_t query_idx, 
+    size_t s,
+    size_t preferred_facet, 
+    bool& orientation) -> size_t
+  {
+    const Point_3 query_point(
+        P(query_idx, 0), P(query_idx, 1), P(query_idx, 2));
+    const Point_3 closest_point(V(s, 0), V(s, 1), V(s, 2));
+    std::vector<size_t> adj_faces;
+    std::vector<size_t> adj_face_corners;
+    {
+      // Gather adj faces to s within I.
+      const auto& all_adj_faces = VF[s];
+      const auto& all_adj_face_corners = VFi[s];
+      const size_t num_all_adj_faces = all_adj_faces.size();
+      for (size_t i=0; i<num_all_adj_faces; i++) 
+      {
+        const size_t fid = all_adj_faces[i];
+        // Shouldn't this always be true if I is a full connected component?
+        if (in_I[fid]) 
+        {
+          adj_faces.push_back(fid);
+          adj_face_corners.push_back(all_adj_face_corners[i]);
+        }
+      }
+    }
+    const size_t num_adj_faces = adj_faces.size();
+    assert(num_adj_faces > 0);
+
+    std::set<size_t> adj_vertices_set;
+    std::unordered_multimap<size_t, size_t> v2f;
+    for (size_t i=0; i<num_adj_faces; i++) 
+    {
+      const size_t fid = adj_faces[i];
+      const size_t cid = adj_face_corners[i];
+      const auto& f = F.row(adj_faces[i]);
+      const size_t next = f[(cid+1)%3];
+      const size_t prev = f[(cid+2)%3];
+      adj_vertices_set.insert(next);
+      adj_vertices_set.insert(prev);
+      v2f.insert({{next, fid}, {prev, fid}});
+    }
+    const size_t num_adj_vertices = adj_vertices_set.size();
+    std::vector<size_t> adj_vertices(num_adj_vertices);
+    std::copy(adj_vertices_set.begin(), adj_vertices_set.end(),
+        adj_vertices.begin());
+
+    std::vector<Point_3> adj_points;
+    for (size_t vid : adj_vertices) 
+    {
+      adj_points.emplace_back(V(vid,0), V(vid,1), V(vid,2));
+    }
+
+    // A plane is on the exterior if all adj_points lies on or to
+    // one side of the plane.
+    auto is_on_exterior = [&](const Plane_3& separator) -> bool{
+      size_t positive=0;
+      size_t negative=0;
+      size_t coplanar=0;
+      for (const auto& point : adj_points) {
+        switch(separator.oriented_side(point)) {
+          case CGAL::ON_POSITIVE_SIDE:
+            positive++;
+            break;
+          case CGAL::ON_NEGATIVE_SIDE:
+            negative++;
+            break;
+          case CGAL::ON_ORIENTED_BOUNDARY:
+            coplanar++;
+            break;
+          default:
+            throw "Unknown plane-point orientation";
+        }
+      }
+      auto query_orientation = separator.oriented_side(query_point);
+      if (query_orientation == CGAL::ON_ORIENTED_BOUNDARY &&
+          (positive == 0 && negative == 0)) {
+        // All adj vertices and query point are coplanar.
+        // In this case, all separators are equally valid.
+        return true;
+      } else {
+        bool r = (positive == 0 && query_orientation == CGAL::POSITIVE)
+          || (negative == 0 && query_orientation == CGAL::NEGATIVE);
+        return r;
+      }
+    };
+
+    size_t d = std::numeric_limits<size_t>::max();
+    for (size_t i=0; i<num_adj_vertices; i++) {
+      const size_t vi = adj_vertices[i];
+      for (size_t j=i+1; j<num_adj_vertices; j++) {
+        Plane_3 separator(closest_point, adj_points[i], adj_points[j]);
+        if (separator.is_degenerate()) {
+          continue;
+        }
+        if (is_on_exterior(separator)) {
+          if (!CGAL::collinear(
+                query_point, adj_points[i], closest_point)) {
+            d = vi;
+            break;
+          } else {
+            d = adj_vertices[j];
+            assert(!CGAL::collinear(
+                  query_point, adj_points[j], closest_point));
+            break;
+          }
+        }
+      }
+    }
+    if (d == std::numeric_limits<size_t>::max()) {
+      Eigen::MatrixXd tmp_vertices(V.rows(), V.cols());
+      for (size_t i=0; i<V.rows(); i++) {
+        for (size_t j=0; j<V.cols(); j++) {
+          tmp_vertices(i,j) = CGAL::to_double(V(i,j));
+        }
+      }
+      Eigen::MatrixXi tmp_faces(adj_faces.size(), 3);
+      for (size_t i=0; i<adj_faces.size(); i++) {
+        tmp_faces.row(i) = F.row(adj_faces[i]);
+      }
+      igl::writePLY("debug.ply", tmp_vertices, tmp_faces, false);
+      throw std::runtime_error("Invalid vertex neighborhood");
+    }
+    const auto itr = v2f.equal_range(d);
+    assert(itr.first != itr.second);
+
+    return process_edge_case(query_idx, s, d, itr.first->second, orientation);
+  };
+
+  const size_t num_queries = P.rows();
+  R.resize(num_queries, 1);
+  S.resize(num_queries, 1);
+  for (size_t i=0; i<num_queries; i++) {
+    const Point_3 query(P(i,0), P(i,1), P(i,2));
+    auto projection = tree.closest_point_and_primitive(query);
+    const Point_3 closest_point = projection.first;
+    size_t fid = projection.second - triangles.begin();
+    bool fid_ori = false;
+
+    // Gether all facets sharing the closest point.
+    std::vector<Tree::Primitive_id> intersected_faces;
+    tree.all_intersected_primitives(Segment_3(closest_point, query),
+        std::back_inserter(intersected_faces));
+    const size_t num_intersected_faces = intersected_faces.size();
+    std::vector<size_t> intersected_face_indices(num_intersected_faces);
+    std::transform(intersected_faces.begin(),
+        intersected_faces.end(),
+        intersected_face_indices.begin(),
+        [&](const Tree::Primitive_id& itr) -> size_t
+        { return I(itr-triangles.begin(), 0); });
+
+    size_t element_index;
+    auto element_type = determine_element_type(closest_point, fid,
+        element_index);
+    switch(element_type) {
+      case VERTEX:
+        {
+          const auto& f = F.row(I(fid, 0));
+          const size_t s = f[element_index];
+          fid = process_vertex_case(i, s, I(fid, 0), fid_ori);
+        }
+        break;
+      case EDGE:
+        {
+          const auto& f = F.row(I(fid, 0));
+          const size_t s = f[(element_index+1)%3];
+          const size_t d = f[(element_index+2)%3];
+          fid = process_edge_case(i, s, d, I(fid, 0), fid_ori);
+        }
+        break;
+      case FACE:
+        {
+          fid = process_face_case(i, closest_point, fid, fid_ori);
+        }
+        break;
+      default:
+        throw std::runtime_error("Unknown element type.");
+    }
+
+
+    R(i,0) = fid;
+    S(i,0) = fid_ori;
+  }
+}
+
+template<
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedP,
+  typename uE2EType,
+  typename DerivedEMAP,
+  typename DerivedR,
+  typename DerivedS >
+IGL_INLINE void igl::copyleft::cgal::closest_facet(
+    const Eigen::PlainObjectBase<DerivedV>& V,
+    const Eigen::PlainObjectBase<DerivedF>& F,
+    const Eigen::PlainObjectBase<DerivedP>& P,
+    const std::vector<std::vector<uE2EType> >& uE2E,
+    const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
+    Eigen::PlainObjectBase<DerivedR>& R,
+    Eigen::PlainObjectBase<DerivedS>& S) {
+  const size_t num_faces = F.rows();
+  Eigen::VectorXi I(num_faces);
+  I.setLinSpaced(num_faces, 0, num_faces-1);
+  igl::copyleft::cgal::closest_facet(V, F, I, P, uE2E, EMAP, R, S);
+}
+
+#ifdef IGL_STATIC_LIBRARY
+template void igl::copyleft::cgal::closest_facet<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1>, unsigned long, 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<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+#endif

+ 76 - 0
include/igl/copyleft/cgal/closest_facet.h

@@ -0,0 +1,76 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Qingnan Zhou <qnzhou@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+//
+#ifndef IGL_COPYLET_CGAL_CLOSEST_FACET_H
+#define IGL_COPYLET_CGAL_CLOSEST_FACET_H
+
+#include "../../igl_inline.h"
+#include <Eigen/Core>
+#include <vector>
+
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // Determine the closest facet for each of the input points.
+      //
+      // Inputs:
+      //   V  #V by 3 array of vertices.
+      //   F  #F by 3 array of faces.
+      //   I  #I list of triangle indices to consider.
+      //   P  #P by 3 array of query points.
+      //
+      // Outputs:
+      //   R  #P list of closest facet indices.
+      //   S  #P list of bools indicating on which side of the closest facet
+      //      each query point lies.
+      template<
+          typename DerivedV,
+          typename DerivedF,
+          typename DerivedI,
+          typename DerivedP,
+          typename uE2EType,
+          typename DerivedEMAP,
+          typename DerivedR,
+          typename DerivedS >
+      IGL_INLINE void closest_facet(
+        const Eigen::PlainObjectBase<DerivedV>& V,
+        const Eigen::PlainObjectBase<DerivedF>& F,
+        const Eigen::PlainObjectBase<DerivedI>& I,
+        const Eigen::PlainObjectBase<DerivedP>& P,
+        const std::vector<std::vector<uE2EType> >& uE2E,
+        const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
+              Eigen::PlainObjectBase<DerivedR>& R,
+              Eigen::PlainObjectBase<DerivedS>& S);
+
+      template<
+          typename DerivedV,
+          typename DerivedF,
+          typename DerivedP,
+          typename uE2EType,
+          typename DerivedEMAP,
+          typename DerivedR,
+          typename DerivedS >
+      IGL_INLINE void closest_facet(
+              const Eigen::PlainObjectBase<DerivedV>& V,
+              const Eigen::PlainObjectBase<DerivedF>& F,
+              const Eigen::PlainObjectBase<DerivedP>& P,
+              const std::vector<std::vector<uE2EType> >& uE2E,
+              const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
+              Eigen::PlainObjectBase<DerivedR>& R,
+              Eigen::PlainObjectBase<DerivedS>& S);
+    }
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#include "closest_facet.cpp"
+#endif
+#endif

+ 8 - 7
include/igl/cgal/complex_to_mesh.cpp → include/igl/copyleft/cgal/complex_to_mesh.cpp

@@ -7,8 +7,8 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "complex_to_mesh.h"
 
-#include <igl/centroid.h>
-#include <igl/remove_unreferenced.h>
+#include "../../centroid.h"
+#include "../../remove_unreferenced.h"
 
 #include <CGAL/Surface_mesh_default_triangulation_3.h>
 #include <CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h>
@@ -16,12 +16,11 @@
 #include <stack>
 
 template <typename Tr, typename DerivedV, typename DerivedF>
-IGL_INLINE bool igl::cgal::complex_to_mesh(
+IGL_INLINE bool igl::copyleft::cgal::complex_to_mesh(
   const CGAL::Complex_2_in_triangulation_3<Tr> & c2t3,
   Eigen::PlainObjectBase<DerivedV> & V, 
   Eigen::PlainObjectBase<DerivedF> & F)
 {
-  using namespace igl;
   using namespace Eigen;
   // CGAL/IO/Complex_2_in_triangulation_3_file_writer.h
   using CGAL::Surface_mesher::number_of_facets_on_surface;
@@ -140,12 +139,14 @@ IGL_INLINE bool igl::cgal::complex_to_mesh(
   }
 
   // CGAL code somehow can end up with unreferenced vertices
-  VectorXi _1;
-  remove_unreferenced( MatrixXd(V), MatrixXi(F), V,F,_1);
+  {
+    VectorXi _1;
+    remove_unreferenced( MatrixXd(V), MatrixXi(F), V,F,_1);
+  }
 
   return success;
 }
 
 #ifdef IGL_STATIC_LIBRARY
-template bool igl::cgal::complex_to_mesh<CGAL::Delaunay_triangulation_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_data_structure_3<CGAL::Surface_mesh_vertex_base_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_vertex_base_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_ds_vertex_base_3<void> > >, CGAL::Delaunay_triangulation_cell_base_with_circumcenter_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Surface_mesh_cell_base_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_cell_base_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_ds_cell_base_3<void> > > >, CGAL::Sequential_tag>, CGAL::Default, CGAL::Default>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(CGAL::Complex_2_in_triangulation_3<CGAL::Delaunay_triangulation_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_data_structure_3<CGAL::Surface_mesh_vertex_base_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_vertex_base_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_ds_vertex_base_3<void> > >, CGAL::Delaunay_triangulation_cell_base_with_circumcenter_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Surface_mesh_cell_base_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_cell_base_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_ds_cell_base_3<void> > > >, CGAL::Sequential_tag>, CGAL::Default, CGAL::Default>, void> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template bool igl::copyleft::cgal::complex_to_mesh<CGAL::Delaunay_triangulation_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_data_structure_3<CGAL::Surface_mesh_vertex_base_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_vertex_base_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_ds_vertex_base_3<void> > >, CGAL::Delaunay_triangulation_cell_base_with_circumcenter_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Surface_mesh_cell_base_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_cell_base_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_ds_cell_base_3<void> > > >, CGAL::Sequential_tag>, CGAL::Default, CGAL::Default>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(CGAL::Complex_2_in_triangulation_3<CGAL::Delaunay_triangulation_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_data_structure_3<CGAL::Surface_mesh_vertex_base_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_vertex_base_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_ds_vertex_base_3<void> > >, CGAL::Delaunay_triangulation_cell_base_with_circumcenter_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Surface_mesh_cell_base_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_cell_base_3<CGAL::Robust_circumcenter_traits_3<CGAL::Epick>, CGAL::Triangulation_ds_cell_base_3<void> > > >, CGAL::Sequential_tag>, CGAL::Default, CGAL::Default>, void> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 #endif

+ 47 - 0
include/igl/copyleft/cgal/complex_to_mesh.h

@@ -0,0 +1,47 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_COPYLEFT_CGAL_COMPLEX_TO_MESH_H
+#define IGL_COPYLEFT_CGAL_COMPLEX_TO_MESH_H
+#include "../../igl_inline.h"
+
+#include <Eigen/Dense>
+#include <CGAL/Complex_2_in_triangulation_3.h>
+
+namespace igl 
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // Templates:
+      //   Tr  CGAL triangulation type, e.g.
+      //     CGAL::Surface_mesh_default_triangulation_3
+      // Inputs
+      //   c2t3  2-complex (surface) living in a 3d triangulation (e.g. result of
+      //     CGAL::make_surface_mesh)
+      // Outputs:
+      //   V  #V by 3 list of vertex positions
+      //   F  #F by 3 list of triangle indices
+      // Returns true iff conversion was successful, failure can ok if CGAL code
+      // can't figure out ordering.
+      //
+      template <typename Tr, typename DerivedV, typename DerivedF>
+      IGL_INLINE bool complex_to_mesh(
+        const CGAL::Complex_2_in_triangulation_3<Tr> & c2t3,
+        Eigen::PlainObjectBase<DerivedV> & V, 
+        Eigen::PlainObjectBase<DerivedF> & F);
+    }
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "complex_to_mesh.cpp"
+#endif
+
+#endif
+

+ 6 - 6
include/igl/cgal/component_inside_component.cpp → include/igl/copyleft/cgal/component_inside_component.cpp

@@ -22,7 +22,7 @@
 #include "points_inside_component.h"
 
 template <typename DerivedV, typename DerivedF, typename DerivedI>
-IGL_INLINE bool igl::cgal::component_inside_component(
+IGL_INLINE bool igl::copyleft::cgal::component_inside_component(
         const Eigen::PlainObjectBase<DerivedV>& V1,
         const Eigen::PlainObjectBase<DerivedF>& F1,
         const Eigen::PlainObjectBase<DerivedI>& I1,
@@ -39,13 +39,13 @@ IGL_INLINE bool igl::cgal::component_inside_component(
             (V1(f[0],1) + V1(f[1],1) + V1(f[2],1))/3.0,
             (V1(f[0],2) + V1(f[1],2) + V1(f[2],2))/3.0);
     Eigen::VectorXi inside;
-    igl::cgal::points_inside_component(V2, F2, I2, query, inside);
+    igl::copyleft::cgal::points_inside_component(V2, F2, I2, query, inside);
     assert(inside.size() == 1);
     return inside[0];
 }
 
 template<typename DerivedV, typename DerivedF>
-IGL_INLINE bool igl::cgal::component_inside_component(
+IGL_INLINE bool igl::copyleft::cgal::component_inside_component(
         const Eigen::PlainObjectBase<DerivedV>& V1,
         const Eigen::PlainObjectBase<DerivedF>& F1,
         const Eigen::PlainObjectBase<DerivedV>& V2,
@@ -56,13 +56,13 @@ IGL_INLINE bool igl::cgal::component_inside_component(
     Eigen::VectorXi I1(F1.rows()), I2(F2.rows());
     I1.setLinSpaced(F1.rows(), 0, F1.rows()-1);
     I2.setLinSpaced(F2.rows(), 0, F2.rows()-1);
-    return igl::cgal::component_inside_component(V1, F1, I1, V2, F2, I2);
+    return igl::copyleft::cgal::component_inside_component(V1, F1, I1, V2, F2, I2);
 }
 
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
-template bool igl::cgal::component_inside_component<
+template bool igl::copyleft::cgal::component_inside_component<
 Eigen::Matrix<double, -1, -1, 0, -1, -1>,
 Eigen::Matrix<   int, -1, -1, 0, -1, -1>,
 Eigen::Matrix<   int, -1, -1, 0, -1, -1> > (
@@ -73,7 +73,7 @@ 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::cgal::component_inside_component<
+template bool igl::copyleft::cgal::component_inside_component<
 Eigen::Matrix<double, -1, -1, 0, -1, -1>,
 Eigen::Matrix<   int, -1, -1, 0, -1, -1> > (
 Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&,

+ 6 - 3
include/igl/cgal/component_inside_component.h → include/igl/copyleft/cgal/component_inside_component.h

@@ -5,14 +5,16 @@
 // 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 COMONENT_INSIDE_COMPONENT
-#define COMONENT_INSIDE_COMPONENT
+#ifndef IGL_COPYLEFT_CGAL_COMONENT_INSIDE_COMPONENT
+#define IGL_COPYLEFT_CGAL_COMONENT_INSIDE_COMPONENT
 
-#include "../igl_inline.h"
+#include "../../igl_inline.h"
 #include <Eigen/Core>
 #include <vector>
 
 namespace igl {
+  namespace copyleft
+  {
     namespace cgal {
 
         // Determine if connected facet component (V1, F1, I1) is inside of
@@ -64,6 +66,7 @@ namespace igl {
                     const Eigen::PlainObjectBase<DerivedV>& V2,
                     const Eigen::PlainObjectBase<DerivedF>& F2);
     }
+  }
 }
 
 #ifndef IGL_STATIC_LIBRARY

+ 556 - 0
include/igl/copyleft/cgal/extract_cells.cpp

@@ -0,0 +1,556 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Qingnan Zhou <qnzhou@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+//
+#include "extract_cells.h"
+#include "../../extract_manifold_patches.h"
+#include "../../facet_components.h"
+#include "../../triangle_triangle_adjacency.h"
+#include "../../unique_edge_map.h"
+#include "../../get_seconds.h"
+#include "closest_facet.h"
+#include "order_facets_around_edge.h"
+#include "outer_facet.h"
+
+#include <vector>
+#include <queue>
+
+//#define EXTRACT_CELLS_DEBUG
+
+template<
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedC >
+IGL_INLINE size_t igl::copyleft::cgal::extract_cells(
+  const Eigen::PlainObjectBase<DerivedV>& V,
+  const Eigen::PlainObjectBase<DerivedF>& F,
+  Eigen::PlainObjectBase<DerivedC>& cells)
+{
+  const size_t num_faces = F.rows();
+  // Construct edge adjacency
+  Eigen::MatrixXi E, uE;
+  Eigen::VectorXi EMAP;
+  std::vector<std::vector<size_t> > uE2E;
+  igl::unique_edge_map(F, E, uE, EMAP, uE2E);
+  // Cluster into manifold patches
+  Eigen::VectorXi P;
+  igl::extract_manifold_patches(F, EMAP, uE2E, P);
+  // Extract cells
+  DerivedC per_patch_cells;
+  const size_t num_cells =
+    igl::copyleft::cgal::extract_cells(V,F,P,E,uE,uE2E,EMAP,per_patch_cells);
+  // Distribute per-patch cell information to each face
+  cells.resize(num_faces, 2);
+  for (size_t i=0; i<num_faces; i++) 
+  {
+    cells.row(i) = per_patch_cells.row(P[i]);
+  }
+  return num_cells;
+}
+
+
+template<
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedP,
+  typename DerivedE,
+  typename DeriveduE,
+  typename uE2EType,
+  typename DerivedEMAP,
+  typename DerivedC >
+IGL_INLINE size_t igl::copyleft::cgal::extract_cells(
+  const Eigen::PlainObjectBase<DerivedV>& V,
+  const Eigen::PlainObjectBase<DerivedF>& F,
+  const Eigen::PlainObjectBase<DerivedP>& P,
+  const Eigen::PlainObjectBase<DerivedE>& E,
+  const Eigen::PlainObjectBase<DeriveduE>& uE,
+  const std::vector<std::vector<uE2EType> >& uE2E,
+  const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
+  Eigen::PlainObjectBase<DerivedC>& cells) 
+{
+#ifdef EXTRACT_CELLS_DEBUG
+  const auto & tictoc = []() -> double
+  {
+    static double t_start = igl::get_seconds();
+    double diff = igl::get_seconds()-t_start;
+    t_start += diff;
+    return diff;
+  };
+  const auto log_time = [&](const std::string& label) -> void {
+    std::cout << "extract_cells." << label << ": "
+      << tictoc() << std::endl;
+  };
+  tictoc();
+#else
+  // no-op
+  const auto log_time = [](const std::string){};
+#endif
+  const size_t num_faces = F.rows();
+  typedef typename DerivedF::Scalar Index;
+  const size_t num_patches = P.maxCoeff()+1;
+
+  // Extract all cells...
+  DerivedC raw_cells;
+  const size_t num_raw_cells =
+    extract_cells_single_component(V,F,P,uE,uE2E,EMAP,raw_cells);
+  log_time("extract_single_component_cells");
+
+  // Compute triangle-triangle adjacency data-structure
+  std::vector<std::vector<std::vector<Index > > > TT,_1;
+  igl::triangle_triangle_adjacency(E, EMAP, uE2E, false, TT, _1);
+  log_time("compute_face_adjacency");
+
+  // Compute connected components of the mesh
+  Eigen::VectorXi C, counts;
+  igl::facet_components(TT, C, counts);
+  log_time("form_components");
+
+  const size_t num_components = counts.size();
+  // components[c] --> list of face indices into F of faces in component c
+  std::vector<std::vector<size_t> > components(num_components);
+  // Loop over all faces
+  for (size_t i=0; i<num_faces; i++) 
+  {
+    components[C[i]].push_back(i);
+  }
+  // Convert vector lists to Eigen lists...
+  std::vector<Eigen::VectorXi> Is(num_components);
+  for (size_t i=0; i<num_components; i++)
+  {
+    Is[i].resize(components[i].size());
+    std::copy(components[i].begin(), components[i].end(),Is[i].data());
+  }
+
+  // Find outer facets, their orientations and cells for each component
+  Eigen::VectorXi outer_facets(num_components);
+  Eigen::VectorXi outer_facet_orientation(num_components);
+  Eigen::VectorXi outer_cells(num_components);
+  for (size_t i=0; i<num_components; i++)
+  {
+    bool flipped;
+    igl::copyleft::cgal::outer_facet(V, F, Is[i], outer_facets[i], flipped);
+    outer_facet_orientation[i] = flipped?1:0;
+    outer_cells[i] = raw_cells(P[outer_facets[i]], outer_facet_orientation[i]);
+  }
+#ifdef EXTRACT_CELLS_DEBUG
+  log_time("outer_facet_per_component");
+#endif
+
+  // Compute barycenter of a triangle in mesh (V,F)
+  //
+  // Inputs:
+  //   fid  index into F
+  // Returns row-vector of barycenter coordinates
+  const auto get_triangle_center = [&V,&F](const size_t fid) 
+  {
+    return ((V.row(F(fid,0))+V.row(F(fid,1))+V.row(F(fid,2)))/3.0).eval();
+  };
+  std::vector<std::vector<size_t> > nested_cells(num_raw_cells);
+  std::vector<std::vector<size_t> > ambient_cells(num_raw_cells);
+  std::vector<std::vector<size_t> > ambient_comps(num_components);
+  // Only bother if there's more than one component
+  if(num_components > 1) 
+  {
+    // construct bounding boxes for each component
+    DerivedV bbox_min(num_components, 3);
+    DerivedV bbox_max(num_components, 3);
+    // Why not just initialize to numeric_limits::min, numeric_limits::max?
+    bbox_min.rowwise() = V.colwise().maxCoeff().eval();
+    bbox_max.rowwise() = V.colwise().minCoeff().eval();
+    // Loop over faces
+    for (size_t i=0; i<num_faces; i++)
+    {
+      // component of this face
+      const auto comp_id = C[i];
+      const auto& f = F.row(i);
+      for (size_t j=0; j<3; j++) 
+      {
+        for(size_t d=0;d<3;d++)
+        {
+          bbox_min(comp_id,d) = std::min(bbox_min(comp_id,d), V(f[j],d));
+          bbox_max(comp_id,d) = std::max(bbox_max(comp_id,d), V(f[j],d));
+        }
+      }
+    }
+    // Return true if box of component ci intersects that of cj
+    const auto bbox_intersects = [&bbox_max,&bbox_min](size_t ci, size_t cj)
+    {
+      return !(
+        bbox_max(ci,0) < bbox_min(cj,0) ||
+        bbox_max(ci,1) < bbox_min(cj,1) ||
+        bbox_max(ci,2) < bbox_min(cj,2) ||
+        bbox_max(cj,0) < bbox_min(ci,0) ||
+        bbox_max(cj,1) < bbox_min(ci,1) ||
+        bbox_max(cj,2) < bbox_min(ci,2));
+    };
+    
+    // Loop over components. This section is O(m²)
+    for (size_t i=0; i<num_components; i++)
+    {
+      // List of components that could overlap with component i
+      std::vector<size_t> candidate_comps;
+      candidate_comps.reserve(num_components);
+      // Loop over components
+      for (size_t j=0; j<num_components; j++) 
+      {
+        if (i == j) continue;
+        if (bbox_intersects(i,j)) candidate_comps.push_back(j);
+      }
+
+      const size_t num_candidate_comps = candidate_comps.size();
+      if (num_candidate_comps == 0) continue;
+
+      // Get query points on each candidate component: barycenter of
+      // outer-facet 
+      DerivedV queries(num_candidate_comps, 3);
+      for (size_t j=0; j<num_candidate_comps; j++)
+      {
+        const size_t index = candidate_comps[j];
+        queries.row(j) = get_triangle_center(outer_facets[index]);
+      }
+
+      // Gather closest facets in ith component to each query point and their
+      // orientations
+      const auto& I = Is[i];
+      Eigen::VectorXi closest_facets, closest_facet_orientations;
+      closest_facet(V, F, I, queries,
+        uE2E, EMAP, closest_facets, closest_facet_orientations);
+      // Loop over all candidates
+      for (size_t j=0; j<num_candidate_comps; j++)
+      {
+        const size_t index = candidate_comps[j];
+        const size_t closest_patch = P[closest_facets[j]];
+        const size_t closest_patch_side = closest_facet_orientations[j] ? 0:1;
+        // The cell id of the closest patch
+        const size_t ambient_cell =
+          raw_cells(closest_patch,closest_patch_side);
+        if (ambient_cell != (size_t)outer_cells[i])
+        {
+          // ---> component index inside component i, because the cell of the
+          // closest facet on i to component index is **not** the same as the
+          // "outer cell" of component i: component index is **not** outside of
+          // component i (therefore it's inside).
+          nested_cells[ambient_cell].push_back(outer_cells[index]);
+          ambient_cells[outer_cells[index]].push_back(ambient_cell);
+          ambient_comps[index].push_back(i);
+        }
+      }
+    }
+  }
+
+#ifdef EXTRACT_CELLS_DEBUG
+    log_time("nested_relationship");
+#endif
+
+    const size_t INVALID = std::numeric_limits<size_t>::max();
+    const size_t INFINITE_CELL = num_raw_cells;
+    std::vector<size_t> embedded_cells(num_raw_cells, INVALID);
+    for (size_t i=0; i<num_components; i++) {
+        const size_t outer_cell = outer_cells[i];
+        const auto& ambient_comps_i = ambient_comps[i];
+        const auto& ambient_cells_i = ambient_cells[outer_cell];
+        const size_t num_ambient_comps = ambient_comps_i.size();
+        assert(num_ambient_comps == ambient_cells_i.size());
+        if (num_ambient_comps > 0) {
+            size_t embedded_comp = INVALID;
+            size_t embedded_cell = INVALID;
+            for (size_t j=0; j<num_ambient_comps; j++) {
+                if (ambient_comps[ambient_comps_i[j]].size() ==
+                        num_ambient_comps-1) {
+                    embedded_comp = ambient_comps_i[j];
+                    embedded_cell = ambient_cells_i[j];
+                    break;
+                }
+            }
+            assert(embedded_comp != INVALID);
+            assert(embedded_cell != INVALID);
+            embedded_cells[outer_cell] = embedded_cell;
+        } else {
+            embedded_cells[outer_cell] = INFINITE_CELL;
+        }
+    }
+    for (size_t i=0; i<num_patches; i++) {
+        if (embedded_cells[raw_cells(i,0)] != INVALID) {
+            raw_cells(i,0) = embedded_cells[raw_cells(i, 0)];
+        }
+        if (embedded_cells[raw_cells(i,1)] != INVALID) {
+            raw_cells(i,1) = embedded_cells[raw_cells(i, 1)];
+        }
+    }
+
+    size_t count = 0;
+    std::vector<size_t> mapped_indices(num_raw_cells+1, INVALID);
+    // Always map infinite cell to index 0.
+    mapped_indices[INFINITE_CELL] = count;
+    count++;
+
+    for (size_t i=0; i<num_patches; i++) {
+        const size_t old_positive_cell_id = raw_cells(i, 0);
+        const size_t old_negative_cell_id = raw_cells(i, 1);
+        size_t positive_cell_id, negative_cell_id;
+        if (mapped_indices[old_positive_cell_id] == INVALID) {
+            mapped_indices[old_positive_cell_id] = count;
+            positive_cell_id = count;
+            count++;
+        } else {
+            positive_cell_id = mapped_indices[old_positive_cell_id];
+        }
+        if (mapped_indices[old_negative_cell_id] == INVALID) {
+            mapped_indices[old_negative_cell_id] = count;
+            negative_cell_id = count;
+            count++;
+        } else {
+            negative_cell_id = mapped_indices[old_negative_cell_id];
+        }
+        raw_cells(i, 0) = positive_cell_id;
+        raw_cells(i, 1) = negative_cell_id;
+    }
+    cells = raw_cells;
+#ifdef EXTRACT_CELLS_DEBUG
+    log_time("finalize");
+#endif
+    return count;
+}
+
+template<
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedP,
+  typename DeriveduE,
+  typename uE2EType,
+  typename DerivedEMAP,
+  typename DerivedC>
+IGL_INLINE size_t igl::copyleft::cgal::extract_cells_single_component(
+  const Eigen::PlainObjectBase<DerivedV>& V,
+  const Eigen::PlainObjectBase<DerivedF>& F,
+  const Eigen::PlainObjectBase<DerivedP>& P,
+  const Eigen::PlainObjectBase<DeriveduE>& uE,
+  const std::vector<std::vector<uE2EType> >& uE2E,
+  const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
+  Eigen::PlainObjectBase<DerivedC>& cells)
+{
+  const size_t num_faces = F.rows();
+  // Input:
+  //   index  index into #F*3 list of undirect edges
+  // Returns index into face
+  const auto edge_index_to_face_index = [&num_faces](size_t index)
+  {
+    return index % num_faces;
+  };
+  // Determine if a face (containing undirected edge {s,d} is consistently
+  // oriented with directed edge {s,d} (or otherwise it is with {d,s})
+  // 
+  // Inputs:
+  //   fid  face index into F
+  //   s  source index of edge
+  //   d  destination index of edge
+  // Returns true if face F(fid,:) is consistent with {s,d}
+  const auto is_consistent = 
+    [&F](const size_t fid, const size_t s, const size_t d) -> bool
+  {
+    if ((size_t)F(fid, 0) == s && (size_t)F(fid, 1) == d) return false;
+    if ((size_t)F(fid, 1) == s && (size_t)F(fid, 2) == d) return false;
+    if ((size_t)F(fid, 2) == s && (size_t)F(fid, 0) == d) return false;
+
+    if ((size_t)F(fid, 0) == d && (size_t)F(fid, 1) == s) return true;
+    if ((size_t)F(fid, 1) == d && (size_t)F(fid, 2) == s) return true;
+    if ((size_t)F(fid, 2) == d && (size_t)F(fid, 0) == s) return true;
+    throw "Invalid face!";
+    return false;
+  };
+
+  const size_t num_unique_edges = uE.rows();
+  const size_t num_patches = P.maxCoeff() + 1;
+
+  // patch_edge_adj[p] --> list {e,f,g,...} such that p is a patch id and
+  //   e,f,g etc. are edge indices into 
+  std::vector<std::vector<size_t> > patch_edge_adj(num_patches);
+  // orders[u] --> J  where u is an index into unique edges uE and J is a
+  //   #adjacent-faces list of face-edge indices into F*3 sorted cyclicaly around
+  //   edge u.
+  std::vector<Eigen::VectorXi> orders(num_unique_edges);
+  // orientations[u] ---> list {f1,f2, ...} where u is an index into unique edges uE
+  //   and points to #adj-facets long list of flags whether faces are oriented
+  //   to point their normals clockwise around edge when looking along the
+  //   edge.
+  std::vector<std::vector<bool> > orientations(num_unique_edges);
+  // Loop over unique edges
+  for (size_t i=0; i<num_unique_edges; i++) 
+  {
+    const size_t s = uE(i,0);
+    const size_t d = uE(i,1);
+    const auto adj_faces = uE2E[i];
+    // If non-manifold (more than two incident faces)
+    if (adj_faces.size() > 2) 
+    {
+      // signed_adj_faces[a] --> sid  where a is an index into adj_faces
+      // (list of face edges on {s,d}) and sid is a signed index for resolve
+      // co-planar duplicates consistently (i.e. using simulation of
+      // simplicity).
+      std::vector<int> signed_adj_faces;
+      for (auto ei : adj_faces)
+      {
+        const size_t fid = edge_index_to_face_index(ei);
+        bool cons = is_consistent(fid, s, d);
+        signed_adj_faces.push_back((fid+1)*(cons ? 1:-1));
+      }
+      {
+        // Sort adjacent faces cyclically around {s,d}
+        auto& order = orders[i];
+        // order[f] will reveal the order of face f in signed_adj_faces
+        order_facets_around_edge(V, F, s, d, signed_adj_faces, order);
+        // Determine if each facet is oriented to point its normal clockwise or
+        // not around the {s,d} (normals are not explicitly computed/used)
+        auto& orientation = orientations[i];
+        orientation.resize(order.size());
+        std::transform(
+          order.data(), 
+          order.data() + order.size(),
+          orientation.begin(), 
+          [&signed_adj_faces](const int i){ return signed_adj_faces[i] > 0;});
+        // re-index order from adjacent faces to full face list. Now order
+        // indexes F directly
+        std::transform(
+          order.data(), 
+          order.data() + order.size(),
+          order.data(), 
+          [&adj_faces](const int index){ return adj_faces[index];});
+      }
+      // loop over adjacent faces, remember that patch is adjacent to this edge
+      for(const auto & ei : adj_faces)
+      {
+        const size_t fid = edge_index_to_face_index(ei);
+        patch_edge_adj[P[fid]].push_back(ei);
+      }
+    }
+  }
+
+  // Initialize all patch-to-cell indices as "invalid" (unlabeled)
+  const int INVALID = std::numeric_limits<int>::max();
+  cells.resize(num_patches, 2);
+  cells.setConstant(INVALID);
+
+  // Given a "seed" patch id, a cell id, and which side of the patch that cell
+  // lies, identify all other patches bounding this cell (and tell them that
+  // they do)
+  //
+  // Inputs:
+  //   seed_patch_id  index into patches
+  //   cell_idx  index into cells
+  //   seed_patch_side   0 or 1 depending on whether cell_idx is on left or
+  //     right side of seed_patch_id 
+  //   cells  #cells by 2 list of current assignment of cells incident on each
+  //     side of a patch
+  // Outputs:
+  //   cells  udpated (see input)
+  // 
+  const auto & peel_cell_bd = 
+    [&P,&patch_edge_adj,&EMAP,&orders,&orientations,&num_faces](
+    const size_t seed_patch_id, 
+    const short seed_patch_side, 
+    const size_t cell_idx,
+    Eigen::PlainObjectBase<DerivedC>& cells)
+  {
+    typedef std::pair<size_t, short> PatchSide;
+    // Initialize a queue of {p,side} patch id and patch side pairs to BFS over
+    // all patches
+    std::queue<PatchSide> Q;
+    Q.emplace(seed_patch_id, seed_patch_side);
+    // assign cell id of seed patch on appropriate side
+    cells(seed_patch_id, seed_patch_side) = cell_idx;
+    while (!Q.empty())
+    {
+      // Pop patch from Q
+      const auto entry = Q.front();
+      Q.pop();
+      const size_t patch_id = entry.first;
+      const short side = entry.second;
+      // face-edges adjacent to patch
+      const auto& adj_edges = patch_edge_adj[patch_id];
+      // Loop over **ALL EDGES IN THE ENTIRE PATCH** not even just the boundary
+      // edges, all edges... O(n)
+      for (const auto& ei : adj_edges)
+      {
+        // unique edge
+        const size_t uei = EMAP[ei];
+        // ordering of face-edges stored at edge
+        const auto& order = orders[uei];
+        // consistent orientation flags at face-edges stored at edge
+        const auto& orientation = orientations[uei];
+        const size_t edge_valance = order.size();
+        // Search for ei's (i.e. patch_id's) place in the ordering: O(#patches)
+        size_t curr_i = 0;
+        for (curr_i=0; curr_i < edge_valance; curr_i++)
+        {
+          if ((size_t)order[curr_i] == ei) break;
+        }
+        assert(curr_i < edge_valance && "Failed to find edge.");
+        // is the starting face consistent?
+        const bool cons = orientation[curr_i];
+        // Look clockwise or counter-clockwise for the next face, depending on
+        // whether looking to left or right side and whether consistently
+        // oriented or not.
+        size_t next;
+        if (side == 0)
+        {
+          next = (cons ? (curr_i + 1) :
+          (curr_i + edge_valance - 1)) % edge_valance;
+        } else {
+          next = (cons ? (curr_i+edge_valance-1) : (curr_i+1))%edge_valance;
+        }
+        // Determine face-edge index of next face
+        const size_t next_ei = order[next];
+        // Determine whether next is consistently oriented
+        const bool next_cons = orientation[next];
+        // Determine patch of next
+        const size_t next_patch_id = P[next_ei % num_faces];
+        // Determine which side of patch cell_idx is on, based on whether the
+        // consistency of next matches the consistency of this patch and which
+        // side of this patch we're on.
+        const short next_patch_side = (next_cons != cons) ?  side:abs(side-1);
+        // If that side of next's patch is not labeled, then label and add to
+        // queue
+        if (cells(next_patch_id, next_patch_side) == INVALID) 
+        {
+          Q.emplace(next_patch_id, next_patch_side);
+          cells(next_patch_id, next_patch_side) = cell_idx;
+        }else 
+        {
+          assert(
+            (size_t)cells(next_patch_id, next_patch_side) == cell_idx && 
+            "Encountered cell assignment inconsistency");
+        }
+      }
+    }
+  };
+
+  size_t count=0;
+  // Loop over all patches
+  for (size_t i=0; i<num_patches; i++)
+  {
+    // If left side of patch is still unlabeled, create a new cell and find all
+    // patches also on its boundary
+    if (cells(i, 0) == INVALID)
+    {
+      peel_cell_bd(i, 0, count,cells);
+      count++;
+    }
+    // Likewise for right side
+    if (cells(i, 1) == INVALID)
+    {
+      peel_cell_bd(i, 1, count,cells);
+      count++;
+    }
+  }
+  return count;
+}
+
+
+#ifdef IGL_STATIC_LIBRARY
+#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+template unsigned long igl::copyleft::cgal::extract_cells<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, unsigned long, 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, -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&, 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> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+#endif

+ 115 - 0
include/igl/copyleft/cgal/extract_cells.h

@@ -0,0 +1,115 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Qingnan Zhou <qnzhou@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+//
+#ifndef IGL_COPYLEFT_CGAL_EXTRACT_CELLS
+#define IGL_COPYLEFT_CGAL_EXTRACT_CELLS
+
+#include "../../igl_inline.h"
+#include <Eigen/Core>
+#include <vector>
+
+namespace igl {
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // Extract connected 3D space partitioned by mesh (V, F).
+      //
+      // Inputs:
+      //   V  #V by 3 array of vertices.
+      //   F  #F by 3 array of faces.
+      //
+      // Output:
+      //   cells  #F by 2 array of cell indices.  cells(i,0) represents the
+      //          cell index on the positive side of face i, and cells(i,1)
+      //          represents cell index of the negqtive side.
+      //          By convension cell with index 0 is the infinite cell.
+      template<
+        typename DerivedV,
+        typename DerivedF,
+        typename DerivedC >
+      IGL_INLINE size_t extract_cells(
+        const Eigen::PlainObjectBase<DerivedV>& V,
+        const Eigen::PlainObjectBase<DerivedF>& F,
+        Eigen::PlainObjectBase<DerivedC>& cells);
+
+      // Extract connected 3D space partitioned by mesh (V, F).
+      //
+      // Inputs:
+      //   V  #V by 3 array of vertices.
+      //   F  #F by 3 array of faces.
+      //   P  #F list of patch indices.
+      //   E  #E by 2 array of vertex indices, one edge per row.
+      //  uE    #uE by 2 list of vertex_indices, represents undirected edges.
+      //  uE2E  #uE list of lists that maps uE to E. (a one-to-many map)
+      //  EMAP  #F*3 list of indices into uE.
+      //
+      // Output:
+      //   cells  #P by 2 array of cell indices.  cells(i,0) represents the
+      //          cell index on the positive side of patch i, and cells(i,1)
+      //          represents cell index of the negqtive side.
+      //          By convension cell with index 0 is the infinite cell.
+      template<
+        typename DerivedV,
+        typename DerivedF,
+        typename DerivedP,
+        typename DerivedE,
+        typename DeriveduE,
+        typename uE2EType,
+        typename DerivedEMAP,
+        typename DerivedC >
+      IGL_INLINE size_t extract_cells(
+        const Eigen::PlainObjectBase<DerivedV>& V,
+        const Eigen::PlainObjectBase<DerivedF>& F,
+        const Eigen::PlainObjectBase<DerivedP>& P,
+        const Eigen::PlainObjectBase<DerivedE>& E,
+        const Eigen::PlainObjectBase<DeriveduE>& uE,
+        const std::vector<std::vector<uE2EType> >& uE2E,
+        const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
+        Eigen::PlainObjectBase<DerivedC>& cells);
+
+      // Extract connected 3D space partitioned by mesh (V,F) composed of
+      // **possibly multiple components** (the name of this function is
+      // dubious).
+      //
+      // Inputs:
+      //   V  #V by 3 array of vertices.
+      //   F  #F by 3 array of faces.
+      //   P  #F list of patch indices.
+      //   E  #E by 2 array of vertex indices, one edge per row.
+      //  uE    #uE by 2 list of vertex_indices, represents undirected edges.
+      //  uE2E  #uE list of lists that maps uE to E. (a one-to-many map)
+      //  EMAP  #F*3 list of indices into uE.
+      // Output:
+      //  cells  #P by 2 array of cell indices.  cells(i,0) represents the
+      //    cell index on the positive side of patch i, and cells(i,1)
+      //    represents cell index of the negative side.
+      template<
+        typename DerivedV,
+        typename DerivedF,
+        typename DerivedP,
+        typename DeriveduE,
+        typename uE2EType,
+        typename DerivedEMAP,
+        typename DerivedC >
+      IGL_INLINE size_t extract_cells_single_component(
+        const Eigen::PlainObjectBase<DerivedV>& V,
+        const Eigen::PlainObjectBase<DerivedF>& F,
+        const Eigen::PlainObjectBase<DerivedP>& P,
+        const Eigen::PlainObjectBase<DeriveduE>& uE,
+        const std::vector<std::vector<uE2EType> >& uE2E,
+        const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
+        Eigen::PlainObjectBase<DerivedC>& cells);
+    }
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "extract_cells.cpp"
+#endif
+#endif

+ 273 - 0
include/igl/copyleft/cgal/intersect_other.cpp

@@ -0,0 +1,273 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "intersect_other.h"
+#include "CGAL_includes.hpp"
+#include "mesh_to_cgal_triangle_list.h"
+#include "remesh_intersections.h"
+
+#ifndef IGL_FIRST_HIT_EXCEPTION
+#define IGL_FIRST_HIT_EXCEPTION 10
+#endif
+
+// Un-exposed helper functions
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      template <typename DerivedF>
+      static IGL_INLINE void push_result(
+        const Eigen::PlainObjectBase<DerivedF> & F,
+        const int f,
+        const int f_other,
+        const CGAL::Object & result,
+        std::map<
+          typename DerivedF::Index,
+          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)
+      {
+        typedef typename DerivedF::Index Index;
+        typedef std::pair<Index,Index> EMK;
+        if(offending.count(f) == 0)
+        {
+          // first time marking, initialize with new id and empty list
+          offending[f] = {};
+          for(Index e = 0; e<3;e++)
+          {
+            // 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 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);
+          }
+        }
+        offending[f].push_back({f_other,result});
+      }
+      template <
+        typename Kernel,
+        typename DerivedVA,
+        typename DerivedFA,
+        typename DerivedVB,
+        typename DerivedFB,
+        typename DerivedIF,
+        typename DerivedVVA,
+        typename DerivedFFA,
+        typename DerivedJA,
+        typename DerivedIMA,
+        typename DerivedVVB,
+        typename DerivedFFB,
+        typename DerivedJB,
+        typename DerivedIMB>
+      static IGL_INLINE bool intersect_other_helper(
+        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)
+      {
+
+        using namespace std;
+        using namespace Eigen;
+
+        typedef typename DerivedFA::Index Index;
+        // 3D Primitives
+        typedef CGAL::Point_3<Kernel>    Point_3;
+        typedef CGAL::Segment_3<Kernel>  Segment_3; 
+        typedef CGAL::Triangle_3<Kernel> Triangle_3; 
+        typedef CGAL::Plane_3<Kernel>    Plane_3;
+        typedef CGAL::Tetrahedron_3<Kernel> Tetrahedron_3; 
+        // 2D Primitives
+        typedef CGAL::Point_2<Kernel>    Point_2;
+        typedef CGAL::Segment_2<Kernel>  Segment_2; 
+        typedef CGAL::Triangle_2<Kernel> Triangle_2; 
+        // 2D Constrained Delaunay Triangulation types
+        typedef CGAL::Triangulation_vertex_base_2<Kernel>  TVB_2;
+        typedef CGAL::Constrained_triangulation_face_base_2<Kernel> CTAB_2;
+        typedef CGAL::Triangulation_data_structure_2<TVB_2,CTAB_2> TDS_2;
+        typedef CGAL::Exact_intersections_tag Itag;
+        typedef CGAL::Constrained_Delaunay_triangulation_2<Kernel,TDS_2,Itag> 
+          CDT_2;
+        typedef CGAL::Constrained_triangulation_plus_2<CDT_2> CDT_plus_2;
+        // Axis-align boxes for all-pairs self-intersection detection
+        typedef std::vector<Triangle_3> Triangles;
+        typedef typename Triangles::iterator TrianglesIterator;
+        typedef typename Triangles::const_iterator TrianglesConstIterator;
+        typedef 
+          CGAL::Box_intersection_d::Box_with_handle_d<double,3,TrianglesIterator> 
+          Box;
+        typedef 
+          std::map<Index,std::vector<std::pair<Index,CGAL::Object> > > 
+          OffendingMap;
+        typedef std::map<std::pair<Index,Index>,std::vector<Index> >  EdgeMap;
+        typedef std::pair<Index,Index> EMK;
+
+        Triangles TA,TB;
+        // Compute and process self intersections
+        mesh_to_cgal_triangle_list(VA,FA,TA);
+        mesh_to_cgal_triangle_list(VB,FB,TB);
+        // http://www.cgal.org/Manual/latest/doc_html/cgal_manual/Box_intersection_d/Chapter_main.html#Section_63.5 
+        // Create the corresponding vector of bounding boxes
+        std::vector<Box> A_boxes,B_boxes;
+        const auto box_up = [](Triangles & T, std::vector<Box> & boxes) -> void
+        {
+          boxes.reserve(T.size());
+          for ( 
+            TrianglesIterator tit = T.begin(); 
+            tit != T.end(); 
+            ++tit)
+          {
+            boxes.push_back(Box(tit->bbox(), tit));
+          }
+        };
+        box_up(TA,A_boxes);
+        box_up(TB,B_boxes);
+        OffendingMap offendingA,offendingB;
+        EdgeMap edge2facesA,edge2facesB;
+
+        std::list<int> lIF;
+        const auto cb = [&](const Box &a, const Box &b) -> void
+        {
+          using namespace std;
+          // index in F and T
+          int fa = a.handle()-TA.begin();
+          int fb = b.handle()-TB.begin();
+          const Triangle_3 & A = *a.handle();
+          const Triangle_3 & B = *b.handle();
+          if(CGAL::do_intersect(A,B))
+          {
+            // There was an intersection
+            lIF.push_back(fa);
+            lIF.push_back(fb);
+            if(params.first_only)
+            {
+              throw IGL_FIRST_HIT_EXCEPTION;
+            }
+            if(!params.detect_only)
+            {
+              CGAL::Object result = CGAL::intersection(A,B);
+
+              push_result(FA,fa,fb,result,offendingA,edge2facesA);
+              push_result(FB,fb,fa,result,offendingB,edge2facesB);
+            }
+          }
+        };
+        try{
+          CGAL::box_intersection_d(
+            A_boxes.begin(), A_boxes.end(),
+            B_boxes.begin(), B_boxes.end(),
+            cb);
+        }catch(int e)
+        {
+          // Rethrow if not FIRST_HIT_EXCEPTION
+          if(e != IGL_FIRST_HIT_EXCEPTION)
+          {
+            throw e;
+          }
+          // Otherwise just fall through
+        }
+
+        // Convert lIF to Eigen matrix
+        assert(lIF.size()%2 == 0);
+        IF.resize(lIF.size()/2,2);
+        {
+          int i=0;
+          for(
+            list<int>::const_iterator ifit = lIF.begin();
+            ifit!=lIF.end();
+            )
+          {
+            IF(i,0) = (*ifit);
+            ifit++; 
+            IF(i,1) = (*ifit);
+            ifit++;
+            i++;
+          }
+        }
+        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);
+        }
+
+        return IF.rows() > 0;
+      }
+    }
+  }
+}
+
+template <
+  typename DerivedVA,
+  typename DerivedFA,
+  typename DerivedVB,
+  typename DerivedFB,
+  typename DerivedIF,
+  typename DerivedVVA,
+  typename DerivedFFA,
+  typename DerivedJA,
+  typename DerivedIMA,
+  typename DerivedVVB,
+  typename DerivedFFB,
+  typename DerivedJB,
+  typename DerivedIMB>
+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)
+{
+  if(params.detect_only)
+  {
+    return intersect_other_helper<CGAL::Epick>
+      (VA,FA,VB,FB,params,IF,VVA,FFA,JA,IMA,VVB,FFB,JB,IMB);
+  }else
+  {
+    return intersect_other_helper<CGAL::Epeck>
+      (VA,FA,VB,FB,params,IF,VVA,FFA,JA,IMA,VVB,FFB,JB,IMB);
+  }
+}
+
+IGL_INLINE bool igl::copyleft::cgal::intersect_other(
+  const Eigen::MatrixXd & VA,
+  const Eigen::MatrixXi & FA,
+  const Eigen::MatrixXd & VB,
+  const Eigen::MatrixXi & FB,
+  const bool first_only,
+  Eigen::MatrixXi & IF)
+{
+  Eigen::MatrixXd VVA,VVB;
+  Eigen::MatrixXi FFA,FFB;
+  Eigen::VectorXi JA,JB,IMA,IMB;
+  return intersect_other(
+    VA,FA,VB,FB,{true,first_only},IF,VVA,FFA,JA,IMA,VVB,FFB,JB,IMB);
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template specialization
+#endif

+ 109 - 0
include/igl/copyleft/cgal/intersect_other.h

@@ -0,0 +1,109 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_COPYLEFT_CGAL_INTERSECT_OTHER_H
+#define IGL_COPYLEFT_CGAL_INTERSECT_OTHER_H
+#include "../../igl_inline.h"
+#include "RemeshSelfIntersectionsParam.h"
+
+#include <Eigen/Dense>
+
+#ifdef MEX
+#  include <mex.h>
+#  include <cassert>
+#  undef assert
+#  define assert( isOK ) ( (isOK) ? (void)0 : (void) mexErrMsgTxt(C_STR(__FILE__<<":"<<__LINE__<<": failed assertion `"<<#isOK<<"'"<<std::endl) ) )
+#endif
+
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // INTERSECT_OTHER Given a triangle mesh (VA,FA) and another mesh (VB,FB)
+      // find all pairs of intersecting faces. Note that self-intersections are
+      // ignored.
+      // 
+      // Inputs:
+      //   VA  #V by 3 list of vertex positions
+      //   FA  #F by 3 list of triangle indices into VA
+      //   VB  #V by 3 list of vertex positions
+      //   FB  #F by 3 list of triangle indices into VB
+      //   params   whether to detect only and then whether to only find first
+      //     intersection
+      // Outputs:
+      //   IF  #intersecting face pairs by 2 list of intersecting face pairs,
+      //     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.
+      template <
+        typename DerivedVA,
+        typename DerivedFA,
+        typename DerivedVB,
+        typename DerivedFB,
+        typename DerivedIF,
+        typename DerivedVVA,
+        typename DerivedFFA,
+        typename DerivedJA,
+        typename DerivedIMA,
+        typename DerivedVVB,
+        typename DerivedFFB,
+        typename DerivedJB,
+        typename DerivedIMB>
+      IGL_INLINE bool 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);
+      // Legacy wrapper for detect only using common types.
+      //
+      // Inputs:
+      //   VA  #V by 3 list of vertex positions
+      //   FA  #F by 3 list of triangle indices into VA
+      //   VB  #V by 3 list of vertex positions
+      //   FB  #F by 3 list of triangle indices into VB
+      //   first_only  whether to only detect the first intersection.
+      // Outputs:
+      //   IF  #intersecting face pairs by 2 list of intersecting face pairs,
+      //     indexing FA and FB
+      // Returns true if any intersections were found
+      //
+      // See also: remesh_self_intersections
+      IGL_INLINE bool intersect_other(
+        const Eigen::MatrixXd & VA,
+        const Eigen::MatrixXi & FA,
+        const Eigen::MatrixXd & VB,
+        const Eigen::MatrixXi & FB,
+        const bool first_only,
+        Eigen::MatrixXi & IF);
+    }
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "intersect_other.cpp"
+#endif
+  
+#endif
+

+ 65 - 0
include/igl/copyleft/cgal/mesh_to_cgal_triangle_list.cpp

@@ -0,0 +1,65 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "mesh_to_cgal_triangle_list.h"
+#include "assign_scalar.h"
+
+#include <cassert>
+
+template <
+  typename DerivedV,
+  typename DerivedF,
+  typename Kernel>
+IGL_INLINE void igl::copyleft::cgal::mesh_to_cgal_triangle_list(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::PlainObjectBase<DerivedF> & F,
+  std::vector<CGAL::Triangle_3<Kernel> > & T)
+{
+  typedef CGAL::Point_3<Kernel>    Point_3;
+  typedef CGAL::Triangle_3<Kernel> Triangle_3; 
+  // Must be 3D
+  assert(V.cols() == 3);
+  // **Copy** to convert to output type (this is especially/only needed if the
+  // input type DerivedV::Scalar is CGAL::Epeck
+  Eigen::Matrix<
+    typename Kernel::FT,
+    DerivedV::RowsAtCompileTime,
+    DerivedV::ColsAtCompileTime> 
+    KV(V.rows(),V.cols());
+  // Just use f'ing for loops. What if V and KV don't use same ordering?
+  for(int i = 0;i<V.rows();i++)
+  {
+    for(int j = 0;j<V.cols();j++)
+    {
+      assign_scalar(V(i,j),KV(i,j));
+    }
+  }
+  // Must be triangles
+  assert(F.cols() == 3);
+  T.reserve(F.rows());
+  // Loop over faces
+  for(int f = 0;f<(int)F.rows();f++)
+  {
+    T.push_back(
+      Triangle_3(
+        Point_3( KV(F(f,0),0), KV(F(f,0),1), KV(F(f,0),2)),
+        Point_3( KV(F(f,1),0), KV(F(f,1),1), KV(F(f,1),2)),
+        Point_3( KV(F(f,2),0), KV(F(f,2),1), KV(F(f,2),2))));
+  }
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template specialization
+template void igl::copyleft::cgal::mesh_to_cgal_triangle_list<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epeck>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epeck>, std::allocator<CGAL::Triangle_3<CGAL::Epeck> > >&);
+template void igl::copyleft::cgal::mesh_to_cgal_triangle_list<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epick>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > >&);
+template void igl::copyleft::cgal::mesh_to_cgal_triangle_list<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epeck>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<CGAL::Triangle_3<CGAL::Epeck>, std::allocator<CGAL::Triangle_3<CGAL::Epeck> > >&);
+template void igl::copyleft::cgal::mesh_to_cgal_triangle_list<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epick>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > >&);
+template void igl::copyleft::cgal::mesh_to_cgal_triangle_list<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epeck>(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epeck>, std::allocator<CGAL::Triangle_3<CGAL::Epeck> > >&);
+template void igl::copyleft::cgal::mesh_to_cgal_triangle_list<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epick>(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > >&);
+template void igl::copyleft::cgal::mesh_to_cgal_triangle_list<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epick>(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::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > >&);
+template void igl::copyleft::cgal::mesh_to_cgal_triangle_list<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epeck>(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::vector<CGAL::Triangle_3<CGAL::Epeck>, std::allocator<CGAL::Triangle_3<CGAL::Epeck> > >&);
+#endif

+ 44 - 0
include/igl/copyleft/cgal/mesh_to_cgal_triangle_list.h

@@ -0,0 +1,44 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_COPYLEFT_CGAL_MESH_TO_CGAL_TRIANGLE_LIST_H
+#define IGL_COPYLEFT_CGAL_MESH_TO_CGAL_TRIANGLE_LIST_H
+#include "../../igl_inline.h"
+#include <Eigen/Core>
+#include "CGAL_includes.hpp"
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // Convert a mesh (V,F) to a list of CGAL triangles
+      //
+      // Templates:
+      //   Kernal  CGAL computation and construction kernel (e.g.
+      //     CGAL::Exact_predicates_exact_constructions_kernel)
+      // Inputs:
+      //   V  #V by 3 list of vertex positions
+      //   F  #F by 3 list of triangle indices
+      // Outputs:
+      //   T  #F list of CGAL triangles
+      template <
+        typename DerivedV,
+        typename DerivedF,
+        typename Kernel>
+      IGL_INLINE void mesh_to_cgal_triangle_list(
+        const Eigen::PlainObjectBase<DerivedV> & V,
+        const Eigen::PlainObjectBase<DerivedF> & F,
+        std::vector<CGAL::Triangle_3<Kernel> > & T);
+    }
+  }
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "mesh_to_cgal_triangle_list.cpp"
+#endif
+
+#endif

+ 2 - 2
include/igl/cgal/mesh_to_polyhedron.cpp → include/igl/copyleft/cgal/mesh_to_polyhedron.cpp

@@ -11,7 +11,7 @@
 
 
 template <typename Polyhedron>
-IGL_INLINE bool igl::cgal::mesh_to_polyhedron(
+IGL_INLINE bool igl::copyleft::cgal::mesh_to_polyhedron(
   const Eigen::MatrixXd & V,
   const Eigen::MatrixXi & F,
   Polyhedron & poly)
@@ -50,5 +50,5 @@ IGL_INLINE bool igl::cgal::mesh_to_polyhedron(
 // Explicit template specialization
 #include <CGAL/Simple_cartesian.h>
 #include <CGAL/Polyhedron_items_with_id_3.h>
-template bool igl::cgal::mesh_to_polyhedron<CGAL::Polyhedron_3<CGAL::Simple_cartesian<double>, CGAL::Polyhedron_items_with_id_3, CGAL::HalfedgeDS_default, std::allocator<int> > >(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, CGAL::Polyhedron_3<CGAL::Simple_cartesian<double>, CGAL::Polyhedron_items_with_id_3, CGAL::HalfedgeDS_default, std::allocator<int> >&);
+template bool igl::copyleft::cgal::mesh_to_polyhedron<CGAL::Polyhedron_3<CGAL::Simple_cartesian<double>, CGAL::Polyhedron_items_with_id_3, CGAL::HalfedgeDS_default, std::allocator<int> > >(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, CGAL::Polyhedron_3<CGAL::Simple_cartesian<double>, CGAL::Polyhedron_items_with_id_3, CGAL::HalfedgeDS_default, std::allocator<int> >&);
 #endif

+ 42 - 0
include/igl/copyleft/cgal/mesh_to_polyhedron.h

@@ -0,0 +1,42 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_COPYLEFT_CGAL_MESH_TO_POLYHEDRON_H
+#define IGL_COPYLEFT_CGAL_MESH_TO_POLYHEDRON_H
+#include "../../igl_inline.h"
+#include <Eigen/Core>
+
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // Convert a mesh (V,F) to a CGAL Polyhedron
+      //
+      // Templates:
+      //   Polyhedron  CGAL Polyhedron type (e.g. Polyhedron_3)
+      // Inputs:
+      //   V  #V by 3 list of vertex positions
+      //   F  #F by 3 list of triangle indices
+      // Outputs:
+      //   poly  cgal polyhedron
+      // Returns true only if (V,F) can be converted to a valid polyhedron (i.e. if
+      // (V,F) is vertex and edge manifold).
+      template <typename Polyhedron>
+      IGL_INLINE bool mesh_to_polyhedron(
+        const Eigen::MatrixXd & V,
+        const Eigen::MatrixXi & F,
+        Polyhedron & poly);
+    }
+  }
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "mesh_to_polyhedron.cpp"
+#endif
+
+#endif

+ 406 - 0
include/igl/copyleft/cgal/order_facets_around_edge.cpp

@@ -0,0 +1,406 @@
+#include "order_facets_around_edge.h"
+#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+
+#include <stdexcept>
+
+// adj_faces contains signed index starting from +- 1.
+template<
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedI >
+void igl::copyleft::cgal::order_facets_around_edge(
+    const Eigen::PlainObjectBase<DerivedV>& V,
+    const Eigen::PlainObjectBase<DerivedF>& F,
+    size_t s,
+    size_t d, 
+    const std::vector<int>& adj_faces,
+    Eigen::PlainObjectBase<DerivedI>& order, bool debug)
+{
+  // Although we only need exact predicates in the algorithm,
+  // exact constructions are needed to avoid degeneracies due to
+  // casting to double.
+  typedef CGAL::Exact_predicates_exact_constructions_kernel K;
+  typedef K::Point_3 Point_3;
+  typedef K::Plane_3 Plane_3;
+
+  auto get_face_index = [&](int adj_f)->size_t
+  {
+    return abs(adj_f) - 1;
+  };
+
+  auto get_opposite_vertex = [&](size_t fid)->size_t
+  {
+    typedef typename DerivedF::Scalar Index;
+    if (F(fid, 0) != (Index)s && F(fid, 0) != (Index)d) return F(fid, 0);
+    if (F(fid, 1) != (Index)s && F(fid, 1) != (Index)d) return F(fid, 1);
+    if (F(fid, 2) != (Index)s && F(fid, 2) != (Index)d) return F(fid, 2);
+    assert(false);
+    return -1;
+  };
+
+  // Handle base cases
+  if (adj_faces.size() == 0) 
+  {
+    order.resize(0, 1);
+    return;
+  } else if (adj_faces.size() == 1)
+  {
+    order.resize(1, 1);
+    order(0, 0) = 0;
+    return;
+  } else if (adj_faces.size() == 2)
+  {
+    const size_t o1 = get_opposite_vertex(get_face_index(adj_faces[0]));
+    const size_t o2 = get_opposite_vertex(get_face_index(adj_faces[1]));
+    const Point_3 ps(V(s, 0), V(s, 1), V(s, 2));
+    const Point_3 pd(V(d, 0), V(d, 1), V(d, 2));
+    const Point_3 p1(V(o1, 0), V(o1, 1), V(o1, 2));
+    const Point_3 p2(V(o2, 0), V(o2, 1), V(o2, 2));
+    order.resize(2, 1);
+    switch (CGAL::orientation(ps, pd, p1, p2))
+    {
+      case CGAL::POSITIVE:
+        order(0, 0) = 1;
+        order(1, 0) = 0;
+        break;
+      case CGAL::NEGATIVE:
+        order(0, 0) = 0;
+        order(1, 0) = 1;
+        break;
+      case CGAL::COPLANAR:
+        {
+          switch (CGAL::coplanar_orientation(ps, pd, p1, p2)) {
+            case CGAL::POSITIVE:
+              // Duplicated face, use index to break tie.
+              order(0, 0) = adj_faces[0] < adj_faces[1] ? 0:1;
+              order(1, 0) = adj_faces[0] < adj_faces[1] ? 1:0;
+              break;
+            case CGAL::NEGATIVE:
+              // Coplanar faces, one on each side of the edge.
+              // It is equally valid to order them (0, 1) or (1, 0).
+              // I cannot think of any reason to prefer one to the
+              // other.  So just use (0, 1) ordering by default.
+              order(0, 0) = 0;
+              order(1, 0) = 1;
+              break;
+            case CGAL::COLLINEAR:
+              std::cerr << "Degenerated triangle detected." <<
+                std::endl;
+              assert(false);
+              break;
+            default:
+              assert(false);
+          }
+        }
+        break;
+      default:
+        assert(false);
+    }
+    return;
+  }
+
+  const size_t num_adj_faces = adj_faces.size();
+  const size_t o = get_opposite_vertex( get_face_index(adj_faces[0]));
+  const Point_3 p_s(V(s, 0), V(s, 1), V(s, 2));
+  const Point_3 p_d(V(d, 0), V(d, 1), V(d, 2));
+  const Point_3 p_o(V(o, 0), V(o, 1), V(o, 2));
+  const Plane_3 separator(p_s, p_d, p_o);
+  if (separator.is_degenerate()) {
+    throw std::runtime_error(
+        "Cannot order facets around edge due to degenerated facets");
+  }
+
+  std::vector<Point_3> opposite_vertices;
+  for (size_t i=0; i<num_adj_faces; i++)
+  {
+    const size_t o = get_opposite_vertex( get_face_index(adj_faces[i]));
+    opposite_vertices.emplace_back(
+        V(o, 0), V(o, 1), V(o, 2));
+  }
+
+  std::vector<int> positive_side;
+  std::vector<int> negative_side;
+  std::vector<int> tie_positive_oriented;
+  std::vector<int> tie_negative_oriented;
+
+  std::vector<size_t> positive_side_index;
+  std::vector<size_t> negative_side_index;
+  std::vector<size_t> tie_positive_oriented_index;
+  std::vector<size_t> tie_negative_oriented_index;
+
+  for (size_t i=0; i<num_adj_faces; i++)
+  {
+    const int f = adj_faces[i];
+    const Point_3& p_a = opposite_vertices[i];
+    auto orientation = separator.oriented_side(p_a);
+    switch (orientation) {
+      case CGAL::ON_POSITIVE_SIDE:
+        positive_side.push_back(f);
+        positive_side_index.push_back(i);
+        break;
+      case CGAL::ON_NEGATIVE_SIDE:
+        negative_side.push_back(f);
+        negative_side_index.push_back(i);
+        break;
+      case CGAL::ON_ORIENTED_BOUNDARY:
+        {
+          auto inplane_orientation = CGAL::coplanar_orientation(
+              p_s, p_d, p_o, p_a);
+          switch (inplane_orientation) {
+            case CGAL::POSITIVE:
+              tie_positive_oriented.push_back(f);
+              tie_positive_oriented_index.push_back(i);
+              break;
+            case CGAL::NEGATIVE:
+              tie_negative_oriented.push_back(f);
+              tie_negative_oriented_index.push_back(i);
+              break;
+            case CGAL::COLLINEAR:
+            default:
+              throw std::runtime_error(
+                  "Degenerated facet detected.");
+              break;
+          }
+        }
+        break;
+      default:
+        // Should not be here.
+        throw std::runtime_error("Unknown CGAL state detected.");
+    }
+  }
+  if (debug) {
+    std::cout << "tie positive: " << std::endl;
+    for (auto& f : tie_positive_oriented) {
+      std::cout << get_face_index(f) << " ";
+    }
+    std::cout << std::endl;
+    std::cout << "positive side: " << std::endl;
+    for (auto& f : positive_side) {
+      std::cout << get_face_index(f) << " ";
+    }
+    std::cout << std::endl;
+    std::cout << "tie negative: " << std::endl;
+    for (auto& f : tie_negative_oriented) {
+      std::cout << get_face_index(f) << " ";
+    }
+    std::cout << std::endl;
+    std::cout << "negative side: " << std::endl;
+    for (auto& f : negative_side) {
+      std::cout << get_face_index(f) << " ";
+    }
+    std::cout << std::endl;
+  }
+
+  auto index_sort = [](std::vector<int>& data) -> std::vector<size_t>{
+    const size_t len = data.size();
+    std::vector<size_t> order(len);
+    for (size_t i=0; i<len; i++) { order[i] = i; }
+    auto comp = [&](size_t i, size_t j) { return data[i] < data[j]; };
+    std::sort(order.begin(), order.end(), comp);
+    return order;
+  };
+
+  Eigen::PlainObjectBase<DerivedI> positive_order, negative_order;
+  order_facets_around_edge(V, F, s, d, positive_side, positive_order, debug);
+  order_facets_around_edge(V, F, s, d, negative_side, negative_order, debug);
+  std::vector<size_t> tie_positive_order = index_sort(tie_positive_oriented);
+  std::vector<size_t> tie_negative_order = index_sort(tie_negative_oriented);
+
+  // Copy results into order vector.
+  const size_t tie_positive_size = tie_positive_oriented.size();
+  const size_t tie_negative_size = tie_negative_oriented.size();
+  const size_t positive_size = positive_order.size();
+  const size_t negative_size = negative_order.size();
+
+  order.resize(
+      tie_positive_size + positive_size + tie_negative_size + negative_size,1);
+
+  size_t count=0;
+  for (size_t i=0; i<tie_positive_size; i++)
+  {
+    order(count+i, 0) = tie_positive_oriented_index[tie_positive_order[i]];
+  }
+  count += tie_positive_size;
+
+  for (size_t i=0; i<negative_size; i++) 
+  {
+    order(count+i, 0) = negative_side_index[negative_order(i, 0)];
+  }
+  count += negative_size;
+
+  for (size_t i=0; i<tie_negative_size; i++)
+  {
+    order(count+i, 0) = tie_negative_oriented_index[tie_negative_order[i]];
+  }
+  count += tie_negative_size;
+
+  for (size_t i=0; i<positive_size; i++)
+  {
+    order(count+i, 0) = positive_side_index[positive_order(i, 0)];
+  }
+  count += positive_size;
+  assert(count == num_adj_faces);
+
+  // Find the correct start point.
+  size_t start_idx = 0;
+  for (size_t i=0; i<num_adj_faces; i++)
+  {
+    const Point_3& p_a = opposite_vertices[order(i, 0)];
+    const Point_3& p_b =
+      opposite_vertices[order((i+1)%num_adj_faces, 0)];
+    auto orientation = CGAL::orientation(p_s, p_d, p_a, p_b);
+    if (orientation == CGAL::POSITIVE)
+    {
+      // Angle between triangle (p_s, p_d, p_a) and (p_s, p_d, p_b) is
+      // more than 180 degrees.
+      start_idx = (i+1)%num_adj_faces;
+      break;
+    } else if (orientation == CGAL::COPLANAR &&
+        Plane_3(p_s, p_d, p_a).orthogonal_direction() !=
+        Plane_3(p_s, p_d, p_b).orthogonal_direction())
+    {
+      // All 4 points are coplanar, but p_a and p_b are on each side of
+      // the edge (p_s, p_d).  This means the angle between triangle
+      // (p_s, p_d, p_a) and (p_s, p_d, p_b) is exactly 180 degrees.
+      start_idx = (i+1)%num_adj_faces;
+      break;
+    }
+  }
+  DerivedI circular_order = order;
+  for (size_t i=0; i<num_adj_faces; i++)
+  {
+    order(i, 0) = circular_order((start_idx + i)%num_adj_faces, 0);
+  }
+}
+
+template<
+    typename DerivedV,
+    typename DerivedF,
+    typename DerivedI>
+IGL_INLINE
+void igl::copyleft::cgal::order_facets_around_edge(
+        const Eigen::PlainObjectBase<DerivedV>& V,
+        const Eigen::PlainObjectBase<DerivedF>& F,
+        size_t s,
+        size_t d, 
+        const std::vector<int>& adj_faces,
+        const Eigen::PlainObjectBase<DerivedV>& pivot_point,
+        Eigen::PlainObjectBase<DerivedI>& order)
+{
+
+    assert(V.cols() == 3);
+    assert(F.cols() == 3);
+    assert(pivot_point.cols() == 3);
+    auto signed_index_to_index = [&](int signed_idx)
+    {
+        return abs(signed_idx) -1;
+    };
+    auto get_opposite_vertex_index = [&](size_t fid) -> typename DerivedF::Scalar
+    {
+        typedef typename DerivedF::Scalar Index;
+        if (F(fid, 0) != (Index)s && F(fid, 0) != (Index)d) return F(fid, 0);
+        if (F(fid, 1) != (Index)s && F(fid, 1) != (Index)d) return F(fid, 1);
+        if (F(fid, 2) != (Index)s && F(fid, 2) != (Index)d) return F(fid, 2);
+        assert(false);
+        // avoid warning
+        return -1;
+    };
+
+    {
+        // Check if s, d and pivot are collinear.
+        typedef CGAL::Exact_predicates_exact_constructions_kernel K;
+        K::Point_3 ps(V(s,0), V(s,1), V(s,2));
+        K::Point_3 pd(V(d,0), V(d,1), V(d,2));
+        K::Point_3 pp(pivot_point(0,0), pivot_point(0,1), pivot_point(0,2));
+        if (CGAL::collinear(ps, pd, pp)) {
+            throw std::runtime_error(
+                    "Pivot point is collinear with the outer edge!");
+        }
+    }
+
+    const size_t N = adj_faces.size();
+    const size_t num_faces = N + 1; // N adj faces + 1 pivot face
+
+    // Because face indices are used for tie breaking, the original face indices
+    // in the new faces array must be ascending.
+    auto comp = [&](int i, int j) {
+        return signed_index_to_index(adj_faces[i]) <
+            signed_index_to_index(adj_faces[j]);
+    };
+    std::vector<size_t> adj_order(N);
+    for (size_t i=0; i<N; i++) adj_order[i] = i;
+    std::sort(adj_order.begin(), adj_order.end(), comp);
+
+    DerivedV vertices(num_faces + 2, 3);
+    for (size_t i=0; i<N; i++) {
+        const size_t fid = signed_index_to_index(adj_faces[adj_order[i]]);
+        vertices.row(i) = V.row(get_opposite_vertex_index(fid));
+    }
+    vertices.row(N  ) = pivot_point;
+    vertices.row(N+1) = V.row(s);
+    vertices.row(N+2) = V.row(d);
+
+    DerivedF faces(num_faces, 3);
+    for (size_t i=0; i<N; i++)
+    {
+        if (adj_faces[adj_order[i]] < 0) {
+            faces(i,0) = N+1; // s
+            faces(i,1) = N+2; // d
+            faces(i,2) = i  ;
+        } else {
+            faces(i,0) = N+2; // d
+            faces(i,1) = N+1; // s
+            faces(i,2) = i  ;
+        }
+    }
+    // Last face is the pivot face.
+    faces(N, 0) = N+1;
+    faces(N, 1) = N+2;
+    faces(N, 2) = N;
+
+    std::vector<int> adj_faces_with_pivot(num_faces);
+    for (size_t i=0; i<num_faces; i++)
+    {
+        if ((size_t)faces(i,0) == N+1 && (size_t)faces(i,1) == N+2)
+        {
+            adj_faces_with_pivot[i] = int(i+1) * -1;
+        } else
+        {
+            adj_faces_with_pivot[i] = int(i+1);
+        }
+    }
+
+    DerivedI order_with_pivot;
+    order_facets_around_edge(
+            vertices, faces, N+1, N+2,
+            adj_faces_with_pivot, order_with_pivot);
+
+    assert((size_t)order_with_pivot.size() == num_faces);
+    order.resize(N);
+    size_t pivot_index = num_faces + 1;
+    for (size_t i=0; i<num_faces; i++)
+    {
+        if ((size_t)order_with_pivot[i] == N)
+        {
+            pivot_index = i;
+            break;
+        }
+    }
+    assert(pivot_index < num_faces);
+
+    for (size_t i=0; i<N; i++)
+    {
+        order[i] = adj_order[order_with_pivot[(pivot_index+i+1)%num_faces]];
+    }
+}
+
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template specialization
+template void igl::copyleft::cgal::order_facets_around_edge<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, unsigned long, unsigned long, std::vector<int, std::allocator<int> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, bool);
+template void igl::copyleft::cgal::order_facets_around_edge<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, unsigned long, unsigned long, std::vector<int, std::allocator<int> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, bool);
+template void igl::copyleft::cgal::order_facets_around_edge<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, unsigned long, unsigned long, std::vector<int, std::allocator<int> > 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> >&);
+template void igl::copyleft::cgal::order_facets_around_edge<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, unsigned long, unsigned long, std::vector<int, std::allocator<int> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+template void igl::copyleft::cgal::order_facets_around_edge<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&, unsigned long, unsigned long, std::vector<int, std::allocator<int> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+template void igl::copyleft::cgal::order_facets_around_edge<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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>, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, unsigned long, unsigned long, std::vector<int, std::allocator<int> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+#endif

+ 74 - 0
include/igl/copyleft/cgal/order_facets_around_edge.h

@@ -0,0 +1,74 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Qingnan Zhou <qnzhou@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+//
+#ifndef IGL_COPYLEFT_CGAL_ORDER_FACETS_AROUND_EDGE_H
+#define IGL_COPYLEFT_CGAL_ORDER_FACETS_AROUND_EDGE_H
+#include "../../igl_inline.h"
+#include <Eigen/Core>
+#include <vector>
+
+namespace igl {
+  namespace copyleft
+  {
+    namespace cgal {
+      // Given a directed edge, sort its adjacent faces.  Assuming the
+      // directed edge is (s, d).  Sort the adjacent faces clockwise around the
+      // axis (d - s), i.e. left-hand rule.  An adjacent face is consistently
+      // oriented if it contains (d, s) as a directed edge.
+      //
+      // For overlapping faces, break the tie using signed face index, smaller
+      // signed index comes before the larger signed index.  Signed index is
+      // computed as (consistent? 1:-1) * (face_index + 1).
+      //
+      // Inputs:
+      //   V          #V by 3 list of vertices.
+      //   F          #F by 3 list of faces
+      //   s          Index of source vertex.
+      //   d          Index of desination vertex.
+      //   adj_faces  List of adjacent face signed indices.
+      //
+      // Output:
+      //   order      List of face indices that orders adjacent faces around
+      //              edge (s, d) clockwise.
+      template<
+        typename DerivedV,
+        typename DerivedF,
+        typename DerivedI >
+      IGL_INLINE
+      void order_facets_around_edge(
+          const Eigen::PlainObjectBase<DerivedV>& V,
+          const Eigen::PlainObjectBase<DerivedF>& F,
+          size_t s, size_t d, 
+          const std::vector<int>& adj_faces,
+          Eigen::PlainObjectBase<DerivedI>& order,
+          bool debug=false);
+
+      // This funciton is a wrapper around the one above.  Since the ordering
+      // is circular, the pivot point is used to define a starting point.  So
+      // order[0] is the index into adj_face that is immediately after the
+      // pivot face (s, d, pivot point) in clockwise order.
+      template<
+        typename DerivedV,
+        typename DerivedF,
+        typename DerivedI>
+      IGL_INLINE
+      void order_facets_around_edge(
+          const Eigen::PlainObjectBase<DerivedV>& V,
+          const Eigen::PlainObjectBase<DerivedF>& F,
+          size_t s, size_t d, 
+          const std::vector<int>& adj_faces,
+          const Eigen::PlainObjectBase<DerivedV>& pivot_point,
+          Eigen::PlainObjectBase<DerivedI>& order);
+    }
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#include "order_facets_around_edge.cpp"
+#endif
+#endif

+ 7 - 7
include/igl/cgal/order_facets_around_edges.cpp → include/igl/copyleft/cgal/order_facets_around_edges.cpp

@@ -7,7 +7,7 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "order_facets_around_edges.h"
 #include "order_facets_around_edge.h"
-#include "../sort_angles.h"
+#include "../../sort_angles.h"
 #include <type_traits>
 #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
 
@@ -22,7 +22,7 @@ template<
 IGL_INLINE
 typename std::enable_if<!std::is_same<typename DerivedV::Scalar,
 typename CGAL::Exact_predicates_exact_constructions_kernel::FT>::value, void>::type
-igl::cgal::order_facets_around_edges(
+igl::copyleft::cgal::order_facets_around_edges(
         const Eigen::PlainObjectBase<DerivedV>& V,
         const Eigen::PlainObjectBase<DerivedF>& F,
         const Eigen::PlainObjectBase<DerivedN>& N,
@@ -162,7 +162,7 @@ template<
 IGL_INLINE 
 typename std::enable_if<std::is_same<typename DerivedV::Scalar,
 typename CGAL::Exact_predicates_exact_constructions_kernel::FT>::value, void>::type
-igl::cgal::order_facets_around_edges(
+igl::copyleft::cgal::order_facets_around_edges(
         const Eigen::PlainObjectBase<DerivedV>& V,
         const Eigen::PlainObjectBase<DerivedF>& F,
         const Eigen::PlainObjectBase<DerivedN>& N,
@@ -253,7 +253,7 @@ template<
     typename uE2EType,
     typename uE2oEType,
     typename uE2CType >
-IGL_INLINE void igl::cgal::order_facets_around_edges(
+IGL_INLINE void igl::copyleft::cgal::order_facets_around_edges(
         const Eigen::PlainObjectBase<DerivedV>& V,
         const Eigen::PlainObjectBase<DerivedF>& F,
         const Eigen::PlainObjectBase<DeriveduE>& uE,
@@ -320,7 +320,7 @@ IGL_INLINE void igl::cgal::order_facets_around_edges(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
-template void igl::cgal::order_facets_around_edges<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, long, long, bool>(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> > const&, std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > > const&, std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > >&, std::vector<std::vector<bool, std::allocator<bool> >, std::allocator<std::vector<bool, std::allocator<bool> > > >&);
-template void igl::cgal::order_facets_around_edges<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, long, long, bool>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> > const&, std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > > const&, std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > >&, std::vector<std::vector<bool, std::allocator<bool> >, std::allocator<std::vector<bool, std::allocator<bool> > > >&);
-template void igl::cgal::order_facets_around_edges<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, long, long, bool>(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, 2, 0, -1, 2> > const&, std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > > const&, std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > >&, std::vector<std::vector<bool, std::allocator<bool> >, std::allocator<std::vector<bool, std::allocator<bool> > > >&);
+template void igl::copyleft::cgal::order_facets_around_edges<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, long, long, bool>(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> > const&, std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > > const&, std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > >&, std::vector<std::vector<bool, std::allocator<bool> >, std::allocator<std::vector<bool, std::allocator<bool> > > >&);
+template void igl::copyleft::cgal::order_facets_around_edges<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, long, long, bool>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> > const&, std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > > const&, std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > >&, std::vector<std::vector<bool, std::allocator<bool> >, std::allocator<std::vector<bool, std::allocator<bool> > > >&);
+template void igl::copyleft::cgal::order_facets_around_edges<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, long, long, bool>(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, 2, 0, -1, 2> > const&, std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > > const&, std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > >&, std::vector<std::vector<bool, std::allocator<bool> >, std::allocator<std::vector<bool, std::allocator<bool> > > >&);
 #endif

+ 107 - 0
include/igl/copyleft/cgal/order_facets_around_edges.h

@@ -0,0 +1,107 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_COPYLEFT_CGAL_ORDER_FACETS_AROUND_EDGES_H
+#define IGL_COPYLEFT_CGAL_ORDER_FACETS_AROUND_EDGES_H
+#include "../../igl_inline.h"
+#include <Eigen/Core>
+#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+#include <vector>
+
+namespace igl
+{
+  namespace copyleft
+  {
+    namespace cgal
+    {
+      // For each undirected edge, sort its adjacent faces.  Assuming the
+      // undirected edge is (s, d).  Sort the adjacent faces clockwise around the
+      // axis (d - s), i.e. left-hand rule.  An adjacent face is consistently
+      // oriented if it contains (d, s) as a directed edge.
+      //
+      // For overlapping faces, break the tie using signed face index, smaller
+      // signed index comes before the larger signed index.  Signed index is
+      // computed as (consistent? 1:-1) * index.
+      //
+      // Inputs:
+      //   V    #V by 3 list of vertices.
+      //   F    #F by 3 list of faces
+      //   N    #F by 3 list of face normals.
+      //  uE    #uE by 2 list of vertex_indices, represents undirected edges.
+      //  uE2E  #uE list of lists that maps uE to E. (a one-to-many map)
+      //
+      // Outputs:
+      //   uE2oE #uE list of lists that maps uE to an ordered list of E. (a
+      //         one-to-many map)
+      //   uE2C  #uE list of lists of bools indicates whether each face in
+      //         uE2oE[i] is consistently orientated as the ordering.
+      //
+      template<
+          typename DerivedV,
+          typename DerivedF,
+          typename DerivedN,
+          typename DeriveduE,
+          typename uE2EType,
+          typename uE2oEType,
+          typename uE2CType >
+      IGL_INLINE
+      typename std::enable_if<!std::is_same<typename DerivedV::Scalar,
+      typename CGAL::Exact_predicates_exact_constructions_kernel::FT>::value, void>::type
+      order_facets_around_edges(
+        const Eigen::PlainObjectBase<DerivedV>& V,
+        const Eigen::PlainObjectBase<DerivedF>& F,
+        const Eigen::PlainObjectBase<DerivedN>& N,
+        const Eigen::PlainObjectBase<DeriveduE>& uE,
+        const std::vector<std::vector<uE2EType> >& uE2E,
+        std::vector<std::vector<uE2oEType> >& uE2oE,
+        std::vector<std::vector<uE2CType > >& uE2C );
+
+      template<
+          typename DerivedV,
+          typename DerivedF,
+          typename DerivedN,
+          typename DeriveduE,
+          typename uE2EType,
+          typename uE2oEType,
+          typename uE2CType >
+      IGL_INLINE 
+      typename std::enable_if<std::is_same<typename DerivedV::Scalar,
+      typename CGAL::Exact_predicates_exact_constructions_kernel::FT>::value, void>::type
+      order_facets_around_edges(
+        const Eigen::PlainObjectBase<DerivedV>& V,
+        const Eigen::PlainObjectBase<DerivedF>& F,
+        const Eigen::PlainObjectBase<DerivedN>& N,
+        const Eigen::PlainObjectBase<DeriveduE>& uE,
+        const std::vector<std::vector<uE2EType> >& uE2E,
+        std::vector<std::vector<uE2oEType> >& uE2oE,
+        std::vector<std::vector<uE2CType > >& uE2C );
+
+      // Order faces around each edge. Only exact predicate is used in the algorithm.
+      // Normal is not needed.
+      template<
+          typename DerivedV,
+          typename DerivedF,
+          typename DeriveduE,
+          typename uE2EType,
+          typename uE2oEType,
+          typename uE2CType >
+      IGL_INLINE void order_facets_around_edges(
+        const Eigen::PlainObjectBase<DerivedV>& V,
+        const Eigen::PlainObjectBase<DerivedF>& F,
+        const Eigen::PlainObjectBase<DeriveduE>& uE,
+        const std::vector<std::vector<uE2EType> >& uE2E,
+        std::vector<std::vector<uE2oEType> >& uE2oE,
+        std::vector<std::vector<uE2CType > >& uE2C );
+    }
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#include "order_facets_around_edges.cpp"
+#endif
+
+#endif

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно